软件:动态跟踪调试示例(《加密解密第二版》例子)
实现功能:给程序菜单添加一个简单的功能项,只弹出一个MessageBoxA
(当然读者可以以此为基础添加其他功能)

首先PEID查壳,vc++6.0没有壳
这样就相对简单一点,省去了脱壳的麻烦。
我们要实现的功能是弹出一个对话框,那么就要有对话框的标题与内容
标题与内容,我们可以写在rdata段(因为这个段是可读可写的,方便,而且不容易出错)当然也可以写在其他地方,但要保证有可读的属性。
我用十六进制编辑器将标题“注意”写在了48a0的地方,对话框内容“这是增加的消息循环”写在了48b0的地方。
用loadpe查看原输入表并没有MessageBoxA这个函数,那么就需要添加这个函数了,为了简单我是用loadpe添加的这个函数(本来想截个图的,但是还不知道怎么贴进来一个图,所以这次就省了吧,相关添加函数的方法参见其他帖子)
调用的地址是7019(RVA).好了前期的准备工作就已经完成了,下面关键是添加菜单项了
用ResHacker,eXeScope或Visual C++等资源编辑工具在菜单-帮助下面,添加一个关于菜单,ID号是40001(十六进制是9c41)。
添加完资源后就可以添加功能了,当然添加功能首先应该找到消息循环的地方。经过跟踪分析,发现401925是处理菜单的
00401295   > \3D F6030000   CMP EAX,3F6
0040129A   .  74 07         JE SHORT TraceMe.004012A3
0040129C   .  3D 429C0000   CMP EAX,9C42       ;此处对应"关于(&A)..."菜单选项
004012A1   .  75 1D         JNZ SHORT TraceMe.004012C0
004012A3   >  8B9424 000100>MOV EDX,DWORD PTR SS:[ESP+100]           ;  Cases 3F6,9C42 of switch 0040115E
004012AA   .  A1 E0544000   MOV EAX,DWORD PTR DS:[4054E0]
004012AF   .  6A 00         PUSH 0                                   ; /lParam = NULL
004012B1   .  68 20104000   PUSH TraceMe.00401020                    ; |DlgProc = TraceMe.00401020
004012B6   .  52            PUSH EDX                                 ; |hOwner
004012B7   .  6A 67         PUSH 67                                  ; |pTemplate = 67
004012B9   .  50            PUSH EAX                                 ; |hInst => NULL
004012BA   .  FF15 C8404000 CALL DWORD PTR DS:[<&USER32.DialogBoxPar>; \DialogBoxParamA
004012C0   >  5F            POP EDI                                  ;  Default case of switch 0040115E
004012C1   .  33C0          XOR EAX,EAX
004012C3   .  5E            POP ESI
004012C4   .  81C4 F4000000 ADD ESP,0F4
004012CA   .  C2 1000       RETN 10

刚才增加“关于”资源,应该留意到,程序原来"关于(&A)..."项的ID号是40002,十六进制是9c42,刚好就是原来菜单的关于选项
40129c这个代码意思是,如果单击了"关于(&A)..."按钮,则弹出一个对话框窗体。
我们增加菜单新功能就要在这段代码附近动手脚了。OD载入的时候发现这段代码后面的空白处不足以添加我们的代码,所以我们应该让其跳转到后面一大片空白代码处,这样我们就可以“为所欲为了”
00401295   > \3D F6030000   CMP EAX,3F6
0040129A   .  E9 81290000   JMP 增加菜单.00403C20
0040129F      90            NOP
004012A0   >  8B9424 000100>MOV EDX,DWORD PTR SS:[ESP+100]
004012A7   .  A1 E0544000   MOV EAX,DWORD PTR DS:[4054E0]
004012AC   .  90            NOP
004012AD   .  90            NOP
004012AE   .  90            NOP

这是我修改之后的代码。JMP  00403C20这条指令是无条件更改程序的流程,在403c20处的代码如下

00403C20   >^\0F84 7AD6FFFF JE 增加菜单.004012A0
00403C26   .  3D 429C0000   CMP EAX,9C42
00403C2B   .^ 0F84 6FD6FFFF JE 增加菜单.004012A0
00403C31   .  3D 419C0000   CMP EAX,9C41       ;是不是单击了我们增加的关于菜单项
00403C36   .^ 0F85 84D6FFFF JNZ 增加菜单.004012C0
00403C3C   .  60            PUSHAD            ;注意保护原来的变量
00403C3D   .  9C            PUSHFD
00403C3E   .  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
00403C40   .  68 A0484000   PUSH 增加菜单.004048A0                       ; |Title = "注意"
00403C45   .  68 B0484000   PUSH 增加菜单.004048B0                       ; |Text = "这是增加的消息循环"
00403C4A   .  6A 00         PUSH 0                                   ; |hOwner = NULL
00403C4C   .  FF15 19704000 CALL DWORD PTR DS:[<&user32.MessageBoxA>>; \MessageBoxA
00403C52   .  9D            POPFD              ;回复原来的变量
00403C53   .  61            POPAD
00403C54   .^ E9 67D6FFFF   JMP 增加菜单.004012C0;跳回原代码处

添加代码时候,一定要注意堆栈的平衡以及寄存器的保护,以防出现异常。一般情况下,如果在OEP前面增加不需要保护标志位,
但此处不行,因为原代码附近有很多的比较跳转指令,所以保护标志位就非常重要了。
好了,增加菜单并实现其功能就完成了,是不是很简单?当然这只是一个很小的例子,如果要实现很复杂的功能,不是那么容易的
。比如,要准确定位消息循环,以及用最少的代码实现预期的功能等等。不过一切复杂的程序都是由许多简单的程序代码实现的,
希望这篇文章给大家以启示

上传的附件 TraceMe.rar