本帖最后由 jimmy2752 于 2015-4-25 16:19 编辑
参看这个教程后,http://www.52pojie.cn/thread-141165-1-1.html
其实利用IDA pro的tracing功能,可以很好的追踪程序ESP和EBP等指针的数值,只需tracing instruction即可。
[Asm] 纯文本查看 复制代码 Thread Address Instruction Result
------ ------- ----------- ------
000006CC ST0=FFFFFFFFFFFFFFFF ST1=FFFFFFFFFFFFFFFF ST2=FFFFFFFFFFFFFFFF ST3=FFFFFFFFFFFFFFFF ST4=FFFFFFFFFFFFFFFF ST5=FFFFFFFFFFFFFFFF ST6=FFFFFFFFFFFFFFFF ST7=FFFFFFFFFFFFFFFF CTRL=FFFF CS=001B DS=0023 ES=0023 FS=003B GS=0000 SS=0023 EAX=00A40BC0 EBX=7FFDD000 ECX=00000001 EDX=00A40C28 ESI=012CF764 EDI=00000000 EBP=0012FFC0 ESP=0012FF84 EFL=00000202 XMM0= XMM1= XMM2= XMM3= XMM4= XMM5= XMM6= XMM7= MXCSR=FFFFFFFF MM0= MM1= MM2= MM3= MM4= MM5= MM6= MM7=
000006CC .text:_main_0 jmp _main
000006CC .text:_main push ebp ; 保存EBP ESP=0012FF80
000006CC .text:_main+1 mov ebp, esp ; 原EBP值已经被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。 EBP=0012FF80
000006CC .text:_main+3 sub esp, 40h ; 为局部变量申请空间,大小为40h(注意40h是16进制数,用IDA看看转换成10进制为多少,为64) ESP=0012FF40
000006CC .text:_main+6 push ebx ESP=0012FF3C
000006CC .text:_main+7 push esi ESP=0012FF38
000006CC .text:_main+8 push edi ESP=0012FF34
000006CC .text:_main+9 lea edi, [ebp+var_40]; Var_40是IDA自己分析出来的,表示为局部变量,就是SUB ESP,40h分配的40h个大小,目的是保存局部变量的区域 EDI=0012FF40
000006CC .text:_main+C mov ecx, 10h ECX=00000010
000006CC .text:_main+11 mov eax, 0CCCCCCCCh EAX=CCCCCCCC
000006CC .text:_main+16 rep stosd ; 拷贝字符串,初始化局部变量空间 ECX=00000000 EDI=0012FF80
000006CC .text:_main+18 push 2 ; 参数2入栈 ESP=0012FF30
000006CC .text:_main+1A push 1 ; 参数1入栈 ESP=0012FF2C
000006CC .text:_main+1C call Silence ; 调用我们定义的Silence函数 ESP=0012FF28
000006CC .text:Silence jmp Silence_0
000006CC .text:Silence_0 push ebp ESP=0012FF24
000006CC .text:Silence_0+1 mov ebp, esp EBP=0012FF24
000006CC .text:Silence_0+3 sub esp, 44h ; 这里将局部变量的大小分配为44h ESP=0012FEE0
000006CC .text:Silence_0+6 push ebx ESP=0012FEDC
000006CC .text:Silence_0+7 push esi ESP=0012FED8
000006CC .text:Silence_0+8 push edi ESP=0012FED4
000006CC .text:Silence_0+9 lea edi, [ebp+var_44] EDI=0012FEE0
000006CC .text:Silence_0+C mov ecx, 11h ECX=00000011
000006CC .text:Silence_0+11 mov eax, 0CCCCCCCCh
000006CC .text:Silence_0+16 rep stosd ECX=00000000 EDI=0012FF24
000006CC .text:Silence_0+18 mov eax, [ebp+arg_0]; 取第一个参数放到EAX里面,即参数a EAX=00000001
000006CC .text:Silence_0+1B add eax, [ebp+arg_4]; 与保存在EBP+0Ch里面的参数b相加 EAX=00000003 PF=1
000006CC .text:Silence_0+1E mov [ebp+var_4], eax; 返回值放到ebp - 4里面,即最终结果放到参数c里面
000006CC .text:Silence_0+21 pop edi EDI=0012FF80 ESP=0012FED8
000006CC .text:Silence_0+22 pop esi ESP=0012FEDC
000006CC .text:Silence_0+23 pop ebx ESP=0012FEE0
000006CC .text:Silence_0+24 mov esp, ebp ESP=0012FF24
000006CC .text:Silence_0+26 pop ebp EBP=0012FF80 ESP=0012FF28
000006CC .text:Silence_0+27 retn ESP=0012FF2C
000006CC .text:_main+21 add esp, 8 ; 调用完函数后恢复/释放栈 ESP=0012FF34 PF=0 AF=1
000006CC .text:_main+24 pop edi ; 以下三句都是恢复三个保存的寄存器 EDI=00000000 ESP=0012FF38
000006CC .text:_main+25 pop esi ESP=0012FF3C
000006CC .text:_main+26 pop ebx ESP=0012FF40
000006CC .text:_main+27 add esp, 40h ; 这句对应的是上面的SUB ESP,40h,恢复堆栈, ESP=0012FF80 AF=0
000006CC .text:_main+2A cmp ebp, esp ; 检测ESP是否恢复正常,如果不正常将调用下面的Chkesp PF=1 ZF=1
000006CC .text:_main+2C call __chkesp ; 处理可能出现的堆栈错误(如果出错,将陷入debug) ESP=0012FF7C
000006CC .text:__chkesp jnz short loc_4010B3
000006CC .text:__chkesp+2 retn ESP=0012FF80
000006CC .text:_main+31 mov esp, ebp ; 还记得上面那句mov ebp,esp吗?EBP里面保存着我们初始状态的ESP值,这句是将栈顶指针放回esp
000006CC .text:_main+33 pop ebp ; 恢复原来的ebp和esp,让上一个调用的函数正常使用 EBP=0012FFC0 ESP=0012FF84
000006CC .text:_main+34 retn ; 将返回地址存入EIP, 转移流程 ESP=0012FF88
|