这是我的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 Debugger / 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&amp; amp; x32dbg供您参考。
我的问题是:
ESP
地址是否应该在同一个EIP
上相同?Olly:EIP 0040134E,ESP 0022FFC4
GDB:EIP 0x40134e,ESP 0x22ff40
print &a
命令轻松找到变量虚拟内存地址,如上所示。
那么基于GUI的调试器如Olly或Immunity?答案 0 :(得分:4)
请看一下ebx。它的值相差0x1000,但仍然指向环境字符串。 调试器将debugee的各个部分加载到调试器定义的地址。调试器可以在debugee的地址空间中存储额外的信息。这将改变内存布局。创建新线程时,调试器必须拦截CreateThread()调用以进行自己的簿记。它可能会在新生线程的堆栈上推送一些数据。
答案 1 :(得分:1)
这可能是由于Adress Space Layout Randomization。 ASLR随机化地址空间布局,包括堆栈的位置,以便让攻击者更难以预测攻击代码在内存中的最终位置。