2006/07/11 | Symbian 60的手机软件破解手记
类别(软件破解及黑客技术) | 评论(2) | 阅读(707) | 发表于 09:51
转自:看雪学院

【文章标题】: 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的支持不好,基本不能自动解码,要手动处理。方法是:

引用: 这里引用 TEAM n7uG的教程里原文

在程序的开头处找到CODE32,点一下,然后按alt+g,弹出一个对话框Segment Register value,在value里面输入1,点OK。然后菜单项Options->General,点第二个标签Analysis,右下角有个按钮Reanalyse program,点一下开始对代码进行重新分析。一会儿,汇编代码就出来了。一般情况下不能将所有代码完全分析,你就得手工逐个的右击DCD 0x...等数据,选择undefine,然后重新进行Reanalyse program的工作,直到你能看清楚自己所感兴趣的代码为止。



而IDA4.9直接自动全部分析出来,然后看Names window找相关字符串,很遗憾,找不到一点点和注册有关系的信息:-(,这是怎么回事呢?后来我找到了一些汉化软件的教程,我试着汉化一下这个软件,突然在.rsc文件中找到了wrong code,Program's trial period is over!等信息。然后看了看关于S60软件的设计,发现NOKIA推出最近几个版本的SDK,把手机的资源全部整合到一个文件中了,不再把资源放在程序里了。我再次看了看n7uG的教程,2001年的...无语了,原来教程老了,不实用了。但还是有思路的,软件不是要读取资源嘛,读取资源肯定要用到API函数,对这个函数下断点。。。等等,好像只能静态分析。没办法,找到API函数
AllocReadResourceAsDes16LC__C7CCoeEnvi; CCoeEnv::AllocReadResourceAsDes16LC(int)

意思很明确,申请读取资源方面的,后面还跟着一个

OpenL__16CContactDatabaseQ216CContactDatabase13TThreadAccess; CContactDatabase::OpenL(CContactDatabase::TThreadAccess)

整个代码如下

代码:--------------------------------------------------------------------------------
.text:10006724 ADD R1, R5, #0
.text:10006726 ADD R1, #0x9C
.text:10006728 STR R0, [R1]
.text:1000672A BL PopAndDestroy__12CleanupStack ; CleanupStack::PopAndDestroy(void)
.text:1000672E LDR R0, [R5,#4]
.text:10006730 LDR R1, =0x5DA0B05F
.text:10006732 BL AllocReadResourceAsDes16LC__C7CCoeEnvi ; CCoeEnv::AllocReadResourceAsDes16LC(int)
.text:10006736 ADD R1, R0, #0
.text:10006738 LDR R0, [R5,#0x7C]
.text:1000673A BL AVKON_465
.text:1000673E ADD R1, R5, #0
.text:10006740 ADD R1, #0xA0
.text:10006742 STR R0, [R1]
.text:10006744 BL PopAndDestroy__12CleanupStack ; CleanupStack::PopAndDestroy(void)
.text:10006748 MOV R0, #0
.text:1000674A BL OpenL__16CContactDatabaseQ216CContactDatabase13TThreadAccess ; CContactDatabase::OpenL(CContactDatabase::TThreadAccess)
.text:1000674E ADD R1, R5, #0
.text:10006750 ADD R1, #0xE8

--------------------------------------------------------------------------------


先申请缓冲区,然后打开资源,但打开资源传入的参数是CContactDatabase::TThreadAccess,是个类?参数是又栈传入的,不动态调试不容易看出来,这个可是需要编程的基础,对于我来说等于天书了,无能力逆向。这条路走不通了。要另想办法

突然想起来,时间到了之后,注册码输入不正确,程序会自动退出。为什么不在退出上下功夫呢?这个退出肯定不是程序结束后的退出,一定调用了API(windows下也是这样的)。继续寻找,找到了下面API函数:

Exit__9CEikAppUi ; CEikAppUi::Exit(void)

这个肯定是退出函数了,点右键,JUMP TO XREF OPERAND ,


代码:--------------------------------------------------------------------------------

p .text:100069A4 BL Exit__9CEikAppUi; CEikAppUi::Exit(void)
Down p .text:10006C14 BL Exit__9CEikAppUi; CEikAppUi::Exit(void)

--------------------------------------------------------------------------------

就出现2条,也就是程序就2处调用了退出函数,下面一处是这里


代码:--------------------------------------------------------------------------------

.text:10006C08 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006C08
.text:10006C08 loc_10006C08 ; CODE XREF: .text:10006BF8j
.text:10006C08 ADD R0, R6, #0
.text:10006C0A ADD R0, #0xE4
.text:10006C0C LDR R0, [R0]
.text:10006C0E BL sub_100085F4
.text:10006C12 ADD R0, R6, #0
.text:10006C14 BL CEikAppUi__Exit_void_ ; 这里程序退出
.text:10006C18 B loc_10006E7A
.text:10006C1A ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006C1A
.text:10006C1A loc_10006C1A ; CODE XREF: .text:10006B3Cj
.text:10006C1A ADD R0, R6, #0
.text:10006C1C BL sub_100070EC
.text:10006C20 B loc_10006E7A
.text:10006C22 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006C22

--------------------------------------------------------------------------------


这几段看不出什么东西,我们需要向上或向下看,可以看到


代码:--------------------------------------------------------------------------------

.text:10006B1C CMP R1, #0x1E
.text:10006B1E BGT loc_10006B8E
.text:10006B20 CMP R1, #0x1C
.text:10006B22 BLT loc_10006B26
.text:10006B24 B loc_10006D68
.text:10006B26 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006B26
.text:10006B26 loc_10006B26 ; CODE XREF: .text:10006B22j
.text:10006B26 CMP R1, #9
.text:10006B28 BNE loc_10006B2C
.text:10006B2A B loc_10006CD0
.text:10006B2C ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006B2C
.text:10006B2C loc_10006B2C ; CODE XREF: .text:10006B28j
.text:10006B2C CMP R1, #9
.text:10006B2E BGT loc_10006B5C
.text:10006B30 CMP R1, #4
.text:10006B32 BNE loc_10006B36
.text:10006B34 B loc_10006C5E
.text:10006B36 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006B36
.text:10006B36 loc_10006B36 ; CODE XREF: .text:10006B32j
.text:10006B36 CMP R1, #4
.text:10006B38 BGT loc_10006B4A
.text:10006B3A CMP R1, #2
.text:10006B3C BEQ loc_10006C1A
.text:10006B3E CMP R1, #2
.text:10006B40 BGT loc_10006C22
.text:10006B42 CMP R1, #1
.text:10006B44 BNE loc_10006B48
.text:10006B46 B loc_10006CD0
.text:10006B48 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10006B48
.text:10006B48 loc_10006B48 ; CODE XREF: .text:10006B44j
.text:10006B48 B loc_10006E7A

--------------------------------------------------------------------------------


显然,CMP R1,数值,然后跳转,这个不是switch选择语句嘛?一般哪里用选择语句呢?很容易就想到消息循环,也就是说,这个退出是正常退出,是我们选择关闭程序,然后程序退出。那么另一个毫无疑问就是试用期满的退出。分析一下附近的代码


代码:--------------------------------------------------------------------------------

.text:1000696C BL REG_CALC
.text:10006970 MOV R0, SP
.text:10006972 BL CMP_STR ; 这里也有个比较函数
.text:10006972 ;
.text:10006976 CMP R0, #0
.text:10006978 BEQ loc_1000697C ; 试用版的就跳
.text:10006978 ; ★不跳就是注册版了,启动时检测,爆破点
.text:1000697A B END ; 非试用版,结束这段代码
.text:1000697C ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:1000697C
.text:1000697C loc_1000697C ; CODE XREF: .text:10006978j
.text:1000697C MOV R0, SP
.text:1000697E BL TIME_LEFT ; 读取时间信息
.text:1000697E ;
.text:10006982 CMP R0, #0
.text:10006984 BEQ loc_10006A1C ; 试用期没满?跳走显示NAG
.text:10006984 ; 否则显示试用期满
.text:10006986 BL Static__7CCoeEnv ; CCoeEnv::Static(void)
.text:1000698A LDR R1, =0x5DA0B061
.text:1000698C LDR R2, =0x5DA0B070
.text:1000698E BL InfoWinL__C9CEikonEnvii ; CEikonEnv::InfoWinL(int,int)
.text:10006992 MOV R0, SP
.text:10006994 BL REG_WINDOW ; 试用期满后注册
.text:10006994 ;
.text:10006994 ;
.text:10006998 MOV R0, SP ; 传入比较的参数
.text:10006998 ;
.text:1000699A BL CMP_STR ; 这里是个比较字符串函数
.text:1000699A ; 返回R0的值
.text:1000699A ; R0=0就是比较不相等
.text:1000699A ; 上面不远还有一个此函数
.text:1000699E CMP R0, #0
.text:100069A0 BNE END_FUNC ; R0不等于0则跳转
.text:100069A0 ; 这个是一定要跳转的
.text:100069A0 ; 否则就退出了
.text:100069A2 ADD R0, R5, #0
.text:100069A4 BL CEikAppUi__Exit_void_ ; ★这里是试用期满的退出
.text:100069A8 B END

--------------------------------------------------------------------------------


当然,可以猜测,这段代码是开始运行程序时执行的,可以在10006978点爆破,不让它跳,启动时就不会有NAG了。但是功能方面不能保证,因为这只是启动时的检测(其实这个软件也就这一处检测一下)。为了找出检测的所有点,我们可以找出下面这个函数调用的所有地方

.text:1000699A BL CMP_STR ; 这里是个比较字符串函数

这个函数是比较函数,比较的都是和注册有关系的^_^,点右键选 Jump to xref to operand,就是查找所有调用这个函数的地方,共4处


代码:--------------------------------------------------------------------------------

Up p REG_WINDOW+1A BL CMP_STR
p .text:10006972 BL CMP_STR ; 比较函数
Down p .text:1000699A BL CMP_STR ; 这里是个比较字符串函数
Down p ABOUT_WINDOW+3E BL CMP_STR

--------------------------------------------------------------------------------


可以看到,第一处是在注册窗口中调用,显然是判断是否注册成功的,第二,第三处上面已经有了,在启动时分别判断是否注册了和试用期是否满了,第四处我已经写出来了,是关于这个窗口里调用的,我们进去看看


代码:--------------------------------------------------------------------------------

.text:100095A4 ABOUT_WINDOW ; CODE XREF: .text:100093DAp
.text:100095A4
.text:100095A4 var_14 = -0x14
.text:100095A4 var_10 = -0x10
.text:100095A4 var_C = -0xC
.text:100095A4
.text:100095A4 PUSH {R4-R6,LR}
.text:100095A6 MOV R6, R8
.text:100095A8 PUSH {R6}
.text:100095AA LDR R4, =0xFFFFF6DC
.text:100095AC ADD SP, R4
.text:100095AE ADD R0, SP, #0x14+var_C
.text:100095B0 MOVL R1, 0x400
.text:100095B4 BL __10TBufBase16i
.text:100095B8 BL Static__7CCoeEnv ; CCoeEnv::Static(void)
.text:100095BC LDR R1, =0x5DA0B062
.text:100095BE BL AllocReadResourceAsDes16LC__C7CCoeEnvi ; CCoeEnv::AllocReadResourceAsDes16LC(int)
.text:100095C2 ADD R1, R0, #0
.text:100095C4 ADD R0, SP, #0x14+var_C
.text:100095C6 BL Append__6TDes16RC7TDesC16 ; TDes16::Append(TDesC16 const &)
.text:100095CA BL PopAndDestroy__12CleanupStack ; CleanupStack::PopAndDestroy(void)
.text:100095CE MOVL R4, 0x810
.text:100095D2 ADD R4, SP
.text:100095D4 ADD R0, R4, #0
.text:100095D6 BL sub_10005D70
.text:100095DA ADD R0, R4, #0
.text:100095DC BL REG_CALC
.text:100095E0 ADD R0, R4, #0
.text:100095E2 BL CMP_STR ; 这里可以看到
.text:100095E2 ; 和启动时的判断过程一样
.text:100095E2 ;
.text:100095E6 ADD R5, R0, #0
.text:100095E8 ADD R0, R4, #0
.text:100095EA BL nullsub_2
.text:100095EE CMP R5, #0 ; 等于0就是未注册的
.text:100095EE ;
.text:100095F0 BEQ loc_10009608
.text:100095F2 BL Static__7CCoeEnv ; CCoeEnv::Static(void)
.text:100095F6 LDR R1, =0x5DA0B063 ; "注册版",资源的位置
.text:100095F6 ;
.text:100095F8 B loc_1000960E
.text:100095F8 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:100095FA ALIGN 4
.text:100095FC dword_100095FC DCD 0xFFFFF6DC ; DATA XREF: ABOUT_WINDOW+6r
.text:10009600 dword_10009600 DCD 0x5DA0B062 ; DATA XREF: ABOUT_WINDOW+18r
.text:10009604 dword_10009604 DCD 0x5DA0B063 ; DATA XREF: ABOUT_WINDOW+52r
.text:10009608 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10009608
.text:10009608 loc_10009608 ; CODE XREF: ABOUT_WINDOW+4Cj
.text:10009608 BL Static__7CCoeEnv ; CCoeEnv::Static(void)
.text:1000960C LDR R1, =0x5DA0B064 ; "未注册",资源的位置
.text:1000960C ;
.text:1000960E
.text:1000960E loc_1000960E ; CODE XREF: ABOUT_WINDOW+54j
.text:1000960E BL AllocReadResourceAsDes16LC__C7CCoeEnvi ; CCoeEnv::AllocReadResourceAsDes16LC(int)
.text:1000960E ; 调用资源的函数

--------------------------------------------------------------------------------


大家可能比较奇怪,我为什么确定这个是注册窗口,我又没有调试过程序。这里,我们在ABOUT_WINDOW上点右键选 Jump to xref to operand


代码:--------------------------------------------------------------------------------

Up p .text:100093DA BL ABOUT_WINDOW

--------------------------------------------------------------------------------


就一处地方,双击,进去看看


代码:--------------------------------------------------------------------------------

.text:100093CC loc_100093CC ; DATA XREF: .text:1000D374o
.text:100093CC PUSH {R4,LR}
.text:100093CE SUB SP, SP, #0x100
.text:100093D0 ADD R4, R1, #0
.text:100093D2 CMP R4, #0x32 ; "注册",菜单选项
.text:100093D2 ;
.text:100093D4 BEQ loc_100093E0
.text:100093D6 CMP R4, #0x33 ; "关于",菜单选项
.text:100093D6 ;
.text:100093D8 BNE loc_10009402 ; 2个都不是,跳走
.text:100093D8 ;
.text:100093DA BL ABOUT_WINDOW
.text:100093DE B loc_10009410
.text:100093E0 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:100093E0
.text:100093E0 loc_100093E0 ; CODE XREF: .text:100093D4j
.text:100093E0 MOV R0, SP
.text:100093E2 BL sub_10005D70
.text:100093E6 MOV R0, SP
.text:100093E8 BL REG_CALC ; 计算注册码
.text:100093E8 ;
.text:100093EC MOV R0, SP
.text:100093EE BL REG_WINDOW ; 显示注册窗口
.text:100093EE ;
.text:100093F2 MOV R0, SP
.text:100093F4 BL nullsub_2
.text:100093F8 MOV R0, SP
.text:100093FA MOV R1, #2
.text:100093FC BL sub_10005D8C
.text:10009400 B loc_10009410
.text:10009402 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:10009402
.text:10009402 loc_10009402 ; CODE XREF: .text:100093D8j
.text:10009402 BL AVKON_42 ; 这里应该是系统的功能
.text:10009402 ; 我手机上这里是
.text:10009402 ; "添加到捷径"
.text:10009402 ; 而且不用汉化,
.text:10009402 ; 就是说资源应该是手机里的
.text:10009406 LDR R1, [R0]
.text:10009408 LDR R2, [R1,#0x4C]
.text:1000940A ADD R1, R4, #0
.text:1000940C BL sub_1000A4AC
.text:10009410
.text:10009410 loc_10009410 ; CODE XREF: .text:100093DEj
.text:10009410 ; .text:10009400j
.text:10009410 ADD SP, SP, #0x100
.text:10009412 POP {R4}
.text:10009414 POP {R0}
.text:10009416 BX R0

--------------------------------------------------------------------------------


这里很容易看出来的,也不需要过多分析。
最后,就是破解了,分析一下这个:


代码:--------------------------------------------------------------------------------

Up p REG_WINDOW+1A BL CMP_STR
p .text:10006972 BL CMP_STR ; 比较函数
Down p .text:1000699A BL CMP_STR ; 这里是个比较字符串函数
Down p ABOUT_WINDOW+3E BL CMP_STR

--------------------------------------------------------------------------------


其实爆破点就是1个,就是启动那里判断是否注册的一个点,上面说了,但是修改时候有些头疼,我没有OPCODE的表,不知道NOP这个命令的OPCODE,晕了。我们换个思路,每次判断是否注册,程序都调用了CMP_STR这个函数,我们可以在这里做文章,这个函数返回值在R0里面,R0=0则比较结果不相同,所以,我们只要让它返回不是0就可以了


代码:--------------------------------------------------------------------------------

.text:100061B0 BL Compare__C7TDesC16RC7TDesC16 ; TDesC16::Compare(TDesC16 const &)
.text:100061B4 MOV R1, #0
.text:100061B6 CMP R0, #0
.text:100061B8 BNE loc_100061BC
.text:100061BA MOV R1, #1
.text:100061BC
.text:100061BC loc_100061BC ; CODE XREF: CMP_STR+24j
.text:100061BC CMP R1, #0
.text:100061BE BEQ loc_100061C8
.text:100061C0
.text:100061C0 Wrong ; CODE XREF: CMP_STR+Cj
.text:100061C0 MOV R0, #0 ; R0不是以0返回就OK了
.text:100061C0 ; 改成MOV R0,#1
.text:100061C0 ; 二进制码为 01 21
.text:100061C2 B END

--------------------------------------------------------------------------------


函数中唯一返回R0=0的地方,我们改成R0=1就可以了,在IDA最下面看看这个100061C0地址对应的文件偏移:623C。用16进制编辑工具,定位偏移623C,修改 00 21 为 01 21,保存,破解成功。


引用: 引用fxyang的话:

破解了这里就全部的破解了这个软件。(模块化编程的弊端?)




后记:
这篇文章写了很久。第一,因为没什么资料,误打误撞了半天。第二,因为课程比较紧,耽误了点时间。
这里,需要感谢的是 TEAM n7uG 的教程,没有这篇教程,我花的时间可能更多。还要感谢fxyang,他的破解方法给了我启发。

另外,论坛上已经出现一些手机方面的文章,但可惜的是都是WIN CE 操作系统下的,很容易看出来的,WINCE下的程序每个语句都是4字节,而Symbian 60程序是2字节。这个系统的API函数不同于WINCE,又没有调试器,算法就分析不出来了。

第一次用IDA分析东西,分析的不彻底,大家可能看得不是很清晰,只能说对不起大家了

--------------------------------------------------------------------------------
【版权声明】: 本文原创于海风月影, 转载请注明作者并保持文章的完整, 谢谢!

2006年07月10日 1:20:05
0

评论Comments