首先声明,破解仅仅是为了学习,并无其他任何母的。多年以前就已经知道看雪,但是当年更喜欢hack,crack不是太感冒,就放了一放。想不到,这一放就是8年。
YY语音并非一个收费或者注册软件,我希望破解的仅仅是一些功能限制,例如聊天时间限制。
1、打开start.exe,出现登陆框,登陆后,新出来一个框,查看进程,发现没有start.exe,而是多了个duospeak.exe,于是明白了,我要调试的目标是duospeak.exe,而不是start.exe。于是上网猛查资料,终于找到了《加密与解密》第三版提到的A.exe调用B.exe如何调试的问题。打开B.exe,找到程序入口,把入口的汇编代码改成INT 3,把OllyDbg设置成即时调试器,运行A.exe,程序会崩溃,崩溃后可以点击“调试”,会自动打开OllyDbg调试。
可是,作为新人,这个过程花了我两天。说起来简单,一大堆问题。首先,B.exe的入口处是PUSH 74,我双击该行代码,输入INT 3,然后保存到文件,但是,书上提到INT 3是CC,可是,我看16进制那边,根本就不是CC,PUSH 74的时候,HEX数据是6A 74,改成INT 3之后是
CD 03,作为一个新人,我纳闷了,这不是和书上说的不对么?请哪位达人出来解释一下?
虽然和书上说的不对,我还是义无反顾的继续调试。问题又出来了,一直调试不了duospeak.exe,我一直在想,这到底是怎么回事?是不是INT 3这句PUSH 74没被执行?因为到了INT 3中断之后,EIP是不是就指向了下一个地址,导致了PUSH 74没被执行,而导致整个程序不能正确执行?没办法,又是查了一大堆资料,终于知道可以把EIP改到PUSH 74的地方,重新执行一次。可是,还是不行。忙活了半天,才发现,因为我执行A.exe是通过安装程序的桌面快捷方式执行的,而不是直接运行了A.exe。呵呵,所以,经验之谈,不要通过快捷方式运行,不知道是我运气背还是什么,说不定是OllyDbg调试的时候使用了一些相对路径之类的。反正,花了两天时间,终于让B.exe能正常调试了。
我满心欢喜,以为后面的都是小儿科了,谁知道,更大的考验在后头,更大的郁闷。
作为一个Cracker,首先要确定你需要调试的东西是否一定能调试出来,这点,我经过了严格的测试。很简单,作为一个聊天软件,不大可能大量的信息都是服务器处理。YY语音作为一个聊天语聊软件,应该也不例外。YY分了很多频道,主频道、子频道,每个频道都可以设置聊天速度,一般可以设置为300秒才可以说一句话,防止恶意刷屏,并且可以降低服务器负担。那么,问题是,这个300秒是服务器检测的还是客户端检测的?
最好的方案是:客户端先检测,检测通过了再发给服务器,服务器再检测,通过了两道检测了再给其他客户端转发聊天信息。很简单的道理,如果客户端不检测,直接发服务器,那服务器的负担过大是必然的。碰上有人恶意刷屏,随时就能把服务器刷挂掉了。
其次的方案是:客户端检测,服务器不检测。这种方案有什么好处?好处明显是降低了服务器的处理负担。一旦写了客户端外挂,不断的向服务器发消息,服务器检测也能把服务器拖垮。那么,如果服务器不检测,不断的转发,有什么好处?没什么好处,也会拖垮,但唯一的好处是,可以让管理员看到有人恶意刷屏,管理员可以人为的把恶意的人处理掉。如果服务器仅仅是检测而不转发,垮掉了管理员也不知道怎么回事。
综上,再加上我在网络非常繁忙的时候不断发送,但是客户端能瞬间告诉我不能发送消息,我就知道,一定是客户端做了限制。所以,初步判定,YY使用的是第二种方案。
接下来,正式的调试开始。对所有的聊天软件,不外是输入聊天信息,点击“发送”按钮,发送聊天信息。那按照常理,只需要在GetWindowTextW下个断点,即能找到关键地方。可是,我错了。我是这样操作的:
1、Ctrl + G,输入GetWindowTextW,点击确定,找到了一行“PUSH 0C”。我非常非常的纳闷,没道理啊没道理,我还以为找到的是调用GetWindowTextW的地方,结果我失望了,只能找到GetWindowTextW的函数入口。不过想想也对,程序调用函数的时候,只能根据函数的汇编代码找到函数被调用的地方,而不大可能能找到调用函数的地方。但问题来了,我在函数被调用的地方加了断点,alt + F9,能返回函数调用的地方,CALL ***,那我,所有调用这个函数的地方,应该都是CALL ***啊,那我能不能在所有的代码中搜索CALL ***找到所有调用GetWindowTextW的地方?理论上完全是可以的,可惜我OllyDbg不熟,不知道怎么办,哪位高人可以说说的?
我努力的搜索,我一直认为是可以的,可是,到我alt + F9,看了调用GetWindowTextW的地方,我失望了。调用的时候,是CALL Ptr DS***,也就是说,这个函数地址是先放到DS寄存器,再调用的,而放到寄存器的时候,不是直接的mov或者怎么,也是通过一些计算计算到了函数的地址,这样看来,通过搜索命令来找到所有调用GetWindowTextW又是一场空了。多次受到打击,实在让我失望。退而求其次,打算用消息断点试试看。
2、打开消息断点(点工具栏中的“W”),发现有无数个窗口。郁闷,现在每个程序都有N个窗口,没办法的事。打开SPY++,打算找到我要拦截的窗口,可惜,我要点击那个窗口,没有title的,title是一张图片,上面有“发送”两字。我怒,靠,难道就找不到小小一个窗口?立马写个小程序,鼠标移到那个窗口上,找到了,窗口句柄是******。打开计算器,把句柄转换成16进制,找到OD中对应的窗口,右键,加入消息断点,找到消息WM_LBUTTONUP,消息码是202。开始重新调试。可是,这次无论我如何点击按钮,完全断不到。我晕,难道是消息类型有问题?我不灰心,把对应的消息选为所有消息,这次,每次都断到了,断到了大量无意义的点。郁闷,消除断点,F9,再设202消息,还是没断到,试试201(WM_LBUTTONDOWN),再调试,还是不行。
这时,不禁有一种山穷水尽的绝望感觉。或者所有的cracker都会有吧,毕竟我仅仅是个新人,这里,有人可能怀疑我的操作有没有问题,我相信没有,因为我用同样的方法测试其他的程序,断点都是没有问题的,难道我查找的窗口有问题,我查错按钮了?我再次仔细再仔细的检查,发现都是徒劳的。因为我测试了YY的其他按钮,一样无法响应消息断点。到了这里,我彻底放弃了消息断点的做法,打算试试条件断点。
仔细查看GetWindowTextW的参数,第一个参数是窗口句柄,我查了一下,类似的API都是stdcall的参数传递方式,第一个参数应该是esp+4,因此,我在GetWindowTextW的入口处,设了个条件断点,[esp+4]==******,******是那个聊天窗口的句柄。理论上,只要是获取了该聊天窗口的Text,都会断点。遗憾的是,理论是理论,和实践是两码事。无论我如何的发送消息,就是无法断点。
3、到了这里,我已经是黔驴技穷。看着空洞的OllyDbg屏幕,转了千百个念头,却觉得没有一个是有用的。
苍天啊,大地啊,快来个高人来救救我把。接下来,我还有什么办法?
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)