【发布时间】: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 的截图供您参考。
我的问题是:
-
ESP地址不应该与同一个二进制文件上的EIP相同吗?
Olly:EIP 0040134E,ESP 0022FFC4
GDB:EIP 0x40134e,ESP 0x22ff40
- 在GDB中,我们可以通过
print &a命令轻松找到变量虚拟内存地址,如上图所示。 基于 GUI 的调试器(例如 Olly 或 Immunity)呢?
【问题讨论】:
-
“同一个二进制文件的同一个 EIP 的 ESP 地址不应该是一样的吗?” 不,为什么?您无法保证您将从操作系统获得多少内存用于堆栈,并且对于 PIC(位置无关代码)可执行文件,它甚至可以加载到任何地址。即使是相同的可执行文件+OS 在不同的运行中,地址也可能不同,尽管调试器可能会进行一些环境设置以最小化两次调试运行之间的这些差异。