首页 > 逆向调试 > PEDIY之计算器关闭动画

PEDIY之计算器关闭动画

这个月似乎没有接触过逆向了,事情有点多,趁着今天有时间复习一下。参考看雪论坛http://bbs.pediy.com/showthread.php?t=75788一文(其实吧,我是照着上面的一步一步做的,配上一点自己对文章的分析)。

我们的目标:当计算器关闭时给其添加关闭动画,通过调用user32.dll中的AnimateWindow来实现。

操作步骤:OD载入计算器,然后右键,选择“搜索”->“所有分支”,来到分支窗口,选择其中的一个分支,单击右键,选择“列出分支案例”,可以找到窗口消息处理(一个一个试就可以看到了,这里的分支是“案例5..138”),如图所示:
找到switch case的WM_CLOSE
双击WM_CLOSE,来到相应的代码处。你可能会发现另外一个WM_CLOSE,如图所示,那到底哪一个是目标消息呢?下个断点测试一下就知道是第一个了。

0100623F  |> \A1 744D0101   MOV EAX,DWORD PTR DS:[1014D74]           ;  案例 10 (WM_CLOSE) --> 分支 01006124
01006244  |.  33DB          XOR EBX,EBX                              ;  第一处
01006246  |.  3BC3          CMP EAX,EBX
01006248  |.  74 11         JE SHORT 0100625B
0100624A  |.  53            PUSH EBX                                 ; /lParam => 0
0100624B  |.  53            PUSH EBX                                 ; |wParam => 0
0100624C  |.  6A 10         PUSH 10                                  ; |Message = WM_CLOSE
0100624E  |.  50            PUSH EAX                                 ; |hWnd => NULL
0100624F  |.  FF15 3C110001 CALL DWORD PTR DS:[<&USER32.SendMessageW>; \SendMessageW
01006255  |.  891D 744D0101 MOV DWORD PTR DS:[1014D74],EBX
0100625B  |>  FF35 6C4D0101 PUSH DWORD PTR DS:[1014D6C]              ; /hWnd = NULL
01006261  |.  FF15 78110001 CALL DWORD PTR DS:[<&USER32.DestroyWindo>; \DestroyWindow
01006267  |.  E8 00E1FFFF   CALL 0100436C
0100626C  |.  53            PUSH EBX                                 ; /Data
0100626D  |.  6A 02         PUSH 2                                   ; |Command = HELP_QUIT
0100626F  |.  FF35 8C4B0101 PUSH DWORD PTR DS:[1014B8C]              ; |Path = NULL
01006275  |.  FF35 6C4D0101 PUSH DWORD PTR DS:[1014D6C]              ; |hWnd = NULL
0100627B  |.  FF15 C0100001 CALL DWORD PTR DS:[<&USER32.WinHelpW>]   ; \WinHelpW
01006281  |.  53            PUSH EBX                                 ; /ExitCode
01006282  |.  FF15 C4100001 CALL DWORD PTR DS:[<&USER32.PostQuitMess>; \PostQuitMessage
01006288  |.  E9 94020000   JMP 01006521

我们只要把0100623F处的代码改为一个跳转,跳到我们自己的地方,然后再跳回来就可以了。现在就开始写我们自己的代码了吗?请别着急,还有一个问题,AnimateWindow函数的第一个参数是窗口句柄,我们如何得到计算器的主窗口句柄呢?我们可以使用GetForegroundWindow来获得的。但我们有很好的条件(^_^),请注意观察上面代码中0100625B处的代码

0100625B  |>  FF35 6C4D0101 PUSH DWORD PTR DS:[1014D6C]              ; /hWnd = NULL

压入的是DestroyWindow函数的参数,而该参数就应当是计算器的主窗口句柄。稍微有经验的人都应该知道[1014D6C]相当于一个全局变量吧!由于我们要在0100623F处就让程序跳走,因此先在0100623F处下一个断点,运行程序,用Spy++获得主窗口句柄,点X关闭程序,断下来之后,在OD的反汇编指令中就可以看到hwnd的值了,观察存储的值是否与Spy++获得的窗口句柄一致。事实证明,果然是一致的验证计算器的窗口句柄值

下面开始找地方写代码了,我找了010136C0这个地方,由于计算器并没有导入AnimateWindow这个华丽的函数,因此需要用工具或者手动增加导入函数。而我选择的是在代码中使用LoadLibrary和GetProcAddress这一黄金搭档来动态获得该函数的地址,
具体代码如下:(可以自己先用C写一段代码,然后参考他的反汇编代码)

010136C0   > \60                  PUSHAD                                   ;  保存寄存器
010136C1   .  68 6C6C0000         PUSH 6C6C                                ;  ll\0\0
010136C6   .  68 33322E64         PUSH 642E3233                            ;  32.d
010136CB   .  68 75736572         PUSH 72657375                            ;  user
010136D0   .  8BC4                MOV EAX,ESP                              ;  esp -> "user32.dll"
010136D2   .  50                  PUSH EAX                                 ; /FileName
010136D3   .  FF15 24100001       CALL DWORD PTR DS:[<&KERNEL32.LoadLibrar>; \LoadLibraryA
010136D9   .  6A 77               PUSH 77                                  ;  w\0\0\0
010136DB   .  68 696E646F         PUSH 6F646E69                            ;  indo
010136E0   .  68 61746557         PUSH 57657461                            ;  ateW
010136E5   .  68 416E696D         PUSH 6D696E41                            ;  Anim
010136EA   .  8BDC                MOV EBX,ESP                              ;  esp -> "AnimateWindow"
010136EC   .  53                  PUSH EBX                                 ; /ProcNameOrOrdinal
010136ED   .  50                  PUSH EAX                                 ; |hModule
010136EE   .  FF15 28100001       CALL DWORD PTR DS:[<&KERNEL32.GetProcAdd>; \GetProcAddress
010136F4      68 02000100         PUSH 10002                               ;  AW_HOR_NEGATIVE | AW_HIDE
010136F9   .  68 B80B0000         PUSH 0BB8                                ;  3000 ms
010136FE   .  FF35 6C4D0101       PUSH DWORD PTR DS:[1014D6C]              ;  hwnd
01013704   .  FFD0                CALL EAX                                 ;  Call AnimateWindow
01013706   .  83C4 1C             ADD ESP,1C                               ;  堆栈平衡
01013709   .  61                  POPAD                                    ;  恢复寄存器
0101370A   .  A1 744D0101         MOV EAX,DWORD PTR DS:[1014D74]           ;  原来的语句,被改成jmp,现在改回来
0101370F   .^ E9 302BFFFF         JMP 01006244                             ;  跳回去

前面的跳转代码的修改:

0100623F   > \E9 7CD40000         JMP 010136C0                             ;  案例 10 (WM_CLOSE) --> 分支 01006124
01006244   >  33DB                XOR EBX,EBX

至此,PEDIY工作结束,现在可以保存修改的文件,来执行一下,发现PEDIY成功。


觉得文章还不错?点击此处对作者进行打赏!


本文地址: 程序人生 >> PEDIY之计算器关闭动画
作者:代码疯子(Wins0n) 本站内容如无声明均属原创,转载请保留作者信息与原文链接,谢谢!


更多



分类: 逆向调试 标签: , ,
  1. 2011年6月27日13:40 | #1

    测试一下 [em018]

    [回复]