【文章标题】: Symbian 60的手机软件破解手记
【文章作者】: 海风月影[NE365][DFCG]
【软件名称】: Symbian 60手机软件
【使用工具】: IDA 4.9,WINHEX
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
nokia的智能手机用的操作系统是Symbian 60 简称 S60。这个操作系统不同于windows操作系统,执行的文件是.APP文件,其实就相当于windows里的.exe文件,当然,没有动态调试器了(od是肯定不能用的),只能用静态分析,工具只好选用强大的IDA(尽量用4.9版本的,4.5版本貌似对此支持不好)。修改代码工具用winhex或ultraedit都可以,只要能进行定位,修改16进制代码就行。
其实对我来说,破解S60手机软件障碍还是很大的。首先,没有手机模拟器,电脑上不能运行,也没有调试器。完全是修改代码,传到手机上,运行后才知道结果。其次,不是PC机的CPU,因此OPCODE也不一样,要重新去理解,不过好在有点基础的人很快能看懂。第三,我是第一次用IDA分析软件,对于E文不太好的我来说,这么强大的功能在我这里发挥不出来。
这是一篇破解手记,因此大家可能看起来没头绪,我只是想记录下我从开始接触手机软件到破解后的过程。
刚刚换手机,下了一些手机软件,很奇怪,手机软件也有破解版,汗~~~(破解真是无处不在),然而出于好奇心,我也想了解了解手机软件的破解,所以在百度,GOOGLE上大搜一番,很遗憾,只找到2篇关于S60软件的破解,而且思路都是一样,用IDA分析,查找相关的字符信息(程序的交互性决定了它肯定会告诉你是否注册成功),PC软件我们也通常这么做。与PC软件不同的是,手机软件设计者考虑的是手机的资源问题,效率问题,一个手机软件是不可能动不动就占用个nMB内存的,或者启动一下程序花个几分钟,这样的软件显然没人会用。我看过一本关于博弈游戏编程的书,里面提到手机上的博弈游戏软件必须考虑到一些PC机编程所不需要过多考虑的问题,如棋盘表示用bit棋盘就很省内存,而且运算速度比一般棋盘快。扯远了~~ 手机软件都会用明码存放一些敏感信息,始终能找到的,加上手机软件一般不大,呵呵,更轻松了。网上 TEAM n7uG 的教程就搜索到了如 aYouHave,aDayLeft,aRegisterCallCo 之类的字符串,大家一看就知道这些与注册有关。顺着思路下去,分析它的跳转语句,一定能找到破解点。看到这里大家可能会说,手机软件破解也太简单了吧。确实不错,对于一个手机软件爆破来说,是很简单的事,于是,我就随便找
了个软件自己去尝试一下。
我在www.symbianware.com网站上随便下了一个我手机能用的软件SMSMACHINE(我手机不能用我就不能验证我是否破解成功),首先,安装软件,运行,提示我还有15天的试用期,然后进去,选注册,随便填,确定,显示错误的注册码(这是英文软件,显示的是:wrong code ),然后继续可以使用。把日期调到1个月后,发现不能进软件了,提示试用期已到,然后要求注册,注册码当然也是错的,然后就退出了,看来这个软件是时间限制。破解思路,只要超过15天还能用就能算无时间限制版了。
用UNMAKESIS解压缩安装文件,解压后有主要的几个文件: .app , .rsc , .mbm。.app不说了,这个是程序文件;.rsc是资源文件,这里和PC机上不同,PC机是把资源文件编译到EXE文件里的,这里是分开放的,里面是UNICODE的字符,方便汉化。 .mbm是软件的图库文件。
用IDA载入.app文件,CPU选ARM,确定后让IDA分析完。这里我发现一个问题,IDA4.5对ARM的支持不好,基本不能自动解码,要手动处理。方法是:
.text:10006724 [color=#0000D0]ADD R1, R5, #0
.text:10006726 [color=#0000D0]ADD R1, #0x9C
.text:10006728 [color=#0000D0]STR R0, [R1]
.text:1000672A [color=#FF0000]BL PopAndDestroy__12CleanupStack [color=#008000]; CleanupStack::PopAndDestroy(void)
.text:1000672E LDR R0, [R5,#4]
.text:10006730 LDR R1, =0x5DA0B05F
.text:10006732 [color=#FF0000]BL AllocReadResourceAsDes16LC__C7CCoeEnvi [color=#008000]; CCoeEnv::AllocReadResourceAsDes16LC(int)
.text:10006736 [color=#0000D0]ADD R1, R0, #0
.text:10006738 LDR R0, [R5,#0x7C]
.text:1000673A [color=#FF0000]BL AVKON_465
.text:1000673E [color=#0000D0]ADD R1, R5, #0
.text:10006740 [color=#0000D0]ADD R1, #0xA0
.text:10006742 [color=#0000D0]STR R0, [R1]
.text:10006744 [color=#FF0000]BL PopAndDestroy__12CleanupStack [color=#008000]; CleanupStack::PopAndDestroy(void)
.text:10006748 [color=#0000D0]MOV R0, #0
.text:1000674A [color=#FF0000]BL OpenL__16CContactDatabaseQ216CContactDatabase13TThreadAccess [color=#008000]; CContactDatabase::OpenL(CContactDatabase::TThreadAccess)
.text:1000674E [color=#0000D0]ADD R1, R5, #0
.text:10006750 [color=#0000D0]ADD R1, #0xE8
p .text:100069A4 [color=#FF0000]BL Exit__9CEikAppUi[color=#008000]; CEikAppUi::Exit(void)
Down p .text:10006C14 [color=#FF0000]BL Exit__9CEikAppUi[color=#008000]; CEikAppUi::Exit(void)
.text:10006C08 [color=#008000]; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006C08
.text:10006C08 loc_10006C08 [color=#008000]; CODE XREF: .text:10006BF8j
.text:10006C08 [color=#0000D0]ADD R0, R6, #0
.text:10006C0A [color=#0000D0]ADD R0, #0xE4
.text:10006C0C LDR R0, [R0]
.text:10006C0E [color=#FF0000]BL sub_100085F4
.text:10006C12 [color=#0000D0]ADD R0, R6, #0
.text:10006C14 [color=#FF0000]BL CEikAppUi__Exit_void_ [color=#008000]; 这里程序退出
.text:10006C18 B loc_10006E7A
.text:10006C1A [color=#008000]; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006C1A
.text:10006C1A loc_10006C1A [color=#008000]; CODE XREF: .text:10006B3Cj
.text:10006C1A [color=#0000D0]ADD R0, R6, #0
.text:10006C1C [color=#FF0000]BL sub_100070EC
.text:10006C20 B loc_10006E7A
.text:10006C22 [color=#008000]; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006C22
.text:10006B1C [color=#0000D0]CMP R1, #0x1E
.text:10006B1E BGT loc_10006B8E
.text:10006B20 [color=#0000D0]CMP R1, #0x1C
.text:10006B22 BLT loc_10006B26
.text:10006B24 B loc_10006D68
.text:10006B26 [color=#008000]; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006B26
.text:10006B26 loc_10006B26 [color=#008000]; CODE XREF: .text:10006B22j
.text:10006B26 [color=#0000D0]CMP R1, #9
.text:10006B28 BNE loc_10006B2C
.text:10006B2A B loc_10006CD0
.text:10006B2C [color=#008000]; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006B2C
.text:10006B2C loc_10006B2C [color=#008000]; CODE XREF: .text:10006B28j
.text:10006B2C [color=#0000D0]CMP R1, #9
.text:10006B2E BGT loc_10006B5C
.text:10006B30 [color=#0000D0]CMP R1, #4
.text:10006B32 BNE loc_10006B36
.text:10006B34 B loc_10006C5E
.text:10006B36 [color=#008000]; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006B36
.text:10006B36 loc_10006B36 [color=#008000]; CODE XREF: .text:10006B32j
.text:10006B36 [color=#0000D0]CMP R1, #4
.text:10006B38 BGT loc_10006B4A
.text:10006B3A [color=#0000D0]CMP R1, #2
.text:10006B3C BEQ loc_10006C1A
.text:10006B3E [color=#0000D0]CMP R1, #2
.text:10006B40 BGT loc_10006C22
.text:10006B42 [color=#0000D0]CMP R1, #1
.text:10006B44 BNE loc_10006B48
.text:10006B46 B loc_10006CD0
.text:10006B48 [color=#008000]; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006B48
.text:10006B48 loc_10006B48 [color=#008000]; CODE XREF: .text:10006B44j
.text:10006B48 B loc_10006E7A
.text:1000696C [color=#FF0000]BL REG_CALC
.text:10006970 [color=#0000D0]MOV R0, [color=#FF0000]SP
.text:10006972 [color=#FF0000]BL CMP_STR [color=#008000]; 这里也有个比较函数
.text:10006972 [color=#008000];
.text:10006976 [color=#0000D0]CMP R0, #0
.text:10006978 BEQ loc_1000697C [color=#008000]; 试用版的就跳
.text:10006978 [color=#008000]; ★不跳就是注册版了,启动时检测,爆破点
.text:1000697A B [color=#b000b0]END [color=#008000]; 非试用版,结束这段代码
.text:1000697C [color=#008000]; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:1000697C
.text:1000697C loc_1000697C [color=#008000]; CODE XREF: .text:10006978j
.text:1000697C [color=#0000D0]MOV R0, [color=#FF0000]SP
.text:1000697E [color=#FF0000]BL TIME_LEFT [color=#008000]; 读取时间信息
.text:1000697E [color=#008000];
.text:10006982 [color=#0000D0]CMP R0, #0
.text:10006984 BEQ loc_10006A1C [color=#008000]; 试用期没满?跳走显示NAG
.text:10006984 [color=#008000]; 否则显示试用期满
.text:10006986 [color=#FF0000]BL Static__7CCoeEnv [color=#008000]; CCoeEnv::Static(void)
.text:1000698A LDR R1, =0x5DA0B061
.text:1000698C LDR R2, =0x5DA0B070
.text:1000698E [color=#FF0000]BL InfoWinL__C9CEikonEnvii [color=#008000]; CEikonEnv::InfoWinL(int,int)
.text:10006992 [color=#0000D0]MOV R0, [color=#FF0000]SP
.text:10006994 [color=#FF0000]BL REG_WINDOW [color=#008000]; 试用期满后注册
.text:10006994 [color=#008000];
.text:10006994 [color=#008000];
.text:10006998 [color=#0000D0]MOV R0, [color=#FF0000]SP [color=#008000]; 传入比较的参数
.text:10006998 [color=#008000];
.text:1000699A [color=#FF0000]BL CMP_STR [color=#008000]; 这里是个比较字符串函数
.text:1000699A [color=#008000]; 返回R0的值
.text:1000699A [color=#008000]; R0=0就是比较不相等
.text:1000699A [color=#008000]; 上面不远还有一个此函数
.text:1000699E [color=#0000D0]CMP R0, #0
.text:100069A0 BNE END_FUNC [color=#008000]; R0不等于0则跳转
.text:100069A0 [color=#008000]; 这个是一定要跳转的
.text:100069A0 [color=#008000]; 否则就退出了
.text:100069A2 [color=#0000D0]ADD R0, R5, #0
.text:100069A4 [color=#FF0000]BL CEikAppUi__Exit_void_ [color=#008000]; ★这里是试用期满的退出
.text:100069A8 B [color=#b000b0]END
Up p REG_WINDOW+1A [color=#FF0000]BL CMP_STR
p .text:10006972 [color=#FF0000]BL CMP_STR [color=#008000]; 比较函数
Down p .text:1000699A [color=#FF0000]BL CMP_STR [color=#008000]; 这里是个比较字符串函数
Down p ABOUT_WINDOW+3E [color=#FF0000]BL CMP_STR
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)