现在的位置: 首页 > 综合 > 正文

若干个游戏辅助的分析手记(三)

2012年06月18日 ⁄ 综合 ⁄ 共 7084字 ⁄ 字号 评论关闭

 

 

 

若干个游戏辅助的分析手记(三)

----飞五棋牌平台幸运骰子自动投注

目标进程进程名(幸运骰子):Sicbo.exe

 

  OK,开工。
  进入游戏后,用OD附加,随后设断点:bp send,然后下注。没有断下,依次断WSASend等函数都断不下来。此路不通,祭出CE。
  CE搜索投注额,最后定为到下面代码:

0040303A - 89 18  - mov [eax],ebx // 修改了自己在东风的押注数额


  先走马观花逛一圈,一路回溯会先经过GamePubl.dll模块,最后会回溯到ProcMsg模块。在ProcMsg模块中是一个大的消息循环。这几个模块的相关CALL浪费了分析了整整一个通宵的时间,=_=!最后终于搞明白了它的大体框架,但是让我崩溃的是----随后得出的结论这几个CALL仅仅是根据消息更新界面(即相当于CE搜到的是界面的"Text"),所以得另寻方法。

  哎,一晚上的体力活没想最后成了杨白劳。睡一觉起来再说。

  zzZZZ.。o0O...
  

  一觉起来顿觉神清气爽。昨晚运气不佳,浪费了一个通宵。这活不但要看体力,还有一部分运气也是非常重要的。好了,不灰心。继续开工。

  整理下思路----经过昨天一个晚上的分析,既然知道了上面是根据消息来更新界面,那么得找到消息的源头。在OD中对Sicbo.exe的主窗口下WM_LBUTTONUP消息断点,断下来后,返回程序领空,来到下面代码:

