首页
社区
课程
招聘
[旧帖] [求助]堆栈用esp而不用ebp堆栈寻址,怎么调试啊 0.00雪花
2011-4-26 20:07 1766

[旧帖] [求助]堆栈用esp而不用ebp堆栈寻址,怎么调试啊 0.00雪花

2011-4-26 20:07
1766
【求助】OD逆向后,发现都用esp而不用ebp堆栈寻址,怎么调试啊??
主要是 esp+xxx  很难知道表示啥内容

部分代码如下:

0047619D  |>  85DB          TEST EBX,EBX
0047619F  |.  74 09         JE SHORT pdoc.004761AA
004761A1  |.  6A 01         PUSH 1                                   ; /How = SD_SEND
004761A3  |.  53            PUSH EBX                                 ; |Socket
004761A4  |.  FF15 04FE4700 CALL DWORD PTR DS:[<&WS2_32.#22>]        ; \shutdown
004761AA  |>  8B45 18       MOV EAX,DWORD PTR SS:[EBP+18]
004761AD  |.  C700 01000000 MOV DWORD PTR DS:[EAX],1
004761B3  |.  C74424 10 000>MOV DWORD PTR SS:[ESP+10],0
004761BB  |.  E9 E1010000   JMP pdoc.004763A1
004761C0  |>  FF15 FCFD4700 CALL DWORD PTR DS:[<&WS2_32.#111>]       ; [WSAGetLastError
004761C6  |.  2D 01000100   SUB EAX,10001                            ;  Switch (cases 10001..10002)
004761CB  |.  74 10         JE SHORT pdoc.004761DD
004761CD  |.  48            DEC EAX
004761CE  |.  75 30         JNZ SHORT pdoc.00476200
004761D0  |.  C74424 10 060>MOV DWORD PTR SS:[ESP+10],6              ;  Case 10002 of switch 004761C6
004761D8  |.  E9 C4010000   JMP pdoc.004763A1
004761DD  |>  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]             ;  Case 10001 of switch 004761C6
004761E0  |.  8B51 04       MOV EDX,DWORD PTR DS:[ECX+4]
004761E3  |.  6A 00         PUSH 0                                   ; /Timeout = 0. ms
004761E5  |.  52            PUSH EDX                                 ; |hObject
004761E6  |.  FF15 0CF14700 CALL DWORD PTR DS:[<&KERNEL32.WaitForSin>; \WaitForSingleObject
004761EC  |.  3D 02010000   CMP EAX,102
004761F1  |.  75 0D         JNZ SHORT pdoc.00476200
004761F3  |.  C74424 10 050>MOV DWORD PTR SS:[ESP+10],5
004761FB  |.  E9 A1010000   JMP pdoc.004763A1
00476200  |>  8B45 18       MOV EAX,DWORD PTR SS:[EBP+18]            ;  Default case of switch 004761C6
00476203  |.  C700 01000000 MOV DWORD PTR DS:[EAX],1
00476209  |.  C74424 10 020>MOV DWORD PTR SS:[ESP+10],2
00476211  |.  E9 8B010000   JMP pdoc.004763A1
00476216  |>  8B4C24 14     MOV ECX,DWORD PTR SS:[ESP+14]
0047621A  |.  85C9          TEST ECX,ECX
0047621C  |.  C74424 10 000>MOV DWORD PTR SS:[ESP+10],0
00476224  |.  0F84 06010000 JE pdoc.00476330
0047622A  |.  83F8 07       CMP EAX,7
0047622D  |.  0F82 DD000000 JB pdoc.00476310
00476233  |.  8B9424 440700>MOV EDX,DWORD PTR SS:[ESP+744]
0047623A  |.  8D78 FA       LEA EDI,DWORD PTR DS:[EAX-6]
0047623D  |.  0FB7F7        MOVZX ESI,DI
00476240  |.  8BC6          MOV EAX,ESI
00476242  |.  8D8C24 460700>LEA ECX,DWORD PTR SS:[ESP+746]
00476249  |.  895424 14     MOV DWORD PTR SS:[ESP+14],EDX
0047624D  |.  E8 9EF7FFFF   CALL pdoc.004759F0
00476252  |.  8B4C24 18     MOV ECX,DWORD PTR SS:[ESP+18]
00476256  |.  66:0FB611     MOVZX DX,BYTE PTR DS:[ECX]
0047625A  |.  8B8C24 440700>MOV ECX,DWORD PTR SS:[ESP+744]
00476261  |.  03D1          ADD EDX,ECX
00476263  |.  03C2          ADD EAX,EDX
00476265  |.  66:398424 420>CMP WORD PTR SS:[ESP+742],AX
0047626D  |.  0F85 9D000000 JNZ pdoc.00476310
00476273  |.  66:3BCF       CMP CX,DI
00476276  |.  0F87 94000000 JA pdoc.00476310
0047627C  |.  8D4C24 28     LEA ECX,DWORD PTR SS:[ESP+28]
00476280  |.  8DBC24 400700>LEA EDI,DWORD PTR SS:[ESP+740]
00476287  |.  E8 D40E0000   CALL pdoc.00477160
0047628C  |.  8B4424 18     MOV EAX,DWORD PTR SS:[ESP+18]
00476290  |.  6A 01         PUSH 1
00476292  |.  6A 10         PUSH 10
00476294  |.  50            PUSH EAX
00476295  |.  56            PUSH ESI
00476296  |.  8D8C24 560700>LEA ECX,DWORD PTR SS:[ESP+756]
0047629D  |.  51            PUSH ECX
0047629E  |.  8BD7          MOV EDX,EDI
004762A0  |.  52            PUSH EDX
004762A1  |.  8D4C24 40     LEA ECX,DWORD PTR SS:[ESP+40]
004762A5  |.  C78424 6C0701>MOV DWORD PTR SS:[ESP+1076C],0
004762B0  |.  E8 9B160000   CALL pdoc.00477950
004762B5  |.  84C0          TEST AL,AL
004762B7  |.  75 37         JNZ SHORT pdoc.004762F0
004762B9  |.  85DB          TEST EBX,EBX
004762BB  |.  74 09         JE SHORT pdoc.004762C6
004762BD  |.  6A 01         PUSH 1                                   ; /How = SD_SEND
004762BF  |.  53            PUSH EBX                                 ; |Socket
004762C0  |.  FF15 04FE4700 CALL DWORD PTR DS:[<&WS2_32.#22>]        ; \shutdown
004762C6  |>  8B45 18       MOV EAX,DWORD PTR SS:[EBP+18]
004762C9  |.  8D4C24 28     LEA ECX,DWORD PTR SS:[ESP+28]
004762CD  |.  C700 01000000 MOV DWORD PTR DS:[EAX],1
004762D3  |.  C74424 10 020>MOV DWORD PTR SS:[ESP+10],2
004762DB  |.  C78424 540701>MOV DWORD PTR SS:[ESP+10754],-1
004762E6  |.  E8 850E0000   CALL pdoc.00477170
004762EB  |.  E9 B1000000   JMP pdoc.004763A1
004762F0  |>  8B4424 18     MOV EAX,DWORD PTR SS:[ESP+18]
004762F4  |.  FE00          INC BYTE PTR DS:[EAX]
004762F6  |.  8D4C24 28     LEA ECX,DWORD PTR SS:[ESP+28]
004762FA  |.  C78424 540701>MOV DWORD PTR SS:[ESP+10754],-1
00476305  |.  E8 660E0000   CALL pdoc.00477170
0047630A  |.  8B4424 14     MOV EAX,DWORD PTR SS:[ESP+14]
0047630E  |.  EB 4F         JMP SHORT pdoc.0047635F
00476310  |>  85DB          TEST EBX,EBX
00476312  |.  74 09         JE SHORT pdoc.0047631D
00476314  |.  6A 01         PUSH 1                                   ; /How = SD_SEND
00476316  |.  53            PUSH EBX                                 ; |Socket
00476317  |.  FF15 04FE4700 CALL DWORD PTR DS:[<&WS2_32.#22>]        ; \shutdown
0047631D  |>  8B4D 18       MOV ECX,DWORD PTR SS:[EBP+18]
00476320  |.  C701 01000000 MOV DWORD PTR DS:[ECX],1
00476326  |.  C74424 10 020>MOV DWORD PTR SS:[ESP+10],2
0047632E  |.  EB 71         JMP SHORT pdoc.004763A1
00476330  |>  83F8 03       CMP EAX,3
00476333  |.  73 20         JNB SHORT pdoc.00476355
00476335  |.  85DB          TEST EBX,EBX
00476337  |.  74 09         JE SHORT pdoc.00476342
00476339  |.  6A 01         PUSH 1                                   ; /How = SD_SEND
0047633B  |.  53            PUSH EBX                                 ; |Socket
0047633C  |.  FF15 04FE4700 CALL DWORD PTR DS:[<&WS2_32.#22>]        ; \shutdown
00476342  |>  8B55 18       MOV EDX,DWORD PTR SS:[EBP+18]
00476345  |.  C702 01000000 MOV DWORD PTR DS:[EDX],1
0047634B  |.  C74424 10 020>MOV DWORD PTR SS:[ESP+10],2
00476353  |.  EB 4C         JMP SHORT pdoc.004763A1
00476355  |>  8DBC24 420700>LEA EDI,DWORD PTR SS:[ESP+742]
0047635C  |.  83C0 FE       ADD EAX,-2
0047635F  |>  66:3D 0200    CMP AX,2
00476363  |.  8B4D 18       MOV ECX,DWORD PTR SS:[EBP+18]
00476366  |.  66:8B17       MOV DX,WORD PTR DS:[EDI]
00476369  |.  C701 00000000 MOV DWORD PTR DS:[ECX],0
0047636F  |.  8B4D 1C       MOV ECX,DWORD PTR SS:[EBP+1C]
00476372  |.  66:8911       MOV WORD PTR DS:[ECX],DX
00476375  |.  75 0B         JNZ SHORT pdoc.00476382
00476377  |.  8B55 24       MOV EDX,DWORD PTR SS:[EBP+24]

[培训]内核驱动高级班,冲击BAT一流互联网大厂工 作,每周日13:00-18:00直播授课

收藏
点赞0
打赏
分享
最新回复 (8)
雪    币: 179
活跃值: (26)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
SJQIANG 2 2011-4-26 22:32
2
0
只是换了一种表示方法,本质上都是一样的。
不过调试起来是比较麻烦,要随时注意esp的变化。
雪    币: 95
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
BombBomb 2011-4-27 08:44
3
0
谢谢回复~~~

是啊,调试起来我得时刻关注OD右下角堆栈区的变化....

不知道有没有更好的办法跟踪这种代码...

还有,这种代码是程序员故意写出来的,还是编译器编译出来的???
1. 如果是程序员故意写出来的,这样做有什么好处呢
2. 如果是编译器编译出来的,有哪些编译器会这样搞呢...我只知道VC6.0不是这样的

3. OD有没有在堆栈区添加注释的功能呢..呵呵,如果可以注释跟踪起来也方便一些
雪    币: 1644
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yodamaster 2011-4-27 09:33
4
1
1,2: 编译器优化的结果.
from: http://blogs.msdn.com/b/larryosterman/archive/2007/03/12/fpo.aspx

FPO
Larry Osterman [MSFT] 12 Mar 2007 12:44 PM

I was chatting with one of the perf guys last week and he mentioned something that surprised me greatly.  Apparently he's having perf issues that appear to be associated with a 3rd party driver.  Unfortunately, he's having problems figuring out what's going wrong because the vendor wrote the driver used FPO (and hasn't provided symbols), so the perf guy can't track the root cause of the problem.

The reason I was surprised was that I didn't realize that ANYONE was using FPO any more.

What's FPO?

To know the answer, you have to go way back into prehistory.

Intel's 8088 processor had an extremely limited set of registers (I'm ignoring the segment registers), they were:

AX BX CX DX IP
SI DI BP SP FLAGS

With such a limited set of registers, the registers were all assigned specific purposes.  AX, BX, CX, and DX were the "General Purpose" registers, SI and DI were "Index" registers, SP was the "Stack Pointer", BP was the "Frame Pointer", IP was the "Instruction Pointer", and FLAGS was a read-only register that contained several bits that were indicated information about the processors' current state (whether the result of the previous arithmetic or logical instruction was 0, for instance).

The BX, SI, DI and BP registers were special because they could be used as "Index" registers.  Index registers are critically important to a compiler, because they are used to access memory through a pointer.  In other words, if you have a structure that's located at offset 0x1234 in memory, you can set an index register to the value 0x1234 and access values relative to that location.  For example:

MOV    BX, [Structure]
MOV    AX, [BX]+4

Will set the BX register to the value of the memory pointed to by [Structure] and set the value of AX to the WORD located at the 4th byte relative to the start of that structure.

One thing to note is that the SP register wasn't an index register.  That meant that to access variables on the stack, you needed to use a different register, that's where the BP register came from - the BP register was dedicated to accessing values on the stack.

When the 386 came out, they stretched the various registers to 32bits, and they fixed the restrictions that only BX, SI, DI and BP could be used as index registers.

EAX EBX ECX EDX EIP
ESI EDI EBP ESP FLAGS

This was a good thing, all of a sudden, instead of being constrained to 3 index registers, the compiler could use 6 of them.

Since index registers are used for structure access, to a compiler they're like gold - more of them is a good thing, and it's worth almost any amount of effort to gain more of them.

Some extraordinarily clever person realized that since ESP was now an index register the EBP register no longer had to be dedicated for accessing variables on the stack.  In other words, instead of:

MyFunction:
    PUSH    EBP
    MOV     EBP, ESP
    SUB      ESP, <LocalVariableStorage>
    MOV     EAX, [EBP+8]
      :
      :
    MOV     ESP, EBP
    POP      EBP
    RETD

to access the 1st parameter on the stack (EBP+0 is the old value of EBP, EBP+4 is the return address), you can instead do:

MyFunction:
    SUB      SP, <LocalVariableStorage>
    MOV     EAX, [ESP+4+<LocalVariableStorage>]
      :
      :
    ADD     SP, <LocalVariableStorage>
    RETD

This works GREAT - all of a sudden, EBP can be repurposed and used as another general purpose register!  The compiler folks called this optimization "Frame Pointer Omission", and it went by the acronym FPO.

But there's one small problem with FPO.

If you look at the pre-FPO example for MyFunction, you'd notice that the first instruction in the routine was PUSH EBP followed by a MOV EBP, ESP.  That had an interesting and extremely useful side effect.  It essentially created a singly linked list that linked the frame pointer for each of the callers to a function.  From the EBP for a routine, you could recover the entire call stack for a function.  This was unbelievably useful for debuggers - it meant that call stacks were quite reliable, even if you didn't have symbols for all the modules being debugged.  Unfortunately, when FPO was enabled, that list of stack frames was lost - the information simply wasn't being tracked.

To solve the is problem, the compiler guys put the information that was lost when FPO was enabled into the PDB file for the binary.  Thus, when you had symbols for the modules, you could recover all the stack information.

FPO was enabled for all Windows binaries in NT 3.51, but was turned off for Windows binaries in Vista because it was no longer necessary - machines got sufficiently faster since 1995 that the performance improvements that were achieved by FPO weren't sufficient to counter the pain in debugging and analysis that FPO caused.

Edit: Clarified what I meant by "FPO was enabled in NT 3.51" and "was turned off in Vista", thanks Steve for pointing this out.
雪    币: 95
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
BombBomb 2011-4-27 09:56
5
0
谢谢yodamaster....原来这是FPO搞的鬼.........

你的回复中 这样一句话不怎么理解啊
FPO was enabled for all Windows binaries in NT 3.51, but was turned off for Windows binaries in Vista

程序在编译后生成的二进制码已经固定了,如果拿这份二进制码到vista或win7下跑,难道就没有FPO了吗???
雪    币: 95
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
BombBomb 2011-4-27 10:25
6
0
发现用ida静态反汇编后,ida能够识别出参数....ida实在太牛了...........
但是还有很多esp+xxx需要手动跟踪......
继续等待牛人给出一个好的调试方法.......
雪    币: 152
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
XSJS 2011-4-27 10:34
7
0
本质上还是一样的嘛,一个地址对应一个XX,ESP和EBP只是相对寻址,根本无所谓。。。。。
该干嘛干嘛
雪    币: 95
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
BombBomb 2011-4-27 11:49
8
0
...我还是慢慢跟吧..............
谢谢各位的回复....

就此结帖吧.....不知道怎么结帖...
雪    币: 1644
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yodamaster 2011-4-27 16:42
9
0
这句话的意思是说, 微软在编译NT 3.51的的时候启用了FPO, 而编译windows vista的时候没有启用FPO.
游客
登录 | 注册 方可回帖
返回