论坛: 编程破解 标题: [转帖]手把手教您打造QQ连连看脱机版 复制本贴地址    
作者: yongmin [yongmin]    论坛用户   登录
前言:因老婆喜欢玩连连看,整天跟我抢着上网,所以突发奇想:把它变成可以脱机玩的那不就好了吗。所以有了下文(在这里,假设您已经熟悉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 <jmp.&MFC42.#2818_CString::Format>

    我们向上追索到这一过程的开始:

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 <jmp.&MFC42.#537_CString::CString>

    尝试在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连连看脱机版。

    很感谢您能有耐心看完这篇“流水帐”,欢迎批评指正。

地主 发表时间: 06-11-25 10:23

论坛: 编程破解

20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon

粤ICP备05087286号