10011AC0 >|$  53            PUSH EBX
10011AC1  |.  55            PUSH EBP
10011AC2  |.  56            PUSH ESI
10011AC3  |.  8BF1          MOV ESI,ECX
10011AC5  |.  8B86 08020000 MOV EAX,DWORD PTR DS:[ESI+208]
10011ACB  |.  33DB          XOR EBX,EBX
10011ACD  |.  85C0          TEST EAX,EAX
10011ACF  |.  57            PUSH EDI
10011AD0  |.  0F8E 95000000 JLE GamePubl.10011B6B
10011AD6  |.  8B6C24 1C     MOV EBP,DWORD PTR SS:[ESP+1C]
10011ADA  |.  8D9B 00000000 LEA EBX,DWORD PTR DS:[EBX]
10011AE0  |>  85DB          /TEST EBX,EBX
10011AE2  |.  0F8C 9E000000 |JL GamePubl.10011B86
10011AE8  |.  3B9E 08020000 |CMP EBX,DWORD PTR DS:[ESI+208]
10011AEE  |.  0F8D 92000000 |JGE GamePubl.10011B86
10011AF4  |.  8B86 FC010000 |MOV EAX,DWORD PTR DS:[ESI+1FC]
10011AFA  |.  8B0C98        |MOV ECX,DWORD PTR DS:[EAX+EBX*4]
10011AFD  |.  8A41 56       |MOV AL,BYTE PTR DS:[ECX+56]
10011B00  |.  84C0          |TEST AL,AL
10011B02  |.  8D3C9D 000000>|LEA EDI,DWORD PTR DS:[EBX*4]
10011B09  |.  74 51         |JE SHORT GamePubl.10011B5C
10011B0B  |.  3B9E 08020000 |CMP EBX,DWORD PTR DS:[ESI+208]
10011B11  |.  7D 73         |JGE SHORT GamePubl.10011B86
10011B13  |.  8B96 FC010000 |MOV EDX,DWORD PTR DS:[ESI+1FC]
10011B19  |.  8B043A        |MOV EAX,DWORD PTR DS:[EDX+EDI]
10011B1C  |.  8A48 55       |MOV CL,BYTE PTR DS:[EAX+55]
10011B1F  |.  84C9          |TEST CL,CL
10011B21  |.  74 39         |JE SHORT GamePubl.10011B5C
10011B23  |.  3B9E 08020000 |CMP EBX,DWORD PTR DS:[ESI+208]
10011B29  |.  7D 5B         |JGE SHORT GamePubl.10011B86
10011B2B  |.  8BC2          |MOV EAX,EDX
10011B2D  |.  8B0C38        |MOV ECX,DWORD PTR DS:[EAX+EDI]
10011B30  |.  03C7          |ADD EAX,EDI
10011B32  |.  E8 39F7FEFF   |CALL GamePubl.?GetVisible@CCardCtrl@@QAE>
10011B37  |.  84C0          |TEST AL,AL
10011B39  |.  74 21         |JE SHORT GamePubl.10011B5C
10011B3B  |.  3B9E 08020000 |CMP EBX,DWORD PTR DS:[ESI+208]
10011B41  |.  7D 43         |JGE SHORT GamePubl.10011B86
10011B43  |.  8B4C24 18     |MOV ECX,DWORD PTR SS:[ESP+18]
10011B47  |.  8B5424 14     |MOV EDX,DWORD PTR SS:[ESP+14]
10011B4B  |.  8B86 FC010000 |MOV EAX,DWORD PTR DS:[ESI+1FC]
10011B51  |.  55            |PUSH EBP
10011B52  |.  51            |PUSH ECX
10011B53  |.  8B0C38        |MOV ECX,DWORD PTR DS:[EAX+EDI]
10011B56  |.  52            |PUSH EDX
10011B57  |.  E8 C426FFFF   |CALL GamePubl.?OnLButtonUp@CCardCtrl@@QA>
10011B5C  |>  8B86 08020000 |MOV EAX,DWORD PTR DS:[ESI+208]
10011B62  |.  43            |INC EBX
10011B63  |.  3BD8          |CMP EBX,EAX
10011B65  |.^ 0F8C 75FFFFFF \JL GamePubl.10011AE0
10011B6B  |>  8BCE          MOV ECX,ESI
10011B6D  |.  E8 CC430000   CALL <JMP.&MFC71.#1903_?Default@CWnd@@IAE>
10011B72  |.  C686 28020000>MOV BYTE PTR DS:[ESI+228],0;返回程序领空后回到这里       10011B79  |.  FF15 C4D80110 CALL DWORD PTR DS:[<&USER32.ReleaseCaptur> [ReleaseCapture
10011B7F  |.  5F            POP EDI
10011B80  |.  5E            POP ESI
10011B81  |.  5D            POP EBP
10011B82  |.  5B            POP EBX
10011B83  |.  C2 0C00       RETN 0C

  回到程序领空的时候是停在了VA:10011B72,下面开始分析。
  因为真正的投注(网络操作)跟用户界面更新是分开的,所以为了方便分析,要得找到网络操作跟用户界面更新的分界线,因为bp send行不通,所以换个方法。
  打开虚拟机,在虚拟机中用另一个账号登陆游戏后申请坐庄,接着回到本机。
  在上面的函数的开头F2下断,即下面这句代码下断:

10011AC0 >|$  53            PUSH EBX

  在本机投注后,程序断了下来,接着观察虚拟机中发现已经有了投注信息,说明网络操作的代码不在这个代码段中。OK,回溯到上一层,继续上面的思路。
  下面代码是上一层的代码:

  

00409670   .  53            PUSH EBX
00409671   .  8B1D A4E04000 MOV EBX,DWORD PTR DS:[<&GDI32.PtInRegion>>;  GDI32.PtInRegion
00409677   .  55            PUSH EBP
00409678   .  8B6C24 14     MOV EBP,DWORD PTR SS:[ESP+14]             ;  第三个参数 Y
0040967C   .  56            PUSH ESI
0040967D   .  57            PUSH EDI
0040967E   .  8B7C24 18     MOV EDI,DWORD PTR SS:[ESP+18]             ;  第二个参数 X
00409682   .  8BF1          MOV ESI,ECX
00409684   .  8BCD          MOV ECX,EBP
00409686   .  51            PUSH ECX                                  ; /Y
00409687   .  8BC7          MOV EAX,EDI                               ; |
00409689   .  50            PUSH EAX                                  ; |X
0040968A   .  8B86 CC040000 MOV EAX,DWORD PTR DS:[ESI+4CC]            ; |
00409690   .  50            PUSH EAX                                  ; |hRegion
00409691   .  FFD3          CALL EBX                                  ; \PtInRegion
00409693   .  85C0          TEST EAX,EAX
00409695   .  0F84 9F000000 JE Sicbo.0040973A
0040969B   .  80BE 02060000>CMP BYTE PTR DS:[ESI+602],1
004096A2   .  0F85 92000000 JNZ Sicbo.0040973A
004096A8   .  80BE 01060000>CMP BYTE PTR DS:[ESI+601],1
004096AF   .  0F85 85000000 JNZ Sicbo.0040973A
004096B5   .  8BCD          MOV ECX,EBP
004096B7   .  51            PUSH ECX                                  ; /Y
004096B8   .  8B8E AC040000 MOV ECX,DWORD PTR DS:[ESI+4AC]            ; |
004096BE   .  8BC7          MOV EAX,EDI                               ; |
004096C0   .  50            PUSH EAX                                  ; |X
004096C1   .  51            PUSH ECX                                  ; |hRegion
004096C2   .  FFD3          CALL EBX                                  ; \PtInRegion
004096C4   .  85C0          TEST EAX,EAX
004096C6   .  74 04         JE SHORT Sicbo.004096CC
004096C8   .  B3 01         MOV BL,1
004096CA   .  EB 3F         JMP SHORT Sicbo.0040970B
004096CC   >  8B96 B4040000 MOV EDX,DWORD PTR DS:[ESI+4B4]
004096D2   .  8BCD          MOV ECX,EBP
004096D4   .  51            PUSH ECX
004096D5   .  8BC7          MOV EAX,EDI
004096D7   .  50            PUSH EAX
004096D8   .  52            PUSH EDX
004096D9   .  FFD3          CALL EBX
004096DB   .  85C0          TEST EAX,EAX
004096DD   .  74 04         JE SHORT Sicbo.004096E3
004096DF   .  B3 02         MOV BL,2
004096E1   .  EB 28         JMP SHORT Sicbo.0040970B
004096E3   >  55            PUSH EBP
004096E4   .  57            PUSH EDI
004096E5   .  8D8E B8040000 LEA ECX,DWORD PTR DS:[ESI+4B8]
004096EB   .  E8 C0D6FFFF   CALL Sicbo.00406DB0
004096F0   .  85C0          TEST EAX,EAX
004096F2   .  74 04         JE SHORT Sicbo.004096F8
004096F4   .  B3 03         MOV BL,3
004096F6   .  EB 13         JMP SHORT Sicbo.0040970B
004096F8   >  55            PUSH EBP
004096F9   .  57            PUSH EDI
004096FA   .  8D8E C0040000 LEA ECX,DWORD PTR DS:[ESI+4C0]
00409700   .  E8 ABD6FFFF   CALL Sicbo.00406DB0
00409705   .  85C0          TEST EAX,EAX
00409707   .  74 31         JE SHORT Sicbo.0040973A
00409709   .  B3 04         MOV BL,4
0040970B   >  E8 12260000   CALL <JMP.&MFC71.#1091_?AfxGetThread@@YGP>
00409710   .  85C0          TEST EAX,EAX
00409712   .  74 09         JE SHORT Sicbo.0040971D
00409714   .  8B10          MOV EDX,DWORD PTR DS:[EAX]
00409716   .  8BC8          MOV ECX,EAX
00409718   .  FF52 7C       CALL DWORD PTR DS:[EDX+7C]
0040971B   .  EB 02         JMP SHORT Sicbo.0040971F
0040971D   >  33C0          XOR EAX,EAX
0040971F   >  0FB696 550800>MOVZX EDX,BYTE PTR DS:[ESI+855]
00409726   .  8B40 20       MOV EAX,DWORD PTR DS:[EAX+20]
00409729   .  0FB6CB        MOVZX ECX,BL
0040972C   .  51            PUSH ECX                                  ; /lParam
0040972D   .  52            PUSH EDX                                  ; |wParam
0040972E   .  68 C9040000   PUSH 4C9                                  ; |Message = MSG(4C9)
00409733   .  50            PUSH EAX                                  ; |hWnd
00409734   .  FF15 34E54000 CALL DWORD PTR DS:[<&USER32.SendMessageA>>; \这里是下注关键
0040973A   >  8B4C24 14     MOV ECX,DWORD PTR SS:[ESP+14]
0040973E   .  55            PUSH EBP
0040973F   .  57            PUSH EDI
00409740   .  51            PUSH ECX
00409741   .  8BCE          MOV ECX,ESI
00409743   .  C686 02060000>MOV BYTE PTR DS:[ESI+602],0
0040974A   .  FF15 CCE04000 CALL DWORD PTR DS:[<&GamePublic.?OnLButto>;  GamePubl.?OnLButtonUp@CGameFrameView@@QAEXIVCPoint@@@Z
00409750   .  5F            POP EDI
00409751   .  5E            POP ESI
00409752   .  5D            POP EBP
00409753   .  5B            POP EBX
00409754   .  C2 0C00       RETN 0C

  

  按照上面的思路,依然在函数头下断,投注后程序断了下来,观察虚拟机中此次并没有投注信息,很好!这段代码就是关键了!
  重点分析此段代码。
  首先分析该函数的参数,这个函数一共有3个参数,第一个参数是什么没去分析了这个不是重点。重点是第二个参数代表X坐标,第三个参数是Y坐标。
  函数开头的代码是把XY的坐标传进PtInRegion来判断投注区。随后对XY坐标进行转化成相应投注区的索引。
  继续往下看代码发现了这里:

0040972C   .  51            PUSH ECX                                  ; /lParam
0040972D   .  52            PUSH EDX                                  ; |wParam
0040972E   .  68 C9040000   PUSH 4C9                                  ; |Message = MSG(4C9)
00409733   .  50            PUSH EAX                                  ; |hWnd
00409734   .  FF15 34E54000 CALL DWORD PTR DS:[<&USER32.SendMessageA>>; \这里是下注关键

  

  

  这里的代码非常非常可疑,因为这里是一个SendMessage的调用,还记得刚才说要找界面更新的消息源头么?为了验证这个SendMessage,在 00409734   .  FF15 34E54000 CALL DWORD PTR DS:[<&USER32.SendMessageA>> 这句代码下断,游戏投注断了下来,观察虚拟机中没有投注信息,回到本机单步执行该条语句,再次回到虚拟中发现了投注信息,说明这里就是下注的关键了!已经离成功很近了。

  下面着重分析SendMessage的参数 首先是HWND,该句柄通过SPY++查找,发现该句柄就是游戏本身主窗口的句柄了, 接着是消息号是4C9,很明显这是一个自定义的消息。 WPARAM 是投注筹码的索引, LPARAM 是投注区域的索引。 OK了,参数分析完毕。如下:

SendMessage( 

HWND hWnd,      // 游戏本身主窗口的句柄 

UINT Msg,      // 4C9,自定义的消息 

WPARAM wParam,  // 投注筹码的索引,2是1000,3是10000以此类推

LPARAM lParam   // 投注区域的索引,1是东,2是南以此类推

);

  

  那么游戏本身实现投注就是靠SendMessage来传递一个自定义的消息,而该自定义的消息处理函数内部进行了什么处理在这里不用去分析已经可以得出结论:该自定义消息处理函数内部进行投注的网络操作,网络操作完毕后,随后再次发送一个自定义消息来更新界面,这里就解释了第一天通宵的时候跟的那几个CALL是在一个消息循环里的原因了。 所以我们不必去分析该自定义的消息处理函数了,因为我们也可以直接向该窗口发送此消息就OK。因为SendMessage是跨进程的,这样做没有任何问题。 有了上面的参数分析,非常容易就写出投注的测试程序。这里提一下一点比较有意思的事情是,投注额的索引是从2开始,2代表1000.我们可以传递“1”。这样虽然在游戏中没有100元的筹码,但是我们可以投注100.呵呵,有意思。

  至此,投注的功能已经搞定。

  后记:投注功能写好后,就是根据客户提供的“赌徒算法”,进行挂机自动投注了。测试了几次,短时间(连续挂一两个小时)收益还不错。但是长时间比如每天睡觉的时候挂机,起床的时候,发现有赢有亏,看来“赌徒算法”有待改进,哈哈。

 

抱歉!评论已关闭.