首页
社区
课程
招聘
[原创]两个简单的手机游戏分析
发表于: 2009-3-14 01:12 23278

[原创]两个简单的手机游戏分析

2009-3-14 01:12
23278
【文章标题】: 第一个-手机游戏爆破
【文章作者】: wangdell
【软件名称】: TextTwist.exe
【下载地址】: 自己搜索下载
【编写语言】: arm
【使用工具】: IDA  WM6SDK UE
【操作平台】: wince
--------------------------------------------------------------------------------
【详细过程】
  老婆手机中很多小游戏,都需要注册。一直想看看wince到底是怎么回事。弄了两天,终于搞懂一些。刚开始看指令,
  好象不太难,以为很简单,但里面是非明码比较,无法追码,算法看了半天也没看懂,可能是用了什么现成的算法库。
  有时间再细研究吧,手机游戏的处女破,就不和她缠绵了,先爆破一下。hiahia.
  1、准备
  1.1IDA 打开Texttwister.exe。静态分析。
  1.2开Activesync。文件=>连接设置 中 选择DMA。
  1.3开启WM6SDK带的设仿真器管理器,选Pocket pc 20003 SE仿真程序,右键“连接”。
  1.4选Pocket pc 20003 SE仿真程序,右键“插入底座”。等待activysync和仿真器连接和同步。
  1.5真机中试运行,在程序底部tools->register菜单中,可进入注册对话框,提示输入用户名和密码。
  
  2、调试
   在IDA的imports中浏览api,看到DialogBoxIndirectParamW.按x查调用处,并在其上尝试设断。最终找到
  
  .text:00015B28 MOV     R3, #0
  .text:00015B2C MOV     R1, R0          ; hDialogTemplate
  .text:00015B30 STR     R3, [SP,#0x29C+dwInitParam]
  .text:00015B34 LDR     R3, =regdlgporc ; lpDialogFunc
  .text:00015B38 MOV     R2, R6          ; hWndParent
  .text:00015B3C LDR     R0, [R4]        ; hInstance
  .text:00015B40 BL      DialogBoxIndirectParamW
  

  为注册对话框调用处。
  进入regdlgproc中看到
  
  .text:00015988  SUB     SP, SP, #0x35C
  .text:0001598C MOV     R3, #WM_INITDIALOG
  .text:00015990 MOV     R4, R0
  .text:00015994  CMP     R1, R3
  .text:00015998 BEQ     loc_15A18
  .text:0001599C MOVL    R3, WM_COMMAND
  .text:000159A4 CMP     R1, R3
  .text:000159A8 BNE     loc_159C4
  .text:000159AC MOV     R3, R2,LSL#16
  .text:000159B0 MOV     R5, R3,LSR#16
  .text:000159B4CMP     R5, #1
  .text:000159B8 BEQ     loc_159CC
  .text:000159BC CMP     R5, #2
  .text:000159C0 BEQ     loc_159CC
  .text:000159C4
  .text:000159C4  loc_159C4                               ; CODE XREF: regdlgporc+24j
  .text:000159C4 MOV     R0, #0
  .text:000159C8 B       loc_15AA8
  .text:000159CC                            ; ---------------------------------------------------------------------------
  .text:000159CC
  .text:000159CC                            loc_159CC                               ; CODE XREF: regdlgporc+34j
  .text:000159CC                                                                    ; regdlgporc+3Cj
  .text:000159CC LDR     R2, =name       ; lpString
  .text:000159D0 MOV     R3, #0x64 ; 'd' ; nMaxCount
  .text:000159D4 MOV     R1, #0x65 ; 'e' ; nIDDlgItem
  .text:000159D8 MOV     R0, R4          ; hDlg
  .text:000159DC BL      GetDlgItemTextW
  .text:000159E0 LDR     R2, =code       ; lpString
  .text:000159E4 MOV     R3, #0x64 ; 'd' ; nMaxCount
  .text:000159E8 MOV     R1, #0x66 ; 'f' ; nIDDlgItem
  .text:000159EC MOV     R0, R4          ; hDlg
  .text:000159F0 BL      GetDlgItemTextW
  .text:000159F4 MOV     R1, R5          ; nResult
  .text:000159F8 MOV     R0, R4          ; hDlg
  .text:000159FC BL      EndDialog
  .text:00015A00 MOV     R1, #1          ; st
  .text:00015A04 MOV     R0, R4          ; hwnd
  .text:00015A08 BL      SHSipPreference
  .text:00015A0C B       loc_15AA4
  

  用ida的grahview较易看出,其根据消息是#WM_INITDIALOG或WM_COMMAND分别处理。
  在其中的两个GetDlgItemTextW分别是获得name和code处。
  在相应位置设断。
  
  f9运行,ida提示与移动设备连接,并提示需下载到移动设备中,确定后,程序开始运行,中断后,单步跟踪来到
  
  .text:00015B78 MOV     R3, R0,LSL#16
  .text:00015B7C MOVS    R5, R3,ASR#16
  .text:00015B80      NOP
  .text:00015B84  MOV     R1, #1
  .text:00015B88 MOV     R0, R7
  .text:00015B8C BL      codecpy
  .text:00015B90 B       loc_15BB4
  .text:00015B94                            ; ---------------------------------------------------------------------------
  .text:00015B94   MOVL    R3, 0xFFFFFFEA
  .text:00015B98  CMP     R5, R3
  .text:00015B9C  BNE     loc_15BB0
  .text:00015BA0  MOVL    R0, 0x1B6C
  .text:00015BA8  BL      sub_155D0
  .text:00015BAC  B       loc_15BB4
  .text:00015BB0                            ; ---------------------------------------------------------------------------
  .text:00015BB0
  .text:00015BB0                            loc_15BB0                               ; CODE XREF: sub_15AB8+E4j
  .text:00015BB0 BL      sub_15F8C
  .text:00015BB4
  .text:00015BB4                            loc_15BB4                               ; CODE XREF: sub_15AB8+D8j
  .text:00015BB4                                                                    ; sub_15AB8+F4j
  .text:00015BB4 CMP     R5, #0
  .text:00015BB8 BNE     loc_15B04
  .text:00015BBC BL      sub_1876C
  .text:00015BC0
  .text:00015BC0                            loc_15BC0                               ; CODE XREF: sub_15AB8+98j
  .text:00015BC0 MOV     R0, #0
  .text:00015BC4
  .text:00015BC4                            loc_15BC4                               ; CODE XREF: sub_15AB8+40j
  .text:00015BC4 ADD     SP, SP, #0x288
  .text:00015BC8 LDMFD   SP!, {R4-R7,PC}
  

  00015BB4处是关键比较,如不等,则跳回再次调用注册对话框。
  向上翻
  
  .text:00015B40 BL      DialogBoxIndirectParamW
  .text:00015B44 MOV     R3, R0,LSL#16
  .text:00015B48 MOV     R3, R3,ASR#16
  .text:00015B4CCMP     R3, #1
  .text:00015B50 BNE     loc_15BC0
  .text:00015B54 CMP     R7, #0
  .text:00015B58 BEQ     loc_15B70
  .text:00015B5C MOV     R0, R7
  .text:00015B60 BL      codecheck_0
  

  看到15b60处,应为关键函数 跟进codecheck_0函数。
  
  .text:0001A6A8                            codecheck_0                             ; CODE XREF: sub_15AB8+A8p
  .text:0001A6A8                                                                    ; sub_19B38+14p ...
  .text:0001A6A8
  .text:0001A6A8                            name1           = -0x30C
  .text:0001A6A8                            var_28C         = -0x28C
  .text:0001A6A8                            name            = -0x288
  .text:0001A6A8
  .text:0001A6A8 STMFD   SP!, {R4,LR}
  .text:0001A6AC SUB     SP, SP, #0x304
  .text:0001A6B0 MOV     R4, R0
  .text:0001A6B4 MOV     R3, #0x284
  .text:0001A6B8 ADD     R0, SP, #0x30C+var_28C
  .text:0001A6BC STR     R3, [SP,#0x30C+var_28C]
  .text:0001A6C0 BL      regkey
  .text:0001A6C4 ADD     R1, SP, #0x30C+name ; wchar_t *
  .text:0001A6C8 ADD     R0, SP, #0x30C+name1 ; wchar_t *
  .text:0001A6CC BL      wcscpy
  .text:0001A6D0 MOV     R2, #1
  .text:0001A6D4 ADD     R1, SP, #0x30C+name1
  .text:0001A6D8 MOV     R0, R4
  .text:0001A6DC BL      codecheck
  .text:0001A6E0 ADD     SP, SP, #0x304
  .text:0001A6E4 LDMFD   SP!, {R4,PC}
  

  看到1a6dc处为关键函数。
  这里爆破吧,更改
  
  .text:0001A6DC 4A FD FF EB           BL      codecheck
  

  为
  
  .text:0001A6DC 00 00 A0 E3           MOV     R0, #0
  

  重新运行,任意即可注册成功。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年03月14日 1:13:24

【文章标题】: 第二个-手机游戏追码
【文章作者】: wangdell
【软件名称】: 美女麻将.exe
【软件大小】: 421K
【下载地址】: 自己搜索下载
【保护方式】: 无
【编写语言】: MFC?
【使用工具】: IDA ActiveSync WM6SDK
【操作平台】: Wince
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  又看了一个手机游戏,这个比较简单,内存中明码比较,适合我等新手。
  1.准备
  准备方法与上一篇相同。
    1.1IDA 打开"美女麻将.exe"。静态分析。
    1.2开Activesync。文件=>连接设置 中 选择DMA。
    1.3开启WM6SDK带的设仿真器管理器,选Pocket pc 20003 SE仿真程序,右键“连接”。
    1.4选Pocket pc 20003 SE仿真程序,右键“插入底座”。等待activysync和仿真器连接和同步。
    1.5真机中试运行,注意到程序启动有提示注册,时间限制为14天。进入注册对话框后,输入假码,会弹出messagebox,
  提示错误。
  
  2.分析
   在IDA中imports中浏览api,看到几个可疑函数
  .idata:0002B0A4 ; int __stdcall lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
  .idata:0002B0A4                 IMPORT __imp_lstrcmpiW  ; DATA XREF: .text:off_28F70o
  
  .idata:0002B258 ; __declspec(dllimport) int __cdecl AfxMessageBox(unsigned int, unsigned int, unsigned int)
  .idata:0002B258                 IMPORT __imp__AfxMessageBox__YAHIII_Z
  
  .idata:0002B034 ; int __stdcall MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
  .idata:0002B034                 IMPORT __imp_MessageBoxW ; DATA XREF: .text:off_28E20o
  
  按x,在相关调用处翻找代码。发现下面的可以代码:
 .text:00027FA0                 LDR     R1, =a105d088a0595 ; lpString2
  .text:00027FA4                 ADD     R0, SP, #0x32C+String1 ; lpString1
  .text:00027FA8                 BL      lstrcmpiW
  .text:00027FAC                 CMP     R0, #0
  .text:00027FB0                 BNE     loc_28008
  .text:00027FB4                 MOV     R0, #0xE1
  .text:00027FB8                 BL      sub_11374
  .text:00027FBC                 MOV     R1, R0          ; lpFormat
  .text:00027FC0                 ADD     R2, SP, #0x32C+String1
  .text:00027FC4                 ADD     R0, SP, #0x32C+Buffer ; lpBuffer
  .text:00027FC8                 BL      wsprintfW
  .text:00027FCC                 MOV     R1, #0x810
  .text:00027FD0                 ADD     R2, SP, #0x32C+Buffer
  .text:00027FD4                 ORR     R1, R1, #6
  .text:00027FD8                 MOV     R0, R5
  .text:00027FDC                 BL      _SetDlgItemText_CWnd__QAAXHPBG_Z ; CWnd::SetDlgItemText(int,ushort const *)
  .text:00027FE0                 MOVL    R1, 0x814
  .text:00027FE8                 MOV     R0, R5
  .text:00027FEC                 BL      _GetDlgItem_CWnd__QBAPAV1_H_Z ; CWnd::GetDlgItem(int)
  .text:00027FF0                 MOV     R1, #0
  .text:00027FF4                 BL      _ShowWindow_CWnd__QAAHH_Z ; CWnd::ShowWindow(int)
  .text:00027FF8                 ADD     R0, SP, #0x32C+var_28C
  .text:00027FFC                 BL      __1CDialog_tbc__UAA_XZ ; CDialog_tbc::~CDialog_tbc(void)
  .text:00028000                 ADD     SP, SP, #0x320
  .text:00028004                 LDMFD   SP!, {R4,R5,PC}
  .text:00028008 ; ---------------------------------------------------------------------------
  .text:00028008
  .text:00028008 loc_28008                               ; CODE XREF: sub_27F4C+64j
  .text:00028008                 MOVL    R2, 0xFFFFFFFF  ; unsigned int
  .text:0002800C                 MOV     R1, #0          ; unsigned int
  .text:00028010                 MOV     R0, #0xE2       ; unsigned int
  .text:00028014                 BL      _AfxMessageBox__YAHIII_Z ; AfxMessageBox(uint,uint,uint)

  注意到此处有用到strcmp和AfxMessageBox这两个函数。
  在00027FA0代码中的=a105d088a0595处双击跟随来到
  
.data:0002B340 a105d088a0595   unicode 0, <105D-088A-0595>,0 ; DATA XREF: .text:lpString2o

  这里就是真码"105D-088A-0595"
  在真机中输入这个注册码后,注册成功。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年03月14日 16:25:52

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (20)
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
2
感谢wangdell深夜辛苦发帖让大家在周末的早晨看到如此精彩的分析!确实分析的很准确,试验效果也很容易重现!

对于手头没有分析工具的朋友只需要用WinHex打开wangdell提供的附件查找4A FD FF EB并将这4个字节的数据修改为00 00 A0 E3保存即可。程序会读取手机用户名作为帐号,输入任何字符串都可以通过验证。
2009-3-14 10:18
0
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
3
前面接受看雪前辈的建议准备发个系列介绍WINCE/ARM指令、开发、破解方面的知识。目前正在准备中。这里先简单介绍些WINCE/ARM指令的基础知识方便大家了解wangdell提供的代码。
2009-3-14 10:26
0
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
4
首先请注意我们爆破的指令:

.text:0001A6DC 4A FD FF EB BL codecheck


这是调用验证函数指令。BL是ARM中的函数调用指令。B:代表跳转,L:代表连接。
这条指令的作用是:首先将该指令后面的一条指令的地址保存在连接寄存器r14中。然后跳转到BL后面的目的地址去。r14在ARM汇编中也常用lr代替。BL中的L就是指她。

代码中单独的一个B指令是无条件跳转指令。直接跳转到B后面的目的地址去。
2009-3-14 10:52
0
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
5
.text:00015BB4 CMP R5, #0
.text:00015BB8 BNE loc_15B04


分析这两条指令,第一条是比较r5寄存器中的数据和立即数0。

r5是一个通用寄存器,一般在函数中保存本函数中使用的临时数据,离开函数时要恢复r5原数据。而立即数0前面的"#"标志表示她是一个立即数,这是ARM语法的特点。

第二条BNE指令是“不相等(或不为0)跳转指令”:
B:是基础指令表示跳转。NE:表示"Not Equal"是“不相等”。
这条指令体现了前面介绍的ARM指令的特点:很多指令拥有标志位可以根据当前状态寄存器的标志位状态决定是否运行。
CMP R5, #0
比较后改变了标志位,BNE根据结果决定是否跳转。在ARM中不止B指令,像mov,add这样的指令都有标志位可以做这样的操作。
2009-3-14 10:54
0
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
6
ARM中函数参数传递规则:

ARM中函数参数传递规则和X86不同。ARM规则是:
当参数在4个以内时使用r0-r3寄存器分别传递1-4号参数。当参数个数超过4时,前4个参数保存在r0-r3寄存器中;后面的参数反向压入堆栈。即最后一个参数先入栈。
2009-3-14 11:17
0
雪    币: 87
活跃值: (47)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
7
多谢斑竹的加精和补充。本想追个码出来,跟一个晚上也没看出算法。
要求注册码为8位字母或数字。
我使用用户名ww,假码11111111。

if (algo1(ww)==algo2("11111111"))
         sucess!
algo1("ww")得到0xef7,algo2("11111111")得到b46,需要algo2(code)=0xef7,没看懂algo2,可能是个标准算法,多轮运算后得到一个双字,取其低12位。
位数不多,可惜还不会wince编程,否则可以遍历试下。
2009-3-14 13:00
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
哈哈,我的手机老掉牙了内存少啊
2009-3-14 16:28
0
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
9
wangdell今天猛烈爆发.....
2009-3-14 16:57
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
不错,比较详细,学习了
2009-3-15 15:46
0
雪    币: 2604
活跃值: (64)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
11
再补充一点:

将函数调用指令的4B替换成:mov r0 , #0刚好也是4B并非偶然。因为ARM指令很规整要么是32位ARM指令要么是16位Thumb指令。该软件使用的是纯的ARM32位指令所以所有指令都是4B的。这是RISC CPU和X86 CPU的一个重要区别。
2009-3-15 17:37
0
雪    币: 107
活跃值: (326)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
楼主不错.......学习了啊...........
2009-3-16 04:27
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
学习了~~强大的~
2009-3-28 11:34
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
好东西,谢了.
2009-5-28 11:28
0
雪    币: 93908
活跃值: (200199)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
15
Thanks for share.
2009-5-28 11:33
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bzh
16
感谢楼主的无私奉献
学习一下
2009-6-4 15:16
0
雪    币: 101
活跃值: (88)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
17
ding~~~~
2009-6-7 23:56
0
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
很想试试,就是没手机啊
2011-5-7 09:46
0
雪    币: 42
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
这个给力,支持!
2011-8-10 11:53
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
20
我也很想学学arm
2011-9-22 17:25
0
雪    币: 419
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
很好的教程,学习学习
2011-10-2 17:18
0
游客
登录 | 注册 方可回帖
返回
//