【问题标题】:Same binary, but different Stack Pointer (ESP) address in different debugger相同的二进制文件,但不同调试器中的堆栈指针 (ESP) 地址不同
【发布时间】:2017-12-05 17:45:10
【问题描述】:

这是我的 C 代码

λ gdb var -q
Reading symbols from C:\Codes\var.exe...done.
(gdb) set disassembly-flavor intel
(gdb) list
1       #include<stdio.h>
2
3       int main()
4       {
5           int a = 9;
6           int b = 10;
7           int c = 11;
8           return 0;
9       }
(gdb)

这是汇编中的主要功能

(gdb) break 3
Breakpoint 1 at 0x40134e: file var.c, line 3.
(gdb) run
Starting program: C:\Codes/var.exe
[New Thread 376.0xc80]

Breakpoint 1, main () at var.c:5
5           int a = 9;
(gdb) disassemble
Dump of assembler code for function main:
   0x00401340 <+0>:     push   ebp
   0x00401341 <+1>:     mov    ebp,esp
   0x00401343 <+3>:     and    esp,0xfffffff0
   0x00401346 <+6>:     sub    esp,0x10
   0x00401349 <+9>:     call   0x401920 <__main>
=> 0x0040134e <+14>:    mov    DWORD PTR [esp+0xc],0x9
   0x00401356 <+22>:    mov    DWORD PTR [esp+0x8],0xa
   0x0040135e <+30>:    mov    DWORD PTR [esp+0x4],0xb
   0x00401366 <+38>:    mov    eax,0x0
   0x0040136b <+43>:    leave
   0x0040136c <+44>:    ret
End of assembler dump.
(gdb)

让我们关注这一行

=> 0x0040134e <+14>:    mov    DWORD PTR [esp+0xc],0x9

此时堆栈指针esp地址为0x22ff40

(gdb) info registers eip esp
eip            0x40134e 0x40134e <main+14>
esp            0x22ff40 0x22ff40
(gdb)

变量a的虚拟内存地址是[esp+0xc],即[0x22ff40 + C] = 0x22ff4c

我还用print 命令验证了这个地址

(gdb) print &a
$1 = (int *) 0x22ff4c
(gdb)

但是,当我将相同的二进制文件加载到其他基于 GUI 的调试器(例如 Olly、Immunity Debugger 或 x32dbg)时,ESP 的值略有不同。

Olly/Immunity 调试器/x32dbg

00401340  /$ 55                    PUSH EBP
00401341  |. 89E5                  MOV EBP,ESP
00401343  |. 83E4 F0               AND ESP,FFFFFFF0
00401346  |. 83EC 10               SUB ESP,10
00401349  |. E8 D2050000           CALL var.00401920
0040134E  |. C74424 0C 09000000    MOV DWORD PTR SS:[ESP+C],9
00401356  |. C74424 08 0A000000    MOV DWORD PTR SS:[ESP+8],0A
0040135E  |. C74424 04 0B000000    MOV DWORD PTR SS:[ESP+4],0B
00401366  |. B8 00000000           MOV EAX,0
0040136B  |. C9                    LEAVE
0040136C  \. C3                    RETN

寄存器

EAX 00000000
ECX 0022FFB0
EDX 7C90E514 ntdll.KiFastSystemCallRet
EBX 7FFD9000
ESP 0022FFC4
EBP 0022FFF0
ESI 00790074
EDI 0069006E

EIP 0040134E var.0040134E

这里是 Immunity Debugger 和 x32dbg 的截图供您参考。

我的问题是:

  1. ESP 地址不应该与同一个二进制文件上的 EIP 相同吗?

Olly:EIP 0040134E,ESP 0022FFC4

GDB:EIP 0x40134e,ESP 0x22ff40

  1. 在GDB中,我们可以通过print &amp;a命令轻松找到变量虚拟内存地址,如上图所示。 基于 GUI 的调试器(例如 Olly 或 Immunity)呢?

【问题讨论】:

  • “同一个二进制文件的同一个 EIP 的 ESP 地址不应该是一样的吗?” 不,为什么?您无法保证您将从操作系统获得多少内存用于堆栈,并且对于 PIC(位置无关代码)可执行文件,它甚至可以加载到任何地址。即使是相同的可执行文件+OS 在不同的运行中,地址也可能不同,尽管调试器可能会进行一些环境设置以最小化两次调试运行之间的这些差异。

标签: c assembly gdb


【解决方案1】:

请也看看 ebx。它的值相差 0x1000,但仍指向环境字符串。 调试器将被调试者的部分加载到调试器定义的地址。调试器可以在被调试者的地址空间中存储额外的信息。这将改变内存布局。创建新线程时,调试器必须拦截 CreateThread() 调用以进行自己的记账。它可能会将一些数据推送到新出生线程的堆栈上。

【讨论】:

    【解决方案2】:

    这可能是由于Adress Space Layout Randomization。 ASLR 随机化地址空间布局,包括堆栈的位置,以使攻击者更难预测其攻击代码将在内存中的最终位置。

    【讨论】:

    • 请注意,堆栈 ASLR 可以与代码映射 ASLR 分开控制。可以禁用它,有些人喜欢这样做,以便在调试时更容易在精神上跟踪事物。
    • 但是,当观察到如此小的变化时,它更有可能是调试环境的产物。
    • 我希望 ASLR 将内容移动页面大小的倍数。
    猜你喜欢
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多