为什么这个函数在我重新启动 windows 时会调用 offset move

逆向工程 拆卸 视窗 部件 登录
2021-06-30 09:36:24

每次我重新启动 Windows 时,它都会破坏我为可执行文件制作的补丁,我在其中从 dll user32.dll 调用了一个函数。目前,函数调用的偏移量位于 0x76E3CDB4,但是当我重新启动计算机时,它将更改为某个其他地址。为什么会这样,我该怎么做才能确保我的汇编代码始终正确调用该函数?

1个回答

这可能是由于地址空间布局随机化又名 ASLR(例如,请参阅赛门铁克的此概述

系统模块的加载地址在每次启动时随机化,可执行映像在 OS > Vista 中的每次执行时随机化

你可以用一些像这样的简单代码来检查

:\>cat aslr.cpp
#include <windows.h>
#include <stdio.h>
void main (void)
{
    HMODULE hMod = LoadLibraryA("user32.dll");
    if(hMod){
        printf("My Load Addr\t%p My user Addr\t%p\n" , &main,hMod);
        FreeLibrary(hMod);
    }
}

编译执行结果如下

:\>for /L %i in (1,1,10) do aslr.exe

:\>aslr.exe
My Load Addr    00121000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    00031000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    00FB1000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    002F1000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    011B1000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    011B1000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    011B1000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    011B1000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    00181000 My user Addr   773A0000

:\>aslr.exe
My Load Addr    01121000 My user Addr   773A0000

为确保正确打补丁,您应该使用 RVA(相对虚拟地址)

即每次获取模块的基础并添加您每次之前确定的固定偏移量

假设您修补了@ 0x12345678,并且当您修补模块时,该模块在 0x10000000 处加载,那么您的差异为 0x2345678

下次如果模块在 0x20000000 加载,你使用地址 0x20000000+0x2345678 == 0x22345678