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

评论

阅读有关地址空间布局随机化(又称为aslr)的信息

#1 楼

这可能是由于地址空间布局随机化又称为ASLR(例如,请参见Symantec的此概述)。

系统模块的加载地址在每次引导时都是随机的,而
可执行映像在可以在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