【新兵申请转正】一个小游戏的分析和注入

2016-07-22 14:36:34 11 3136

经典游戏
分析:
1.        玩游戏,背后操作的API
定时器函数: SetTimer   KillTimer
窗口大小变化:MoveWindow   SetWindowPos
自定义设置: 弹出对话框 DialogBoxParam CreateDialog
窗口回调函数: CreateWindowEx WindowProc
随机函数: rand

API分析
工具: OD/IDA
方法:下各种断点分析
     API断点 (可疑API)
     条件断点 (回调函数过滤信息)
     访问断点 (可疑数据)

2.        游戏中的数据(变量\数组\....)
高度,宽度,雷数, 扫雷数组
表现形式: 全局变量,局部变量, new出来的缓冲区
一般小程序为全局变量: 扫雷\俄罗斯方块\连连看
全局变量的特点,固定大小,或者是一个有穷的空间

工具: CE(Cheat Engine) OD
方法: 猜 - 查找数据,调试分析数据
      猜 数据类型,数据范围
      根据特定值,找到值所在的地址
      例如: 扫雷数组的高度等


CE中指针寻址

指针3 = 指针2
指针2 = 指针1
指针1 = 地址
地址 = 值
Int num = 100;
Int* pNum = #
Int** ppNum = &pNum;
Int*** pppNum = &ppNum;

Step 8
i386.exe"+231390=631390
[631390] = 018C6AB8
[018C6AB8+0C] = 018912A0
[018912A0+14] = 035C3008
[035C3008] = 01827520
[01827520+18]=942


分析步骤
1.        使用CE分析扫雷程序中的数据


2.        根据在CE中查找的数据,在OD查看内存
发现了看似很像数组的一块缓冲区,通过修改宽度\高度,观察内存,最终分析出内存中标记所代表的意思
01005330  0A 00 00 00 0E 00 00 00 0E 00 00 00 00 00 00 00  ......
01005340  10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10  တတတတတတတတ
01005350  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005360  10 0F 0F 0F 8F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐༏ྏ༏༏༏༏ဏ
01005370  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005380  10 0F 0F 8F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐輏༏༏༏༏༏ဏ
01005390  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
010053A0  10 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐༏༏༏༏༏༏ဏ
010053B0  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
010053C0  10 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐༏༏༏༏༏༏ဏ
010053D0  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
010053E0  10 0F 0F 0F 0F 0F 0F 0F 0F 0F 8F 0F 0F 0F 0F 10  ༐༏༏༏༏ྏ༏ဏ
010053F0  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005400  10 0F 0F 0F 8F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐༏ྏ༏༏༏༏ဏ
01005410  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005420  10 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐༏༏༏༏༏༏ဏ
01005430  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005440  10 0F 0F 0F 0F 8F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐༏輏༏༏༏༏ဏ
01005450  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005460  10 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 8F 0F 0F 10  ༐༏༏༏༏༏ྏဏ
01005470  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005480  10 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐༏༏༏༏༏༏ဏ
01005490  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
010054A0  10 0F 0F 0F 0F 8F 0F 0F 0F 0F 8F 0F 0F 0F 0F 10  ༐༏輏༏༏ྏ༏ဏ
010054B0  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
010054C0  10 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 10  ༐༏༏༏༏༏༏ဏ
010054D0  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
010054E0  10 0F 0F 0F 0F 0F 0F 0F 8F 0F 0F 0F 0F 0F 0F 10  ༐༏༏༏ྏ༏༏ဏ
010054F0  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005500  10 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 8F 0F 10  ༐༏༏༏༏༏輏ဏ
01005510  0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F  ༏༏༏༏༏༏༏༏
01005520  10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10  တတတတတတတတ
缓冲区的值:
10 边界
0F 填充值,初始化之后的默认值
8F 雷
40-48 表示当前位置周围的雷数

