前言:因老婆喜欢玩连连看,整天跟我抢着上网,所以突发奇想:把它变成可以脱机玩的那不就好了吗。所以有了下文(在这里,假设您已经熟悉OD和WINHEX的一般操作)。
一、观察对比,查找原因
单独运行QQ连连看的主程序kyodai.exe,发现其“练习”按钮是变灰的,首先想到了“Window 按钮突破专家”,胡弄了一阵子,毫无起色。猜想1:“练习”按钮不是真正的按钮,而是一幅图片,但是能接受鼠标单机事件。
后来在其资源文件Framerc.dll中看到了果然有这么个图片,证实了我这一想法。
接上网,从游戏大厅启动QQ连连看,发现程序先是初始化了一些个人信息,然后“练习”等按钮被激活了。这两件事间有一定的延时。猜想2:游戏中专门有一线程负责监视联网的状态,如果已经连接上,并且下载了足够的个人信息的话,激活“练习”按钮。
游戏中实现多线程的方法很多,最简单的就是用TIMER了。于是,用OD打开kyodai.exe,Ctrl + N显示调用API,找到SetTimer,在每个参考上设置断点,F9运行,果然程序被断了下来:
0040C5D8 . 8B3D 58B74400 mov edi,dword ptr ds:[<&USER32.SetTimer>; USER32.SetTimer //断在这里
0040C5DE . 53 push ebx ; /Timerproc = NULL
0040C5DF . 6A 28 push 28 ; |Timeout = 40. ms
0040C5E1 . 53 push ebx ; |TimerID = 0
0040C5E2 . FF76 20 push dword ptr ds:[esi+20] ; |hWnd = 001A034E (';QQ连连看';,class=';#32770';)
0040C5E5 . FFD7 call near edi ; \SetTimer
0040C5E7 . 53 push ebx ; /Timerproc
0040C5E8 . 6A 28 push 28 ; |Timeout = 40. ms
0040C5EA . 6A 01 push 1 ; |TimerID = 1
0040C5EC . FF76 20 push dword ptr ds:[esi+20] ; |hWnd
0040C5EF . FFD7 call near edi ; \SetTimer
0040C5F1 . 53 push ebx ; /Timerproc
0040C5F2 . 68 30750000 push 7530 ; |Timeout = 30000. ms
0040C5F7 . 6A 02 push 2 ; |TimerID = 2
0040C5F9 . FF76 20 push dword ptr ds:[esi+20] ; |hWnd
0040C5FC . FFD7 call near edi ; \SetTimer
0040C5FE . 53 push ebx ; /Timerproc
0040C5FF . 68 E8030000 push 3E8 ; |Timeout = 1000. ms
0040C604 . 6A 03 push 3 ; |TimerID = 3
0040C606 . FF76 20 push dword ptr ds:[esi+20] ; |hWnd
0040C609 . FFD7 call near edi ; \SetTimer
哈,果然有好多个Timer呢,到底应该是哪一个呢?最笨的办法,一个一个的排除。
首先,跳过第一个Timer,在OD中0040C5DE处直接修改为处以下指令:
0040C5DE /EB 07 jmp short kyodai.0040C5E7
0040C5E0 |90 nop
然后用WINHEX打开kyodai.exe,定位到0xC5DE,修改53 6A 28 -> EB 07 90,保存(记得备份文件哦^_^)。再次从游戏大厅启动QQ连连看,发现“练习”键已经不能正常的被激活了...就是它了,猜想2正确,呵呵~~。
可是Timerproc = NULL,要怎么才能找出这个Timer的处理代码呢?
……
二、针对原因,找到切入点
在这之前,为了找出Timer的处理代码,走了好多的弯路,而且还是不得其法,还请高手赐教!
恢复原版kyodai.exe。再次接上网,从大厅启动连连看,打开OD附加kyodai.exe进程,ALT + E查看可执行模块,发现有几个模块在单独启动连连看的时候是不被加载的,如:SoundPlayer.dll,Language.dll... 猜想3:Timer不断监视程序状态,只有当满足一定条件的时候(什么条件?废话,如果知道了,还用猜吗?)就载入如SoundPlayer.dll,Language.dll等模块。好,终于有了新发现,重新来过。
用OD打开kyodai.exe,查找字符串参考,搜索“SoundPlayer.dll”,回车定位到代码段中:
004233EF |. 68 1C984500 push kyodai.0045981C ; ASCII "SoundPlayer.dll"
004233F4 |. C645 FC 02 mov byte ptr ss:[ebp-4],2
004233F8 |. FF30 push dword ptr ds:[eax]
004233FA |. 8D45 E8 lea eax,[local.6]
004233FD |. 68 AC804500 push kyodai.004580AC ; ASCII "%s%s"
00423402 |. 50 push eax
00423403 |. E8 5A440100 call
我们向上追索到这一过程的开始:
0042314C /$ B8 8C7A4400 mov eax,kyodai.00447A8C ; //尝试在这里下断
00423151 |. E8 0A4C0100 call kyodai.00437D60
00423156 |. 83EC 68 sub esp,68
00423159 |. 53 push ebx
0042315A |. 56 push esi
0042315B |. 8BF1 mov esi,ecx
0042315D |. 68 4C984500 push kyodai.0045984C ; ASCII "LongTimeInit"
00423162 |. 8D4D F0 lea ecx,[local.4]
00423165 |. E8 F2460100 call
尝试在0042314C下断,未能断下。鼠标定位到:
0042314C /$ B8 8C7A4400 mov eax,kyodai.00447A8C ; //尝试在这里下断
看到OD有这么个提示:
*****************************
* 00447A8C=kyodai.00447A8C *
* Local Call from 00425129 *
*****************************
右键 -> 前往CALL 来自 00425129,到达这里:
0042511A . FF75 0C push dword ptr ss:[ebp+C] ; /Arg2
0042511D . 8BCF mov ecx,edi ; |
0042511F . FF75 08 push dword ptr ss:[ebp+8] ; |Arg1
00425122 . E8 53290000 call kyodai.00427A7A ; \kyodai.00427A7A
00425127 . 8BCF mov ecx,edi
00425129 . E8 1EE0FFFF call kyodai.0042314C ; //这句就是CALL进刚才的代码了
0042512E . E9 06150000 jmp kyodai.00426639
继续向上追索...
00424FAF . B8 3E7E4400 mov eax,kyodai.00447E3E ; //这里应该是过程的开始,尝试下断00424FB4 . E8 A72D0100 call kyodai.00437D60
00424FB9 . 81EC AC0A0000 sub esp,0AAC
00424FBF . 53 push ebx
00424FC0 . 56 push esi
00424FC1 . 8BF1 mov esi,ecx
00424FC3 . 33DB xor ebx,ebx
00424FC5 . 8B4D 08 mov ecx,dword ptr ss:[ebp+8]
00424FC8 . 57 push edi
00424FC9 . 3BCB cmp ecx,ebx
00424FCB . 0F84 77160000 je kyodai.00426648
00424FD1 . 395D 0C cmp dword ptr ss:[ebp+C],ebx
00424FD4 . 0F8E 6E160000 jle kyodai.00426648
00424FDA . 0FBF41 06 movsx eax,word ptr ds:[ecx+6]
00424FDE . 83F8 2C cmp eax,2C ; Switch (cases 1..72)
在00424FAF下断,还是未能断下,就是说幕后黑手还在前面呢,揪它出来!嘿嘿~~ 可是这次OD没有提示这过程的来源,怎么办?一不做二 不休,如果这个过程是从其他地方CALL进来的话,那么在这过程的一开时esp里面就应该存放了将要返回的地址。好,在00424FAF处键入以下代码:
00424FAF 8B0424 mov eax,dword ptr ss:[esp] ; //修改这里的代码
00424FB2 BA 00084600 mov edx,kyodai.00460800 ; //这个地址好像不会写进东西的
00424FB7 8902 mov dword ptr ds:[edx],eax
00424FB9 EB 00 jmp short kyodai.00424FBB
00424FBB ^ EB FC jmp short kyodai.00424FB9
二进制:8B0424BA000846008902EB00EBFC
WINHEX打开kyodai.exe,替换B83E7E4400E8A72D010081ECAC0A 为 8B0424BA000846008902EB00EBFC 保存(记得备份)。
连网,从大厅启动连连看,发现游戏载入后就停了下来,因为刚才我们叫它停在00424FB9这里啊。WINHEX打开kyodai.exe的主要内存,定位到00460800(记得,我们刚才把[esp]搬到这里来了),哈哈,还不是你!00460800: 0B B5 42 00,倒过来就是0042B50B。那就是说这过程完成后将会返回到0042B50B,好,再来!
恢复原版kyodai.exe。OD载入,F9运行,Ctrl + G:0042B50B
0042B508 |. FF50 04 call near dword ptr ds:[eax+4] ; //这就是我们跟踪的CALL了
0042B50B |. EB 0E jmp short kyodai.0042B51B ; //返回到这里
向上看:
0042B4A5 /$ 55 push ebp ; //过程的开始
0042B4A6 |. 8BEC mov ebp,esp
0042B4A8 |. 83EC 18 sub esp,18
0042B4AB |. 53 push ebx
在0042B4A5我们找到了这一过程的开始,尝试下断点,嘿嘿,居然断了下来,F9一次,又断了下来,好极了!我们苦苦追寻的“幕后黑手”应该就是这里了。
三、对症下药
到了这一步,相信都不用我说了,大家知道该怎么着了吧。就是修改关键跳转,把程序引导到我们喜欢的地方去……下面就只贴出要修改的地方:
0042B4BC |. 837B 2C 00 cmp dword ptr ds:[ebx+2C],0 ; //运行到这里,修改堆栈数值为1,使其不跳
//堆栈 ds:[0012A38C]=00000000
0042B4C0 |. C745 FC 01000000 mov [local.1],1
0042B4C7 |. 7E 6E jle short kyodai.0042B537 ; //当然也可以在这里修改标志位使不跳
0042B4D4 |. F3:A5 rep movs dword ptr es:[edi],dword ptr d>; //这里访问无效内存,NOP掉
0042B4E2 |. /74 1C je short kyodai.0042B500 ; je -> jmp
00425025 . /0F84 AF000000 je kyodai.004250DA ; je -> jmp
很好,经过上面的修改,QQ连连看在OD下乖乖的跑起来了,该load的模块也load了,可是当我看到那“练习”键依然呆呆的“灰”在那里,我又范傻了,怎么,我的小皇帝啊,你怎么还不听话……
又跟踪了好久,好久……(其实我也忘了是怎么跟出来的,可能有点运气的成分吧^_^),终于找到了这里:
0040B3C3 |. 837E 50 01 cmp dword ptr ds:[esi+50],1 ; //判断按钮状态0--激活,1--变灰
//堆栈ds:[00ABA9A0]=00000001 ; //这个对应是练习键
试着将ds:[00ABA9A0]=00000001 改为 ds:[00ABA9A0]=00000000 ,哈哈~~ “练习”键果然被激活了,连忙用鼠标大力点下去,哇,好熟悉的画面哦……游戏开始了!慢慢享受成功的喜悦吧 ^_^
四、总结
原来QQ连连看不但做得“漂亮”,而且在反跟踪方面也下了一定的功夫,比如对于重要的CALL都采用的诸如:call near dword ptr ds:[eax+4]这样的形式,有效的防止了静态的跟踪。不过现在,我们只对腾讯说声对不起了!
五、编写LOADER
有了上面几个要修改的关键地方,我们可以在自己熟悉的编程环境下轻松的写个LOADER了(毕竟直接修改人家的程序那样不好)。
很晚了,明天还要早起,这就留着给你们自己练习好了。当然你也可以在我的网站(http://www.outerset.com/down.asp)找到已经做好了的QQ连连看脱机版。
很感谢您能有耐心看完这篇“流水帐”,欢迎批评指正。 |