我们左键选所有修改(当然选它了,要不然只会保存我们选定的这一部分。关于这个地方还要说一下,有的时候我们修改完程序选“复制到可执行文件”时只有“选择”菜单,没有“所有修改”菜单项。按
OllyDBG
帮助里关于备份功能的说法,好像是受内存块限制的,补丁功能也同样是这样。对于备份及补丁功能我用的比较少,并不是很了解,这方面的内容还是大家自己去研究吧,有什么好的心得也希望能共享一下。我遇到不能保存所有修改的情况就是先把补丁代码全部复制下来,同时利用二进制功能复制代码,先选一段补丁代码保存为文件,再用
OllyDBG
打开保存后的文件,转到相应位置分别把我们复制下来的补丁二进制代码粘贴上去后保存。纯属笨办法,当然你也可以用
HexView
这样的工具来修改代码),随后会出来一个“把选中的内容复制到可执行文件”的对话框,我们选“全部复制”,又出来一个对话框,我们在上面点右键,在弹出的菜单上选“保存文件”:
这时会出来一个另存文件的对话框,我们另选一个名字如
myuninst1.exe
来保存,不要直接覆盖原文件
myuninst.exe,以便于出错后好修改。现在关闭
OllyDBG,先不要急着运行刚刚修改过的文件,因为我们还有个地方要改一下。大家还记得我们在
.rdata
中用了个地方作为我们保存临时变量的地方吧?原先的
.rdata
段属性设置是不可写的,现在我们写入了数据,运行时是会出错的。现在我们要修改一下
.rdata
段的属性。用
LordPE
的
PE
编辑器打开我们修改后的程序,点“区段”按钮,在弹出的对话框中点击
.rdata
段,右键选择弹出菜单中的“编辑区段”:
在弹出的对话框中选标志后面那个“...”按钮:
现在我们把区段标志添加一个可写入的属性:
完成后按确定保存我们所做的工作,运行一下修改后的程序,呵呵,终于把字体改过来了:
如果你运行出错也没关系,用
OllyDBG
调试一下你修改后的程序,看看错在什么地方。这一般都是输入补丁代码时造成的,你只要看一下你补丁代码运行的情况就可以了。到这里我们的任务似乎也完成了,但细心的朋友可能会发现补丁代码1和补丁代码2前面的代码基本上是相同的。一个两个这样的补丁还好,如果要是多的话,这样重复就要浪费不少空间了,况且工作量也相应加大了。既然前面有很多代码都是重复的,为什么我们不把这些重复的代码做成一个子程序呢?这样调用起来要方便的多。下面我们把前面的补丁代码修改一下,我们先把补丁代码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
;
字体句柄
0040A452
6A
30
PUSH
30
;
WM_SETFONT
0040A454
8B0D
6EC54000
MOV
ECX,DWORD
PTR
DS:[40C56E]
;
窗口句柄
0040A45A
51
PUSH
ECX
;
窗口句柄压栈
0040A45B
FF15
3CB24000
CALL
DWORD
PTR
DS:[<&USER32.SendMessageA>]
;
USER32.SendMessageA
0040A461
61
POPAD
;
恢复现场
0040A462
C3
RETN
;
返回
这样我们的子程序代码就写好了。现在我们再在子程序代码后面写上两个补丁代码,当然不要忘了改前面原程序中的跳转:
修改后的补丁代码1:
0040A467
E8
D2FFFFFF
CALL
myuninst.0040A43E
;
调用子程序
0040A46C
6A
00
PUSH
0
;
恢复前面修改过的代码
0040A46E
8945
F4
MOV
DWORD
PTR
SS:[EBP-C],EAX
0040A471
^
E9
F3EAFFFF
JMP
myuninst.00408F69
;
返回继续执行
修改后的补丁代码2:
0040A47A
E8
BFFFFFFF
CALL
myuninst.0040A43E
0040A47F
8945
F0
MOV
DWORD
PTR
SS:[EBP-10],EAX
0040A482
8B45
F8
MOV
EAX,DWORD
PTR
SS:[EBP-8]
0040A485
^
E9
13EBFFFF
JMP
myuninst.00408F9D
我在每个补丁代码片断间留了4个字节来分隔。同样,我们还要修改一下我们前面的跳转:
第一个要修改跳转的地方:
00408F5E
|.
FF15
98B24000
|CALL
DWORD
PTR
DS:[<&USER32.CreateWindowExA>]
;
\断在这里
00408F64
E9
FE140000
JMP
myuninst.0040A467
;
跳到我们的第一部分补丁代码处
00408F69
|.
E8
A098FFFF
|CALL
<myuninst.sub_40280E>
第二个要修改跳转的地方:
00408F91
|.
FF15
98B24000
|CALL
DWORD
PTR
DS:[<&USER32.CreateWindowExA>]
;
\CreateWindowExA
00408F97
E9
DE140000
JMP
myuninst.0040A47A
;
跳到我们的第二部分补丁代码处
00408F9C
90
NOP
00408F9D
|.
FF30
|PUSH
DWORD
PTR
DS:[EAX]
;
/<%s>
修改好后保存,同样不要忘了再修改一下
.rdata
区段的属性。运行一下,一切OK!