3.        在扫雷数组上下写入断点,可以断到初始化数组的地方,进一步分析
4.        01002ED5 >mov eax,0x360
5.        01002EDA  dec eax
6.        01002EDB  mov byte ptr ds:[eax+<扫雷数组>],0xF
7.        01002EE2  jnz short winmine.01002EDA
8.        01002EE4  mov ecx,dword ptr ds:[<高度>]
9.        01002EEA  mov edx,dword ptr ds:[<宽度>]
10.        01002EF0  lea eax,dword ptr ds:[ecx+0x2]
11.        01002EF3  test eax,eax
12.        01002EF5  push esi
13.        01002EF6  je short winmine.01002F11
14.        01002EF8  mov esi,edx                                    ; 高度
15.        01002EFA  shl esi,0x5
16.        01002EFD  lea esi,dword ptr ds:[esi+0x1005360]
17.        01002F03  dec eax
18.        01002F04  mov byte ptr ds:[eax+<扫雷数组>],0x10              ; 填充边界
19.        01002F0B  mov byte ptr ds:[esi+eax],0x10                 ; 填充边界
20.        01002F0F  jnz short winmine.01002F03
21.        01002F11  lea esi,dword ptr ds:[edx+0x2]
22.        01002F14  test esi,esi
23.        01002F16  je short winmine.01002F39
24.        01002F18  mov eax,esi
25.        01002F1A  shl eax,0x5
26.        01002F1D  lea edx,dword ptr ds:[eax+<扫雷数组>]
27.        01002F23  lea eax,dword ptr ds:[eax+ecx+0x1005341]
28.        01002F2A  sub edx,0x20
29.        01002F2D  sub eax,0x20
30.        01002F30  dec esi
31.        01002F31  mov byte ptr ds:[edx],0x10                     ; 填充边界
32.        01002F34  mov byte ptr ds:[eax],0x10                     ; 填充边界
33.        01002F37  jnz short winmine.01002F2A
34.        01002F39  pop esi
35.        01002F3A  retn36.       
跟踪到初始化扫雷数组函数的上一层,可以找到生成雷的地方
010036B7               mov eax,dword ptr ds:[<雷数>]
010036BC               mov dword ptr ds:[0x1005160],edi
010036C2               mov dword ptr ds:[<雷数>],eax
010036C7               push dword ptr ds:[<高度>]                       ; 循环开始随机生成雷---------------
010036CD               call <winmine.生成随机数>
010036D2               push dword ptr ds:[<宽度>]
010036D8               mov esi,eax
010036DA               inc esi
010036DB               call <winmine.生成随机数>
010036E0               inc eax
010036E1               mov ecx,eax
010036E3               shl ecx,0x5
010036E6               test byte ptr ds:[ecx+esi+<扫雷数组>],0x80
010036EE               jnz short winmine.010036C7
010036F0               shl eax,0x5
010036F3               lea eax,dword ptr ds:[eax+esi+<扫雷数组>]
010036FA               or byte ptr ds:[eax],0x80                      ; 设置雷标记
010036FD               dec dword ptr ds:[<雷数>]
01003703               jnz short winmine.010036C7                     ; 循环结束--------------
01003705               mov ecx,dword ptr ds:[<宽度>]
0100370B               imul ecx,dword ptr ds:[<高度>]
01003712               mov eax,dword ptr ds:[<雷数>]
3.        要完成在界面能判断鼠标所在的位置下方的扫雷数组数据,需要一个转换函数
经过下写入断点,找到转换坐标的代码
01002099  8B45 14  mov eax,dword ptr ss:[ebp+0x14]     ; 获取lParam,低位x,高位y
0100209C  C1E8 10  shr eax,0x10                        ; 清除低位,获取高位,Y坐标
0100209F  83E8 27  sub eax,0x27                        ; 减去界面多余的高度
010020A2  C1F8 04  sar eax,0x4                         ; 转换为数组下标
010020A5  50      push eax                            ; y
010020A6  0FB745 14     movzx eax,word ptr ss:[ebp+0x14]    ; 获取低位
010020AA  83C0 04  add eax,0x4
010020AD  C1F8 04       sar eax,0x4                         ; 转换为数组下标
010020B0  50            push eax                            ; x
010020B1  E8 1E110000   call winmine.010031D4

4.        代码编写
在DLL中编写代码
如果用MFCDLL编写代码
创建MFCDLL工程,在生成app类中的InitInstance函数中编写代码DLL注入
注入之后再游戏里面可以随便玩




关于作者

Jacob10篇文章486篇回复

一切皆有可能

评论11次

要评论?请先  登录  或  注册