Windows 中的 ASLR 是如何工作的?

逆向工程 视窗
2021-06-22 11:30:38

我最近遇到了这种情况,在我正在调试的程序中发现:

03CD38D4:  8B15 8C5FF703  MOV EDX, DWORD PTR DS:[3F75F8C]

如果我在物理文件中查找这些字节,我什么也没找到。我认为这是因为对 的引用3F75F8C(可能会在程序的每个实例上发生变化)被 Windows 随机化。因此,我无法直接在十六进制中更改值 - 比如说更改3F75F8C3F75F88(我想我可以通过一些涉及 的数学来做到这一点base)。

  • 有人可以详细解释Windows 在加载 PE 文件以随机化所有这些字节时是如何进行的吗?我已经找到了关于 ASLR 工作原理的帖子和信息,但我更多地考虑了操作系统将文件与随机地址一起放入内存的步骤 - 即它如何从可执行文件“8B15 XXXX”中的实际字节到“8B15 8C5FF703”如我的例子。
  • 操作系统如何知道必须随机化的字节在哪里(哪些确切地址),并及时进行随机化?
  • 如果我NOP完成整个指令,这个操作系统进程会中断吗?(我问是因为我不知道是否有某种预定义的索引表,我只知道PE中有一个标志来标记ASLR)

编辑

根据答案,我不明白的是,Windows 将查看该.reloc部分,并会根据随机基数一一更改该部分中指向的引用。然后,如果我修改指令的字节,因为它们已经在.reloc节中定义,我的新字节将被修改(可能我错了,但这是我的理解)

但是,我无法找出 Windows 如何“获取”指令:

03CD38D4:  8B15 8C5FF703  MOV EDX, DWORD PTR DS:[3F75F8C]

在文件偏移中482CD4存储为:

MOV EDX, DWORD PTR DS:[B25F8C]

图像基础是400000代码基础1000

我不能在找到任何.reloc节点03CD38D4482CD4或类似的。

1个回答

ASLR 不查看可执行文件内部,

基本上是一种系统范围的漏洞利用缓解技术,简单地说就是在每个可执行文件的每次加载时分配一个随机基地址

也就是说,如果您运行 calc.exe 五次,您可能会看到 calc.exe 在五个不同的地址加载

C:\>cdb -c "lm m calc;q" calc | grep "calc.*deferred
00dd0000 00e90000   calc       (deferred)

C:\>cdb -c "lm m calc;q" calc | grep "calc.*deferred
00250000 00310000   calc       (deferred)

C:\>cdb -c "lm m calc;q" calc | grep "calc.*deferred
00370000 00430000   calc       (deferred)

C:\>cdb -c "lm m calc;q" calc | grep "calc.*deferred
00860000 00920000   calc       (deferred)

C:\>cdb -c "lm m calc;q" calc | grep "calc.*deferred
00110000 001d0000   calc       (deferred)

要修复的信息位于 .reloc 部分下的可执行文件中

加载器在加载可执行文件时获取分配给加载的基地址,并根据可执行文件的 .reloc 部分中提供的详细信息执行修复

您可以使用 dumpbin 和其他无数 pe 编辑器查看修复程序

C:\>dumpbin /relocations c:\Windows\System32\calc.exe | wc -l
7346

C:\>dumpbin /relocations c:\Windows\System32\calc.exe | head -n 20
Microsoft (R) COFF/PE Dumper Version 14.15.26726.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file c:\Windows\System32\calc.exe

File Type: EXECUTABLE IMAGE

BASE RELOCATIONS #4
    1000 RVA,       B4 SizeOfBlock
     641  HIGHLOW            01054064  ___security_cookie
     652  HIGHLOW            01001194  __imp__GetModuleHandleW@4
     6A5  HIGHLOW            010013F4  __imp__LoadStringW@16
     6B3  HIGHLOW            010540AC  ?calcSQM@@3PAVCCalculatorSQM@@A (class CCalculatorSQM * calcSQM)
     6BD  HIGHLOW            01054A70  _Microsoft_Windows_CalculatorHandle
     6C2  HIGHLOW            010551F8  _Microsoft_Windows_Calculator_Context
     6C7  HIGHLOW            010321A3  _McGenControlCallbackV2@36
     6CC  HIGHLOW            01001D5C  _Microsoft_Windows_Calculator
     6D7  HIGHLOW            0105521C
     707  HIGHLOW            01001EDE  ?WndProc@@YGJPAUHWND__@@IIJ@Z (long __stdcall WndProc(struct HWND__ *,unsigned in
t,unsigned int,long))

C:\>

RVA是与基地址相关的相对虚拟地址

所以如果基地址 = 0x10000000 那么绝对地址将是 0x10001000
所以需要修复的地址是上面转储中的 0x10001641

您可以从头文件中找到首选的地址基址,
大多数静态分析工具只会在该地址中加载 pe

C:\>dumpbin /headers c:\Windows\System32\calc.exe | grep -i "image base"
         1000000 image base (01000000 to 010BFFFF)

您可以使用任何十六进制编辑器在可执行文件中的某个指定位置转储字节(使用 0x641 以上转储中第一个条目的 HIGHLOW)您可以看到字节是 a1 0x10054064

使用 a40 而不是 1640 因为代码Base在物理文件中是 0x400

它将被映射到进程地址空间中的 0x1000 (虚拟地址)

C:\>xxd -s 0xa40 -l 10 -g 5 c:\Windows\System32\calc.exe
0000a40: a164400501 33c58945fc                .d@..3..E.

您可以看到反汇编(此处使用虚拟地址,因为这是映射布局而不是物理文件)

C:\>dumpbin /disasm /range:0x1001640,0x1001645 c:\Windows\System32\calc.exe

  01001640: A1 64 40 05 01     mov         eax,dword ptr [___security_cookie]
  01001645: 33

如果您现在在启用 ASLR 的机器中加载它并查看同一虚拟地址处的反汇编,您将看到 0x1000000(首选加载地址)已被修复

C:\>cdb -c "? calc;u calc+1640 l1;q" calc | grep -i -A 3 Reading
0:000> cdb: Reading initial command '? calc;u calc+1640 l1;q'
Evaluate expression: 5177344 = 004f0000
calc!WinMain+0xb:
004f1640 a164405400      mov     eax,dword ptr [calc!__security_cookie (00544064)]

C:\>python -c "print ( \"%x\" % (0x4f0000 + 0x54064) )"
544064