【文章标题】: 修改注册表中的设置信息,实现程序的自定义启动
【文章作者】: 范晨鹏
【作者邮箱】: pengs168@gmail.com
【作者主页】: http://www.cnblogs.com/diylab
【作者QQ号】: 109427716
【软件名称】: 自由门6.2
【软件大小】: 334k
【下载地址】: 自己搜索下载
【保护方式】: 什么是保护方式?
【编写语言】: vc++
【使用工具】: OllyICE,eXeScope
【操作平台】: winXP
【软件介绍】: 很好的代理软件,方便访问Google网页快照,维基等。
【作者声明】: 第一次发,有不合适的地方请先警告一下。谢谢!
--------------------------------------------------------------------------------
【详细过程】
自由门(free Gate)是我用过的最方便的代理软件。运行程序,想去哪儿,就去哪儿。缺点是这个软件启动时会自动访问一些不太好的网站。还有些“程序退出时是否关闭IE”等不友好的界面。
所以做了些修改。
主要内容:
1、程序启动的时候不要让它自动打开那个**的网页。
2、退出程序的时候不要提示“是否关闭IE”而改成“退出而不关闭IE”。
3、去掉那些乱七八糟的链接。
总之,留其精华,去其糟粕。
我从实践中学到了:
od的功能键 f8,f9的用法
bpx命令给注册表设断
想象对于破解非常重要,尤其像我这样不懂汇编的人。
文章中用到的Regmon、OllyICE,eXeScope在看雪的“工具下载”栏目均有下载。
代码中"//" 后面的注释为我加的。其它的是od自动加的。
上面“主要任务”中提到的1和2功能,程序都在“设置”中提供了相关选项,并把用户设置保存到注册表中。只是默认的设置不是我们想要的。
功能3就简单了。在exescope中将相关对话框资源的visiable属性设为"false"就行了。
这个程序只有一个独立的文件,所以它的设置项应该保存在注册表中。用RegmonNt监视注册表,在filter中include中填上freeGate_unpacked。运行程序freeGate_unpacked,并在设置中点一下“程序启动时不打开浏览器”中的复选框。查看监视信息。
1.74390316 freeGate_unpacked:2500 OpenKey HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings SUCCESS Access: 0x20019
1.74395931 freeGate_unpacked:2500 QueryValue HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\~venoeil SUCCESS 0xD420
1.74402022 freeGate_unpacked:2500 CloseKey HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings SUCCESS
1.74454105 freeGate_unpacked:2500 CreateKey HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings SUCCESS Access: 0x2000000
1.74515951 freeGate_unpacked:2500 SetValue HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\~venoeil SUCCESS 0xD430
1.74523580 freeGate_unpacked:2500 CloseKey HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings SUCCESS
由第四行和第五行记录可以看到,设置信息保存在了HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings下的~venoeil键中。运行regedit多次观察发现,~venoeil的默认值为0x0000d400,勾选“程序启动时不打开浏览器”后,值为0x0000d410。不勾选“程序启动时不打开浏览器”而选择“代理退出时自动保留所有浏览器”后,值为0x0000d440。现在我们已经知道。勾选“程序启动时不打开浏览器”后和选择“代理退出时自动保留所有浏览器”后,值为0x0000d440。程序的“设置”项中的所有选项的值通过累加保存到~venoeil键值中。
注意!每次载入程序之前,记得把注册表项HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settingss下的~venoeil键删掉,要不程序就不会有我们想要的写注册表的动作了。
用fi查壳。壳名叫做PEcompact2.02。工具下载栏目提供的PEcompact版本不够,脱不了(忘了在哪儿下的了)。在其它地方找了一个,脱得很干净。再用fi看一下,是用vc++ 写的。
用od载入。停在程序入口处。
0042755A >/$ 55 push ebp(这个信息没用,看别人这么写,我便也这么写)
因为我们想要在程序读、写注册表的时候断下来,所以应该下断
在od的最底下command文本框中填“bpx RegQueryvalueExA” (本来想用RegCreateKey RegSetValueExA但经验不足,断点没成功。),od跳出一个"Intermodular calls"窗口。我不知道它是干什么用的,先关掉。
上下拖了一下,果然看到了一个断点(就是最左面一列显示为红的那一行。)好了,F9运行(相当于twr2000中的f5)。右面寄存器窗口哗哗地一陈翻动。程序断在了
00417151 |. FF15 00B04200 call [<&ADVAPI32.RegOpenKeyExA>] ; \RegOpenKeyExA
00417157 |. 85C0 test eax, eax
00417159 |. 75 40 jnz short 0041719B
0041715B |. 8D4424 0C lea eax, [esp+C]
0041715F |. 8D4C24 00 lea ecx, [esp]
00417163 |. 50 push eax ; /pBufSize
00417164 |. 8B4424 18 mov eax, [esp+18] ; |
00417168 |. 8D5424 08 lea edx, [esp+8] ; |
0041716C |. 51 push ecx ; |Buffer
0041716D |. 8B4C24 18 mov ecx, [esp+18] ; |
00417171 |. 52 push edx ; |pValueType
00417172 |. 6A 00 push 0 ; |Reserved = NULL
00417174 |. 50 push eax ; |ValueName
00417175 |. 51 push ecx ; |hKey
00417176 |. C74424 24 040>mov dword ptr [esp+24], 4 ; |
0041717E |. FF15 1CB04200 call [<&ADVAPI32.RegQueryValueExA>] ; \RegQueryValueExA //程序断在了这里。
00417184 |. 85C0 test eax, eax
00417186 |. 74 08 je short 00417190
00417188 |. 8B5424 18 mov edx, [esp+18]
0041718C |. 895424 00 mov [esp], edx
00417190 |> 8B4424 10 mov eax, [esp+10]
00417194 |. 50 push eax ; /hKey
00417195 |. FF15 20B04200 call [<&ADVAPI32.RegCloseKey>] ; \RegCloseKey
观察这段代码--后面的注释(呵呵,我不懂汇编的)。看到后面的\RegOpenKeyExA,RegQueryValueExA,RegCloseKey ,大致可以想象程序打开某一注册表键,然后读它的值--正是我们想到的一段部分。因为我们只需要键名为“~venoeil”的注册表信息,所以我们在00417151(RegOpenKeyExA处)设断(就是在选中这一行,然后按一下 f2,看到最这一行左面那一列变成红的就行了,再按f2就是取消断点)。以得到open的key为“~venoeil”的信息。
现在,按ctrl+F2重新开始程序(在菜单“调试”-->重新开始)。按f9运行,程序断在了00417151(RegOpenKeyExA)处。
按f8单步跟踪(就是一行一行走,碰上call不跟进去,相当于“超级玛丽”中不钻地下管道)。
十二次f8以后,向下走了十一行
00417174 |. 50 push eax ; |ValueName = "~venoeil"
~vemoeil.正是想要的。
主观想象程序对注册表的操作应该是这样的:查找是否存在某一键,有则读取,无则创建。创建成功后继续运行程序。我们这里属于“查找是否存在某一键”
无论如何,这是第一次查询,程序还会来调用这里“无则创建”。所以继续按"f9"。同时观察注册表什么时候添加了~venoeil(记得每次观察注册表时需要f5刷新)。我这里,第二次走过0041717E (RegQueryValueExA)后,od不动了。跳出了freegate的“运行模式对话框”(可能没有跳出来,可能是其它窗口挡住了,把其它窗口拖走找找。如果程序直接运行了,请把注册表把注册表项HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settingss下的~venoeil键删掉)。点“确定”后,回到OD,程序又被断在了00417151(RegOpenKeyExA)处。继续f9,再下一次f9时,刷新注册表,已经有了~venoeil键。
至此,我们经过00417151(RegOpenKeyExA)处共四次。在第三次和第四次之间,程序创建了注册表键值~venoeil。
因为我们的目的是找到程序写注册表的地方,并把写的数值改一下(想像中是把0x0000d400改成0x0000d450)。所以需要在第三次f9之后一步步地看程序怎样进行了写注册表的操作。
先按F2把0041717E(RegQueryValueExA)处的断点清除掉。这时程序里只有一处断点00417151(RegOpenKeyExA)。
把注册表中的HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings下的~venoeil键删除。
ctrl+F2,重新运行程序,按三次F9,出现“运行模式”对话框,点“确定”,回到od。这时候程序就准备写注册表了。我们用F8单步跟踪,目的是找到写注册表的地方。
00417175 |. 51 push ecx ; |hKey
00417176 |. C74424 24 040>mov dword ptr [esp+24], 4 ; |
0041717E |. FF15 1CB04200 call [<&ADVAPI32.RegQueryValueExA>] ; \RegQueryValueExA
00417184 |. 85C0 test eax, eax
00417186 |. 74 08 je short 00417190
00417188 |. 8B5424 18 mov edx, [esp+18]
0041718C |. 895424 00 mov [esp], edx
00417190 |> 8B4424 10 mov eax, [esp+10]
00417194 |. 50 push eax ; /hKey
00417195 |. FF15 20B04200 call [<&ADVAPI32.RegCloseKey>] ; \RegCloseKey
0041719B |> 8B4424 00 mov eax, [esp]
0041719F |. 83C4 08 add esp, 8
004171A2 \. C3 retn //程序从这里返回到004172AC
004171A3 90 nop
然后到了 004172AC,再次"retn"(也就是ret,返回,相当于玛丽从管道中钻出来)
004172AC |. 83C4 10 add esp, 10
004172AF \. C3 retn //又一个ret
到了00408DCB
00408DC6 . E8 C5E40000 call 00417290
00408DCB . 8BF8 mov edi, eax //ret到这里
00408DCD . 8B86 20010000 mov eax, [esi+120]
00408DD3 . 83C4 04 add esp, 4
00408DD6 . 83F8 02 cmp eax, 2
00408DD9 . 75 0E jnz short 00408DE9
00408DDB . 81E7 FF7FFFFF and edi, FFFF7FFF
00408DE1 . 81CF 00000100 or edi, 10000
00408DE7 . EB 11 jmp short 00408DFA
00408DE9 > 83F8 01 cmp eax, 1
00408DEC . 75 0C jnz short 00408DFA
00408DEE . 81E7 FFFFFEFF and edi, FFFEFFFF
00408DF4 . 81CF 00800000 or edi, 8000
00408DFA > 8B86 80000000 mov eax, [esi+80]
00408E00 . 6A 00 push 0 ; /lParam = 0
00408E02 . 6A 00 push 0 ; |wParam = 0
00408E04 . 68 F0000000 push 0F0 ; |Message = BM_GETCHECK
00408E09 . 50 push eax ; |hWnd
00408E0A . FF15 24B74200 call [<&USER32.SendMessageA>] ; \SendMessageA
00408E10 . 83F8 01 cmp eax, 1
00408E13 . 75 18 jnz short 00408E2D
00408E15 . 81CF 00400000 or edi, 4000
00408E1B . 57 push edi
00408E1C . E8 8FE40000 call 004172B0 //注册表中有~venoeil键了!
00408E21 . 83C4 04 add esp, 4
上面这些代码我看不懂。但F8跟踪到00408E21时,注册表中有了键~venoeil,键值为0x0000d400。所以,可以知道00408E1C 处的这个call是对写注册表子函数的调用,并且完成了记录“启动时打开主页”复选框的值。
Pardon me,我本来想跟踪写注册表的过程的,但汇编方面,就记住几条“九筒就胡”“霸死便霸无”什么的。像esp什么的真不知道是干什么用。 进去看了看,吓晕了。赶紧退出来在外面想办法。上下瞅瞅,只看到有两个眼熟的。
00408DF4 . 81CF 00800000 or edi, 8000
……
00408E15 . 81CF 00400000 or edi, 4000
就是认识后面那两个数字:8000和4000。
没熟人也得办事。想想前面的分析,注册表写入操作应该是这样的:每个选项都要调用一下写注册表的过程,~venoeil的值记录了选项控件的不同状态。比如这里,如果“启动时打开主页”复选框为选中状态,则把~venoeil键值增加0X10。否则,加0。
这样想的话,在这里把这个值改掉。不跟进去也是可以的?试试。
在00408E15处F2下断(因为再运行时要在这儿附近改代码)ctrl+F2重新运行,操作照前,直到程序运行到00408E15。
在00408E15行右键,选择“汇编”,把4000改成4050(默认值(0x0000d400)+0x10(启动时打开主页)+0x40(代理退出时自动保留所有浏览器))。
00408E13 . /75 18 jnz short 00408E2D
00408E15 |81CF 40400000 or edi, 4050
00408E1B . |57 push edi
00408E1C . |E8 8FE40000 call 004172B0 ; 写注册表子过程
00408E21 . |83C4 04 add esp, 4
00408E24 . |8BCE mov ecx, esi
两次f8,到了00408E21,这时写注册表的子过程已经执行完毕。
看看注册表,呵呵,真的变了,变成了我们想要的值0x0000d450。
就这样算大“工”告成。剩下的“小工”一是把修改好的文件保存下来。二是用exescope把不需要的资源隐藏起来。
保存文件:在od中右键,选“复制到可执行文件”-->所有更改。另存成“freegate_2.exe”就好了。
编辑资源不在此赘述。
--------------------------------------------------------------------------------
【经验总结】
糊里糊涂地完成了。心里清楚这样的crack真是狗屁不通。整理了一下思路。解决这个软件的其实只需要两步:
1、对写注册表的函数下断。(bpx RegSetValueExA)。
2、修改RegSetValueExA的参数。
据此我回头再看,破解的核心应该是下面这段写注册表的函数
004171C8 |. FF15 14B04200 call [<&ADVAPI32.RegCreateKeyA>] ; \RegCreateKeyA
004171CE |. 85C0 test eax, eax
004171D0 |. 75 25 jnz short 004171F7
004171D2 |. 8B5424 10 mov edx, [esp+10]
004171D6 |. 8D4C24 00 lea ecx, [esp]
004171DA |. 6A 04 push 4 ; /BufSize = 4
004171DC |. 51 push ecx ; |Buffer
004171DD |. 6A 04 push 4 ; |ValueType = REG_DWORD
004171DF |. 50 push eax ; |Reserved
004171E0 8B4424 24 mov eax, [esp+24]
004171E4 52 push edx
004171E5 |. 50 push eax ; |hKey
004171E6 |. FF15 18B04200 call [<&ADVAPI32.RegSetValueExA>] ; \RegSetValueExA
004171EC |. 8B4C24 14 mov ecx, [esp+14]
004171F0 |. 51 push ecx ; /hKey
004171F1 |. FF15 20B04200 call [<&ADVAPI32.RegCloseKey>] ; \RegCloseKey
到写注册表前,我本来想把004171E0处 mov的数值改一下就行了。如下
004171E0 8B4424 24 mov eax, 1FC //[esp+24]的原值为0ac
但F9运行后会提示“不知如何继续,因为内存地址00000000不可读……”
即使 mov eax, 1AC也是一样出错。
我是菜鸟。请高人解释一下为什么不能这么改。要想实现修改eax的内容(就是把push进去的第四个参数数值比原来加50)
应该怎么实现。我弄明白的话会把这篇破文修改得更明白些。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年11月11日 18:54:05