问题描述
问题
我正在使用 mingw-w64 GCC 在 Windows 10 Home 上编译和链接 C 程序,构建 1809(我知道这是一个古老的故事)。我想禁用地址空间布局随机化 (ASLR),以便在调试时我的堆地址不会随运行而改变。我该怎么做?
示例程序:
// testaslr.c
#include <stdio.h> // printf
#include <stdlib.h> // malloc
int main()
{
printf("allocation: %p\n",malloc(16));
return 0;
}
编译运行:
$ gcc -o testaslr -g -Wall testaslr.c
$ ./testaslr
allocation: 00000000007A1420
$ ./testaslr
allocation: 0000000000A81420
$ ./testaslr
allocation: 0000000000BF1420
如您所见,malloc
返回的地址每次都会发生变化。我希望它在每次运行时都具有相同的值。
工具链
我正在使用 mingw-w64 x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z。 (我之前使用过 x86_64-5.4.0-release-posix-seh-rt_v5-rev0.7z,并且看到了相同的行为。)
$ gcc --version
gcc.exe (x86_64-posix-seh-rev0,Built by MinGW-W64 project) 8.1.0
[...copyright stuff...]
$ ld --version
GNU ld (GNU Binutils) 2.30
[...copyright stuff...]
虽然我使用的是 cygwin shell 实用程序,但我没有使用 cygwin 编译器或链接器。可执行文件仅与 MSVCRT 以及通常的 Windows 库链接:
$ ldd testaslr.exe
ntdll.dll => /cygdrive/c/WINDOWS/SYstem32/ntdll.dll (0x7fff5ad40000)
KERNEL32.DLL => /cygdrive/c/WINDOWS/System32/KERNEL32.DLL (0x7fff57f60000)
KERNELBASE.dll => /cygdrive/c/WINDOWS/System32/KERNELBASE.dll (0x7fff56fa0000)
msvcrt.dll => /cygdrive/c/WINDOWS/System32/msvcrt.dll (0x7fff5a3b0000)
尝试 1:--disable-dynamicbase
根据binutils documentation,应该有一个选项ld
叫做--disable-dynamicbase
来禁用ASLR。但无法识别:
$ gcc -o testaslr -g -Wall testaslr.c -Wl,--disable-dynamicbase
E:/cygwin/home/Scott/opt/mingw64-8.1.0/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: unrecognized option '--disable-dynamicbase'
E:/cygwin/home/Scott/opt/mingw64-8.1.0/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: use the --help option for usage information
collect2.exe: error: ld returned 1 exit status
同时,-Wl,--dynamicbase
被接受但不会改变行为。
尝试 2:之后清除 DYNAMIC_BASE
我发现了一个名为 setdllcharacteristics 的实用程序,它声称可以清除可执行文件中的 ASLR 标志。然而,运行它似乎表明标志已经是假的:
$ setdllcharacteristics.exe -d testaslr.exe
Original DLLcharacteristics = 0x0000
DYNAMIC_BASE = 0
NX_COMPAT = 0
FORCE_INTEGRITY = 0
Updated DLLcharacteristics = 0x0000
DYNAMIC_BASE = 0
NX_COMPAT = 0
FORCE_INTEGRITY = 0
运行该工具后,每次运行的地址仍然不同。
有趣的是,如果我将 -Wl,--dynamicbase
传递给编译器,那么 setdllcharacteristics
确实 将标志显示为已设置,但清除它后,地址仍然不同每次运行。这使我得出结论,DYNAMIC_BASE
不是造成地址变化的原因。但在那种情况下,即使经过大量谷歌搜索,我也不知道是什么或如何更改它。
未尝试:MoveImages 注册表设置
我知道根据 this blog post 的注册表设置 HKLM\SYstem\CurrentControlSet\Control\Session Manager\Memory Management\MoveImages
可能会禁用 ASLR。但是根据需要重新启动的同一篇博客文章,这很烦人,理想情况下,我只希望我正在调试的一个程序,而不是我的整个系统。鉴于清除 DYNAMIC_BASE
没有。
猜测:MSVCRT 切换?
如果 DYNAMIC_BASE
不是罪魁祸首,那么这可能是 MSVCRT 自己做的事情。我找到了一个 MSDN page that mentions heap randomization。页面的编写方式,我不知道是否由 DYNAMIC_BASE
标志控制,但我的实验似乎表明它不是。文中还说:
在 Windows Vista 及更高版本上运行的所有应用程序默认启用堆随机化。
但没有说明如何禁用它。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)