第一次破解,大神请飘过。
首先介绍下CCProxy这个工具吧,CCProxy主要的功能就是设置网络代理,比如在A服务器上设置了代理,B客户机上连接A服务器的代理,这样B就能通过A服务器进行Internet的访问。这样说大家可能不太明白,举个例子吧,我们公司在香港租赁了一台服务器,在这台服务器是可以访问Google的,但总不能每次mstsc到服务器,然后再在服务器上打开浏览器,访问Google吧,这时候只要在香港服务器上运行CCProxy,再在客户端的浏览器上进行代理设置就能直接访问Google,可以无限畅游国外网站。
好的,废话不多说,这次试用的版本是8.0的,如果是非注册用户,就只能设置3个用户,这3个用户可以通过它的代理访问网络(也可以设置不限制,这样你的服务器资源就造福全社会了),如果注册成功就能设置任意个数的用户。用到的破解工具就是OllyDbg2.01。
首先,我在自己电脑上装了一下CCProxy,发现不能用OD链接,结果发现OD貌似是不支持X64程序的。后来装了个虚拟机,在虚拟机上进行破解。
(1)直接运行,点击注册,可以看到提示“对不起,注册失败!”
(2)后来想了想,要是用OD搜索字符串如果是中文可能不好搜索,于是就换成了英文版,提示就变成了"Sorry. Registration Failed!"。
(3)一切准备就绪,用OD连接该程序,按F9运行,右键->搜索->所用引用的字符串,在再里面搜索Sorry,然并卵,并没有搜索到。
(4)觉得是OD自带的字符串搜索工具不行,就下了搜索字符串的插件(StrFinder.dll),结果还是一样没有搜到(最后发现是在内存的堆地址里面),看样子要换别的方法了。在系统函数里下断点,首先BP MessageBoxA,确实可以下到断点,然后还可以看到入参。可以看到调用MessageBoxA是在CCProxy.00438D8F。
01D6D564 |00438D8F ; /返回到 USER32.MessageBoxA 来自 CCProxy.00438D8F
01D6D568 |00000000 ; |hOwner = NULL
01D6D56C |016E0440 ; |Text = "Sorry. Registration Failed!"
01D6D570 |016D11F8 ; |Caption = "Sorry. Registration Failed! (10)"
01D6D574 |00000040 ;
|Type = MB_OK|MB_ICONASTERISK|MB_DEFBUTTON1|MB_APPLMODAL
(5)前往CCProxy.00438D8F该位置,并取消MessageBoxA的断点,观察上下文,看看有没有什么破解的机会。我比较关注的是"Sorry. Registration Failed!"这句话是什么时候生成的,于是我在函数的入口CCProxy.00438CE0下断点,得到了下面的入参,因此可以看出"Sorry. Registration Failed!"这句话已经是生成好了,于是前往他的上一级CCProxy.00438EA2继续研究。
01D6D5A8 |00438EA2 ; /返回到 CCProxy.00438CE0 来自 CCProxy.00438EA2
01D6D5AC |016E0440 ; |Arg1 = ASCII "Sorry. Registration Failed!"
01D6D5B0 |016E0408 ; |Arg2 = ASCII "Sorry. Registration Failed!"
01D6D5B4 |0000000A ; |Arg3 = 0A
01D6D5B8 |00000001 ; |Arg4 = 1
01D6D5BC |00000040 ; |Arg5 = 40
(6)前往CCProxy. 00438EA2,同样的取消断点,并在入口CCProxy.00438E50下断点,同样发现关注的字符串已经出现,于是前往上一级CCProxy.004460E9。\
01D6D640 [004460E9 ; /返回到 CCProxy.00438E50 来自 CCProxy.004460E9
01D6D644 00000000 ; |Arg1 = 0
01D6D648 016E0408 ; |Arg2 = ASCII "Sorry. Registration Failed!"
01D6D64C 016E03D0 ; |Arg3 = ASCII "Sorry. Registration Failed!"
01D6D650 00000040 ; |Arg4 = 40
01D6D654 0000000A ; \Arg5 = 0A
(7)前往CCProxy.004460E9,在入口点00445E40下断点,虽然没有得到明显的参数,但是在栈空间还是发现了目标字符串,于是前往他的调用点CCProxy.00445CAD。
(8)前往CCProxy.00445CAD,在入口点00445790下断点,发现已经无法进入到断点了,而且从00445CAD到00445790这个过程比较庞大,中间有许多函数,执行了很多操作,并且有一些初始化的动作如下所示,这里有可能是创建Client2Server和Server2Client的服务,所以这个函数有可能是初始化函数。
00445B83 | push offset 0046A344; Arg2 = ASCII "Client2Server"
00445B88 | mov edx, dword ptr [ebp-18]
00445B8B |push edx; Arg1
00445B8C |mov ecx, dword ptr [ebp-188C]
00445B92 | call 0043C1F0 CCProxy.0043C1F0
00445B97 | mov eax, dword ptr [ebp-188C]
00445B9D |mov ecx, dword ptr [ebp-18]
00445BA0 |mov dword ptr [eax+118], ecx
00445BA6 |jmp short 00445BBC
00445BA8 |push offset 0046A354 Arg2 = ASCII "Server2Client"
00445BAD |mov edx, dword ptr [ebp-18]
00445BB0 |push edx Arg1
00445BB1 |mov ecx, dword ptr [ebp-188C]
00445BB7 |call 0043C1F0 CCProxy.0043C1F0
(9)后面的过程就是在00445CAD这个位置通过分析代码和下断点看看关键字是什么时候产生的,最后发现这个字符串可能是网络通讯或者进程间通讯发送过来的字符串,这里的整个过程只是接收这个字符串并显示出来。
(10)到了这里感觉遇到了瓶颈,并不知道怎么获取这些的字符串是哪里发送过来的,我首先想到了是网络通讯发送过来的(后来想想应该不是),但是这样想算是幸运的,因为这个软件真的是网络注册流程的,所以我也算少走了不少弯路。
(11)如果是网络流程注册的软件,注册应该都会用到send和recv两个接口,于是我在这两个接口里下断点,看看能不能有所收获。
(12)在实际的破解过程中,我在send和recv中都下了断点,但是现在回想应该是只要在send下断点就好了,recv本身就是循环接收,只有发送是程序触发的,这里我们就不说recv的操作了,在send下断点,bp send,看看程序是否会断点。
(13)在send下断点后,程序一直在这里无限循环发送,根本停不下来!这样会造成我们不能具体分析注册流程,多send几次发现这里的ECX ==00127AB8||ECX== 02A0EB50,这样我们下条件断点ECX!= 00127AB8&& ECX!= 02A0EB50应该就能跳出这循环了。设置后,终于在无操作的时候不会进入断点了。
(14)这时候单击“Register”按钮,发现进入了断点(上帝保佑
),在一次注册过程中一共调用了5次send接口:(1)CCProxy_dll.6BF87C89(2)CCProxy_dll.6BF87C89(3)CCProxy_dll.6BF87C89(4)CCProxy_dll.6BF87C89(5)CCProxy.0043C019。可以看到大部分的操作都是来自CCProxy_dll,因此在这里需要认真分析。
(15)跳转到CCProxy_dll.6BF87C89,在这里下断点,发现程序又到了无限循环进断点的悲惨,没关系,还是按照上面说的下条件断点,这次下的条件断点是ECX!= 02A0EB50,OK顺利跳过。和上面同样的方法,在入口下断点,发现这里基本都是下条件断点,这里就不仔细说明了,参照上面的方法。然后一直向上找,最后会在6C3B8715。这里应该是注册的入口函数,下面认真分析下这里的上下文。
(16)从入口下断点,看最后在哪里出现关键字"Sorry. Registration Failed!"。发现在这句之后就出现了关键字。
6C3B8703 call dword ptr [<&mfc90.#910>]
跟进去看一下,发现是
69C45101 mov eax, dword ptr [ecx],
这样就很简单了,找到ECX对应的地址下的值是多少,我破解的过程中其为042F25B0。
(17)在数据区转到该位置,发现里面对应着关键字的ASCII。从入口重新开始,看哪一句代码修改了这部分的数据。最后发现是
6C3B86E0 call 6C3B70D0
这里把该部分内容修改成了关键字。
(18)进入该函数,该函数带了你填入的用户名和注册码。分析该函数,发现前面一大段是读取配置文件”CCProxy.ini”。后面代码如下
6C3B721B mov eax, dword ptr [ebp+0C]
6C3B721E mov dword ptr [ebp-16A8], eax
6C3B7224 mov ecx, dword ptr [ebp-16A8]
6C3B722A add ecx, 1
6C3B722D mov dword ptr [ebp-16AC], ecx
6C3B7233 mov edx, dword ptr [ebp-16A8]
6C3B7239 mov al, byte ptr [edx]
6C3B723B mov byte ptr [ebp-16AD], al
6C3B7241 add dword ptr [ebp-16A8], 1
6C3B7248 cmp byte ptr [ebp-16AD], 0
6C3B724F jne short 6C3B7233
6C3B7251 mov ecx, dword ptr [ebp-16A8]
6C3B7257 sub ecx, dword ptr [ebp-16AC]
6C3B725D mov dword ptr [ebp-16B4], ecx
6C3B7263 cmp dword ptr [ebp-16B4], 0C
6C3B726A je 6C3B7385
这一段细心分析下,发现是一个循环最后求出用户名的长度,如果长度不为0C则跳出,大概是这个意思,终于发现点有用的了,真的很辛苦
,这时候知道用户名的长度必须是12个字符,然后我就重新输入了一个12位的用户名“111111111111”,弹出的对话框变成了“License doesn’t exist”,终于有点不一样了,感谢上帝,这也坚定了我的信心。
(19)现在我们的关键字变成了”License doesn’t exist”,看看这个关键字是哪里来的,结果发现是这里来的。
6C3B7530 call 6C3B8150
而且这个函数执行起来还有一定的时间,应该是访问了网络吧。
再看看上下文
6C3B76BB lea ecx, [ebp-163C]
6C3B76C1 push ecx
6C3B76C2 push offset 6C3DB590 ASCII "RegCode"
6C3B76C7 push offset 6C3DB598 ASCII "System"
6C3B76CC call dword ptr [<&KERNEL32.WritePrivateProfileStringA>]
这里有写入配置文件的操作,那么函数如果跑到了这里,应该就是注册成功了吧,因为注册失败写毛的配置文件呀!!!系不系!!!
(20)然后继续单步F8,看看怎么样能跳转到这里的操作。发现只要修改下面(即如果跳转就不跳转,不跳转就跳转)的代码判断就能成功注册成功。
1,6C3B765C cmp eax, 2D
6C3B765F jne short 6C3B768B
2,6C3B76A5 mov dword ptr [ebp-524], eax
6C3B76AB cmp dword ptr [ebp-524], 0
6C3B76B2 je short 6C3B76DF
(21)当然我们还没有完成暴力破解,因为我们重启程序后会发现这个软件还是未注册的,这时候我们需要暴力修改掉汇编的内容才能完成一直注册成功。
(22)首先cmp eax, 2D修改为cmp eax, 2F
其次这一大串:
6C3B76A5 mov dword ptr [ebp-524], eax
6C3B76AB cmp dword ptr [ebp-524], 0
6C3B76B2 je short 6C3B76DF
修改为:
mov dword ptr [ebp-524], 1
Nop
Nop
Nop
再右键编辑->复制到可执行文件。终于大功告成,重新打开软件发现终于变成破解版的。
总结:这是我第一次破解一个实际的程序,以前都是看看大神们的帖子,破解破解crackme,本次破解大概花了我一周的时间吧,有时候遇到瓶颈真的不知道怎么跳过去,而且这个程序是网络验证的,也算不上是真正意义的破解,只有我自己能用,而且也不能升级。总结下我自己在破解的一些收获吧,也是对于自己的提高
(1)不要每个都去分析,分析太多会很累,要抓住重点。
(2)有时候顺着不行了,就来逆的,逆的不行了又可以来顺的,结合起来用也许会有利于突破瓶颈。
(3)在破解的时候要修改一些寄存器,改变一些跳转,这样能便于我们找到重点所在。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
上传的附件: