
我们看到 PEiD 把搜索到的空间都给我们列出来了:

现在我们用 WinHEX 打开我们要修改的程序,转到偏移 9815 处,从 9815 处选择 32 字节(16进制是0X20)的一个选块,把光标定位到 9815 处,右键选择菜单 剪贴板数据->写入(从当前位置覆写),随后的格式选择 ASCII Hex,把我们 LOGFONT 的 16 进制值
F4FFFFFF000000000000000000000000900100000000008600000000CBCECCE5
写入保存。现在我们用 OllyDBG 载入已添加了 LOGFONT 数据的程序,先转到 VA 40A415 处(从上图中看到的)往下看一下:

因为 SendMessageA 还要用到一个窗口句柄,我们可以通过前面的 CreateWindowExA 来获得。现在我们就把前一张图中的 .rdata 区段中的地址 0040C56E 作为我们保存窗口句柄 HWND 值的临时空间。一切就绪,开始写代码。先回顾一下我们最先说的那两个要修改的地方:
第一个要改的地方:
00408F5E |. FF15 98B24000 |CALL DWORD PTR DS:[<&USER32.CreateWindowExA>] ; \CreateWindowExA
00408F64 6A 00 PUSH 0 ; 修改前
00408F66 8945 F4 MOV DWORD PTR SS:[EBP-C],EAX
00408F69 |. E8 A098FFFF |CALL <myuninst.sub_40280E>
修改后:
00408F5E |. FF15 98B24000 |CALL DWORD PTR DS:[<&USER32.CreateWindowExA>] ; \CreateWindowExA
00408F64 E9 D5140000 JMP myuninst.0040A43E ; 跳转到我们的补丁代码处
00408F69 |. E8 A098FFFF |CALL <myuninst.sub_40280E>
第二个要改的地方:
00408F91 |. FF15 98B24000 |CALL DWORD PTR DS:[<&USER32.CreateWindowExA>] ; \CreateWindowExA
00408F97 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX ; 改这里
00408F9A 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
00408F9D |. FF30 |PUSH DWORD PTR DS:[EAX] ; /<%s>
00408F9F |. 8D85 B0FEFFFF |LEA EAX,DWORD PTR SS:[EBP-150] ; |
00408FA5 |. 68 D0D94000 |PUSH myuninst.0040D9D0 ; |format = "%s:"
00408FAA |. 50 |PUSH EAX ; |s
00408FAB |. FF15 90B14000 |CALL DWORD PTR DS:[<&MSVCRT.sprintf>] ; \sprintf
00408FB1 |. 8B35 84B24000 |MOV ESI,DWORD PTR DS:[<&USER32.SetWindowTextA>] ; USER32.SetWindowTextA
修改后:
00408F91 |. FF15 98B24000 |CALL DWORD PTR DS:[<&USER32.CreateWindowExA>] ; \CreateWindowExA
00408F97 E9 D4140000 JMP myuninst.0040A470 ; 跳到我们的第二部分补丁代码处
00408F9C 90 NOP
00408F9D |. FF30 |PUSH DWORD PTR DS:[EAX] ; /<%s>
00408F9F |. 8D85 B0FEFFFF |LEA EAX,DWORD PTR SS:[EBP-150] ; |
00408FA5 |. 68 D0D94000 |PUSH myuninst.0040D9D0 ; |format = "%s:"
00408FAA |. 50 |PUSH EAX ; |s
00408FAB |. FF15 90B14000 |CALL DWORD PTR DS:[<&MSVCRT.sprintf>] ; \sprintf
00408FB1 |. 8B35 84B24000 |MOV ESI,DWORD PTR DS:[<&USER32.SetWindowTextA>] ; USER32.SetWindowTextA
这两个地方的修改都是把原代码改成跳转,跳到我们的补丁代码那继续执行。在修改之前先把原代码复制下来,以便恢复。我们在 OllyDBG 中按 CTR+G 组合键,来到 0040A43E 地址处,开始输补丁代码:

同样,我们也在 0040A470 地址处输入我们另一部分的补丁代码。两部分的补丁代码分别如下:
补丁代码1:
0040A43E 60 PUSHAD ; 保护现场
0040A43F A3 6EC54000 MOV DWORD PTR DS:[40C56E],EAX ; 保存窗口句柄
0040A444 68 15A44000 PUSH myuninst.0040A415 ; 传递字体句柄LOGFONT
0040A449 FF15 44B04000 CALL DWORD PTR DS:[<&GDI32.CreateFontIndirectA>] ; GDI32.CreateFontIndirectA
0040A44F 6A 00 PUSH 0 ; lParam 参数留空
0040A451 50 PUSH EAX ; 字体句柄LOGFONT
0040A452 6A 30 PUSH 30 ; WM_SETFONT
0040A454 8B0D 6EC54000 MOV ECX,DWORD PTR DS:[40C56E] ; 窗口句柄送ECX
0040A45A 51 PUSH ECX ; 压入窗口句柄参数
0040A45B FF15 3CB24000 CALL DWORD PTR DS:[<&USER32.SendMessageA>] ; USER32.SendMessageA
0040A461 61 POPAD ; 恢复现场
0040A462 6A 00 PUSH 0 ; 恢复原代码
0040A464 8945 F4 MOV DWORD PTR SS:[EBP-C],EAX
0040A467 ^ E9 FDEAFFFF JMP myuninst.00408F69 ; 返回
补丁代码2:
0040A470 > \60 PUSHAD
0040A471 . A3 6EC54000 MOV DWORD PTR DS:[40C56E],EAX
0040A476 . 68 15A44000 PUSH myuninst.0040A415 ; /pLogfont = myuninst.0040A415
0040A47B . FF15 44B04000 CALL DWORD PTR DS:[<&GDI32.CreateFontIndirectA>] ; \CreateFontIndirectA
0040A481 . 6A 00 PUSH 0 ; /lParam = 0
0040A483 . 50 PUSH EAX ; |wParam
0040A484 . 6A 30 PUSH 30 ; |Message = WM_SETFONT
0040A486 . 8B0D 6EC54000 MOV ECX,DWORD PTR DS:[40C56E] ; |
0040A48C . 51 PUSH ECX ; |hWnd => NULL
0040A48D . FF15 3CB24000 CALL DWORD PTR DS:[<&USER32.SendMessageA>] ; \SendMessageA
0040A493 . 61 POPAD
0040A494 . 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX
0040A497 . 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
0040A49A .^ E9 FEEAFFFF JMP myuninst.00408F9D
补丁代码2因为与补丁代码1类似,我就不做详细解释了。现在我们的代码都写完了,现在我们开始保存我们的工作,选中我们修改的代码,点击鼠标右键,会出来一个菜单:
(未完待续)