是否可以相对于 x64dbg 或类似调试器中的内存块设置断点?

逆向工程 记忆 动态分析 断点 x64dbg
2021-06-26 06:31:29

我的一些断点完全可以在多次重启后幸存下来。

但是我正在调试的代码的许多有趣部分在重新启动后在内存中的位置不同。原因似乎是,在重新启动后,代码被加载到不同的内存段中。而且看起来我正在寻找的部分至少绝对定位到它们所在的内存块。

澄清:我怀疑在重新启动期间保持原位的代码是一个静态链接库,而切换位置的代码是主程序本身。这有意义吗?

x64dbg(或类似的调试器)中有没有办法解决这个问题并相对于它们加载到的块设置内存断点?

为什么代码的某些部分总是被加载到同一个块中,而其他部分则被随机加载到一个内存段中?

编辑:还有一种方法可以以某种方式标记相对于内存段定位的常量指针吗?直接识别我在看哪个常量而不是手动重新计算哪个常量与上次启动它相比真的很有帮助。

编辑3:

这里有一个屏幕截图以供澄清: 在此处输入图片说明

您可以看到地址在较低的两个字节上保持不变,但在较高的 2 个字节上根据它们加载到的内存块而有所不同。

1个回答

windows > 大于 vista 实现称为 ASLR(地址空间布局随机化)的安全功能

此功能在每次重新启动时随机更改二进制文件的基地址,以防止依赖于恒定地址的漏洞利用过时

对于 dll,每次启动都会更改基地址

即使地址空间是随机的,也可能会发生冲突,并且二进制文件可能会多次加载到同一个基地址中

假设你有这样的代码

#include <stdio.h>
#include <windows.h>
void main (void) {
    char buff[MAX_PATH] = {0};
    GetModuleFileName(NULL,buff,MAX_PATH);
    printf("%p\t%s\n" , GetModuleHandle(NULL) , buff);
    HMODULE hntdll = GetModuleHandle("kernel32");
    GetModuleFileName(hntdll,buff,MAX_PATH);
    printf("%p\t%s\n" , hntdll , buff);
}

您可以看到二进制文件连续 3 次加载到同一地址,同时第四次更改其基址,您还可以看到 dll 在所有 4 次重新启动时始终加载到同一地址(此地址可能会在重新启动时更改)

C:\Users\printbaseaddr>printbaseaddr.exe
00C80000        C:\Users\printbaseaddr\printbaseaddr.exe
774E0000        C:\Windows\system32\kernel32.dll

C:\Users\printbaseaddr>printbaseaddr.exe
00C80000        C:\Users\printbaseaddr\printbaseaddr.exe
774E0000        C:\Windows\system32\kernel32.dll

C:\Users\printbaseaddr>printbaseaddr.exe
00C80000        C:\Users\printbaseaddr\printbaseaddr.exe
774E0000        C:\Windows\system32\kernel32.dll

C:\Users\printbaseaddr>printbaseaddr.exe
003D0000        C:\Users\printbaseaddr\printbaseaddr.exe  <<<<<<<<<
774E0000        C:\Windows\system32\kernel32.dll

您可以使用任何 pe 文件浏览器查看您的二进制文件是否启用了 ASLR,一种方法是使用 dumpbin /headers 并在 Dll 特征中查找动态基础

C:\Users\printbaseaddr>dumpbin /headers printbaseaddr.exe | grep  Dyna
                   Dynamic base

您可以在文件中修补它以禁用可执行文件的 aslr,您会注意到 exe 始终加载在其首选基础中,对于 exe 通常为 0x400000

:\>fc printbaseaddr.exe printbaseaddrmod.exe
Comparing files printbaseaddr.exe and PRINTBASEADDRMOD.EXE
00000156: 40 00

:\>xxd -s 0x154 -l 10 printbaseaddrmod.exe
0000154: 0300 0081 0000 1000 0010                 ..........

:\>xxd -s 0x154 -l 10 printbaseaddr.exe
0000154: 0300 4081 0000 1000 0010                 ..@.......

:\>echo off
for /L %i in (1,1,10) do printbaseaddrmod.exe
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll
00400000        printbaseaddr\printbaseaddrmod.exe
774E0000        C:\Windows\system32\kernel32.dll