为了方便查找,粘贴到这里了,因为再次查找比较麻烦。
转自:http://bbs.pcworld.com.cn/archiver/?tid-5625.html
| ||
如何破解Pocket PC (for ARM)软件 [color=Purple]如何破解Pocket PC (for ARM)软件 一点心得,有错误请指出。 比较PC下的软件,Pocket PC上软件的破解是比较简单的。如果你有windows下软件的破解经历,那只要熟悉ARM汇编就够了。 一.所需知识 1.熟悉C语言和ARM汇编语言。 2.有Windows API编程的经验。 二.工具 1. Embedded VC++,用于动态调试待破解程序; 2. IDA Pro,需要全版,这样能反汇编不同类型CPU的程序,用于静态分析; 3. ResHacker,用于查看资源,找出敏感的字符串; 4.二进制编辑器,如UltraEdit,WinHex等,用于修改程序; 5.一种ARM的编译器,如EmbestIDE for ARM、ADS,SDT等,可以用于写一小段汇编代码,再嵌入到目标程序中,也可以用来熟悉ARM指令; 6.最好有一个pocket pc的设备(ARM CPU)。 如何破解Pocket PC (for ARM)软件【2】 wh_cxh 2004.1 三.注册码验证方式与破解方式 当我们输入一个软件的注册码时,软件必须与正确的注册码相比较,才能判断输入的正确与否,下面是常用的注册码验证方法。 1.将owner name或email运算得到正确的注册码,再和输入的注册码比较; RealKeyCode = f(owner name/email); If( inputKeyCode == RealkeyCode) “注册成功” else “注册失败” 要强制破解,可以跳过inputKeyCode == RealkeyCode判断,直接执行“注册成功”。如果要做注册机,则要读懂RealKeyCode = f(owner name/email)这段代码。 如何快速找到注册码判断的入口点呢,这就要借助上面提及的工具了,很明显的标志是字符串“注册成功”与“注册失败”,当然在实际中提示是不完全相同的。如果提示信息以资源的形式保存,则要使用ResHacker查看;否则就需要反汇编程序。 用IDA Pro反汇编时,在反汇编过程中有一个System DLL Directory要输入路径,最好将pocket pc /windows目录下的dll复制到一个文件夹(不是所有的都能复制),如C:/WINDOWS/CE。这些动态库可以是x86模拟器的,因为IDA只是关心他们的引出函数。 找到提示信息后,一般很快能找出注册码比较点。 拿ProWord为例,在ResHacker中查看字符串资源,并没有发现相关注册成功失败的信息,在对话框资源142中可以看出需要输入User name和unlock code。用Ida反汇编,在String窗口中可以发现: .data:00020CF4 00000044 unicode Thank you for registering ProWord .data:00020D38 00000030 unicode Not a valid Unlock code 顺着串往上找,发现: .text:000178A0 BL sub_197C4 ;返回R0 == 0则注册码错误 .text:000178A4 MOVS R3, R0 .text:000178A8 BEQ loc_178D8 .text:000178AC CMP R4, #0 .text:000178B0 MOV R0, #0 .text:000178B4 LDRNE R0, [R4,#0x20] .text:000178B8 BL sub_191D8 .text:000178BC MOV R3, #1 .text:000178C0 MOV R0, R4 .text:000178C4 STR R3, [R4,#0x7C] .text:000178C8 BL mfcce300_1969 .text:000178CC LDR R0, =aThankYouForReg .text:000178D0 B loc_178E8 .text:000178D4 off_178D4 DCD aThankYouForReg ; DATA XREF: sub_17858+74 r .text:000178D4 ; "Thank you for registering ProWord" .text:000178D8 loc_178D8 ; CODE XREF: sub_17858+50 j .text:000178D8 LDR R0, =aNotAValidUnloc .text:000178DC B loc_178E8 .text:000178E0 off_178E0 DCD aNotAValidUnloc ; DATA XREF: sub_17858+80 r .text:000178E0 ; "Not a valid Unlock code" sub_197C4是重点,进入看看,发现调用sub_19540,返回R0==0则注册码错,而且sub_19540有两个地方调用,一个是启动程序时验证注册码,一个是输入注册码时验证,因此要进入sub_19540修改返回值,如果在sub_19540外修改,则需要修改两次,如有遗漏,有时输入注册码虽然提示正确,但重新启动程序时会再次提醒非注册版本,这种错误经常出现! 如何破解Pocket PC (for ARM)软件【3】 wh_cxh 2004.1 有的程序提示信息以串资源的形式保存,如: STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US { 2202, "Enter Code" 2203, "Thank you for registering. /nNow you need to restart game to apply changes." } 应用程序要显示字符串,首先要载入该串资源,用API则调用如下功能: int LoadString(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int cchBufferMax); 在ARM中函数调用参数传递约定: func(R0,R1,R2,R3,SP,SP+4,…,SP+4*n),返回值在R0中。 上例中uID = 2203 = 0x89D,在反汇编代码中应该有如下类似代码: MOV R1, #0x890 ;;不是MOV R1, #0x89D的原因请参阅ARM汇编手册 ORR R1, R1, #0xD 如何快速找到上述代码呢?可以在IDA中先生成.asm文件,File->Produce->Create ASM File。用Emeditor或其他可以用正则表示式查找功能的编辑器打开,查找MOV.*R.*#0x890,很快就能够发现。如果不太明白正则表示式,直接搜索#0x890也可,就是找到结果太多! 如果串资源是53569,”xxxxxxxx” 53679 = 0xD597,一时不明白MOV R1, #0x???, 就可以查找MOV.*R.*#0xD/d/d/d,找到后再缩小范围。 如果不使用API,用MFC 导入串资源是什么功能呢? 这就需要一份MFCCE300.DLL的引出函数列表,形如下: …… 1725 ?LoadTemplate@CDocTemplate@@UAAXXZ (public: virtual void __cdecl CDocTemplate::LoadTemplate(void)) 1724 ?LoadStringW@CString@@QAAHI@Z (public: int __cdecl CString::LoadStringW(unsigned int)) …… 可以从MFCCE300.LIB中导出来。这样就能明白mfcce300_1724,mfcce300_xxx是什么功能了,附件中包含这个文件。 如何破解Pocket PC (for ARM)软件【4】 wh_cxh 2004.1 2.将owner name或email和输入的注册码分别运算得到中间值,比较二者 imdKeyCode = f(owner name/email); imdKey1Code = g(inputKeyCode); if(imdKeyCode == imdKey1Code) “注册成功” else “注册失败” 这种方法,不像方式1,并不将真正的注册码计算出来。 3.有些程序只需要输入注册码,如isilo,此时的验证方式是看输入的注册码是否满足某些条件,例如运算后某些位是否为指定的值。 在实际程序中,验证注册码不一定只是比较一次,很多程序并不是立即判断输入注册码的正确与否,所以要具体对待。 以上是注册码验证的比较常见的方式。 四.用EVC动态调试程序 在静态分析出现困难时,可以使用EVC动态调试待破解程序。 EVC菜单 File -> Open Workspace -> 文件类型选.exe ->打开,然后再Project ->Setting中设置download路径,将计算机与你的pocket pc连上,在EVC中选择POCKET PC 2002/2003 DEVICE,设置断点,Build -> Start Debug -> Go,然后操作你的Pocket pc,满足断点条件时,程序终止,这是可以调试程序了。 用这种方法可以直接看到注册码验证方式1中的注册码。 如: .text:0009D434 ADD R1, R6, #0x84 .text:0009D438 ADD R0, SP, #0x90 .text:0009D43C BL wcscmp ;注册码比较 那么在内存单元中查看R0,R1所显示的内容,就可以知道正确的注册码了。 如何破解Pocket PC (for ARM)软件【5】 wh_cxh 2004.1 五实例 1.TrueFax (Windows Mobile 2003 Phone Edition v2.05 (PXA-CPU)) [url]http://www.ksesoftware.com/showarticle.php...9&sub=downloads[/url] 用ResHacker 依次打开TF20PoomDll.dll,Truefax.exe,TruefaxLangComp20.dll 在TruefaxLangComp20.dll中发现: STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US { 300, "The entered name is too short." 301, "The reg.-no. does not fit with the user-name." 302, "This version was registered successfully. Thank you for your interest in %s." 303, "This trial version has expired!/nPlease register KSE Truefax." } 反汇编Truefax.exe生成.asm文件,用正则表达式查找MOV.*R.*#0x12C .text:00023A24 BL sub_1C294 .text:00023A28 MOV R4, R0 .text:00023A2CMOV R0, #0x12C .text:00023A30 ORR R0, R0, #2 ;"302, "This version was regist..." .text:00023A34 BL sub_20870 .text:00023A38 MOV R1, R0 .text:00023A3C MOV R2, R4 .text:00023A40 ADD R0, SP, #0xD0 .text:00023A44 BL wsprintfW 往上查找 .text:000239C8 ADD R1, SP, #0x10 .text:000239CC ADD R0, SP, #0x48 .text:000239D0 BL sub_234D4 .text:000239D4 CMP R0, #0 .text:000239D8 BEQ loc_23AB0 ;loc_23AB0 注册失败 .text:000239DC LDR R5, =unk_78418 ;注册正确 .text:000239E0 ADD R0, SP, #0x48 sub_234D4有两处调用,一次是输入注册码时验证,一次是启动时验证,修改sub_234D4返回值就可以了 sub_234D4 ........ .text:00023590 loc_23590 ; CODE XREF: sub_234D4+A4j .text:00023590 MOV R0, R7 ;改MOV R0, #1 .text:00023594 ADD SP, SP, #0x50 .text:00023598 LDMFD SP!, {R4-R7,PC} 如何破解Pocket PC (for ARM)软件【6】 wh_cxh 2004.4 2.找出TrueFax (Windows Mobile 2003 Phone Edition v2.05 注册码 注册码比较方式 f(name) == g(code),需要找出g(code)的逆变换 .text:0002351C MOV R1, R0 ; name .text:00023520 STR R3, [SP,#8] .text:00023524 MOV R5, #0 .text:00023528 MOV R6, #0 .text:0002352C STR R5, [SP,#0xC] .text:00023530 MOV R2, #0 .text:00023534 STR R6, [SP,#0x10] .text:00023538 ADD R0, SP, #0x28 .text:0002353C MOV R7, #0 .text:00023540 BL sub_230AC; 变换name -> SP + 0x28 (15位) .text:00023544 MOV R1, R4 .text:00023548 ADD R0, SP, #0 .text:0002354C BL sub_23280 ; 变换input_regcode ->SP (15位) .text:00023550 MOV R3, R7 .text:00023554 .text:00023554 loc_23554 ; CODE XREF: sub_234D4+ACj .text:00023554 ADD R0, SP, #0 .text:00023558 LDRH R0, [R3,R0] .text:0002355C MOV R1, R0,LSL#16 .text:00023560 ADD R0, SP, #0x28 .text:00023564 LDRH R0, [R3,R0] .text:00023568 MOV R2, R1,LSR#16 .text:0002356C ADD R3, R3, #2 .text:00023570 MOV R1, R0,LSL#16 .text:00023574 CMP R2, R1,LSR#16 ;比较name和reg.no变换后的结果 .text:00023578 BNE loc_23590 ;错误 .text:0002357C CMP R2, #0 .text:00023580 BNE loc_23554 .text:00023584 MOV R0, #1 ;正确 看sub_23280 .text:00023280 sub_23280 ; CODE XREF: sub_234D4+78p .text:00023280 STMFD SP!, {R4-R6,LR} ; .text:00023284 SUB SP, SP, #0x30 .text:00023288 MOV R6, R0 .text:0002328C MOV R5, R1 .text:00023290 SUB R3, R5, #2 .text:00023294 .text:00023294 loc_23294 ; CODE XREF: sub_23280+20j .text:00023294 LDRH R0, [R3,#2]! .text:00023298 MOV R1, R0,LSL#16 .text:0002329C MOVS R2, R1,LSR#16 .text:000232A0 BNE loc_23294 .text:000232A4 SUB R0, R3, R5 .text:000232A8 MOV R1, R0,LSR#1 .text:000232AC CMP R1, #0xF ;长度判断应该为15位 .text:000232B0 BNE loc_232F8 .text:000232B4 ADD R0, SP, #0x10 .text:000232B8 ADD R4, SP, #0x10 .text:000232BC SUB R3, R5, R0 .text:000232C0 .text:000232C0 loc_232C0 ; CODE XREF: sub_23280+50j .text:000232C0 LDRH R2, [R4,R3] .text:000232C4 MOV R0, R2,LSL#16 .text:000232C8 STRH R2, [R4],#2 .text:000232CC MOVS R1, R0,LSR#16 .text:000232D0 BNE loc_232C0 .text:000232D4 ADD R1, SP, #0x10 .text:000232D8 ADD R0, SP, #0 .text:000232DC BL sub_22DF0 ;去掉第1,3,5,7位 .text:000232E0 ADD R0, SP, #0 .text:000232E4 BL sub_22EA0 .text:000232E8 ADD R0, SP, #0 .text:000232EC BL sub_22AD8 ;1,3,5,7位是否为0 2 7 4 .text:000232F0 CMP R0, #0 .text:000232F4 BPL loc_23304 ; 是 .text:000232F8 .text:000232F8 loc_232F8 ; CODE XREF: sub_23280+30j .text:000232F8 MOV R0, #0 ;返回错 .text:000232FC ADD SP, SP, #0x30 .text:00023300 LDMFD SP!, {R4-R6,PC} .text:00023304 ; ---------------------------------------------------------------------------------------------- .text:00023304 .text:00023304 loc_23304 ; CODE XREF: sub_23280+74j .text:00023304 MOV R1, R0 .text:00023308 ADD R0, SP, #0x10 .text:0002330CBL sub_231B0 ;变换.text:00023310 ADD R1, SP, #0 .text:00023314 ADD R0, SP, #0x10 .text:00023318 BL sub_22D44 .text:0002331C ADD R0, SP, #0x10 .text:00023320 SUB R3, R0, R6 .text:00023324 .text:00023324 loc_23324 ; CODE XREF: sub_23280+B4j .text:00023324 LDRH R2, [R6,R3] .text:00023328 MOV R0, R2,LSL#16 .text:0002332C STRH R2, [R6],#2 .text:00023330 MOVS R1, R0,LSR#16 .text:00023334 BNE loc_23324 .text:00023338 MOV R0, #1 .text:0002333C ADD SP, SP, #0x30 .text:00023340 LDMFD SP!, {R4-R6,PC} sub_231B0 .text:000231B0 sub_231B0 ; CODE XREF: sub_23280+8Cp .text:000231B0 STMFD SP!, {R4-R11,LR} .text:000231B4 SUB SP, SP, #0x18 .text:000231B8 MOV R10, R0 .text:000231BC MOV R2, R1 .text:000231C0 LDR R1, =aTruefax2_0Phon .text:000231C4 MOV R3, #0x194 .text:000231C8 MLA R5, R2, R3, R1 .text:000231CC MLA R0, R2, R3, R1 .text:000231D0 ADD R9, SP, #0 .text:000231D4 MOV R8, #0xB .text:000231D8 MOV R7, R5 .text:000231DC LDR R4, [R0,#0x16C]; 1 5 0 2 6 3 4 7 8 9 .text:000231E0 MOV R6, R5 .text:000231E4 MOV R11, #0 .text:000231E8 .text:000231E8 loc_231E8 ; CODE XREF: sub_231B0+A0j .text:000231E8 LDR R0, [R6,#0xC8];A 5 3 6 2 9 7 8 1 0 4 .text:000231EC MOV R3, R11 .text:000231F0 ADD R1, R10, R0,LSL#1 .text:000231F4 LDRH R2, [R1] .text:000231F8 MOV R0, R2,LSL#16 .text:000231FC MOV R1, R0,LSR#16 .text:00023200 SUB R2, R1, #0x30 .text:00023204 CMP R2, R4 .text:00023208 BEQ loc_23224 .text:0002320C MOV R1, R5 .text:00023210 .text:00023210 loc_23210 ; CODE XREF: sub_231B0+70j .text:00023210 ADD R1, R1, #4 .text:00023214 LDR R0, [R1,#0x16C] ; 1 5 0 2 6 3 4 7 8 9 .text:00023218 ADD R3, R3, #1 .text:0002321C CMP R2, R0 .text:00023220 BNE loc_23210 .text:00023224 .text:00023224 loc_23224 ; CODE XREF: sub_231B0+58j .text:00023224 LDR R0, [R7,#0x11C] ;3 6 1 2 2 5 8 3 7 4 4 .text:00023228 SUB R8, R8, #1 .text:0002322C ADD R7, R7, #4 .text:00023230 SUBS R1, R3, R0 .text:00023234 ADDMI R1, R1, #0xA ; 负号 .text:00023238 ADD R0, R1, #0x30 .text:0002323C MOV R1, R0,LSL#16 .text:00023240 MOV R2, R1,LSR#16 .text:00023244 STRH R2, [R9],#2 .text:00023248 SUB R6, R6, #4 .text:0002324C CMP R8, #0 .text:00023250 BHI loc_231E8 .text:00023254 ADD R0, SP, #0 .text:00023258 STRH R11, [SP,#0x16] .text:0002325C SUB R3, R0, R10 .text:00023260 .text:00023260 loc_23260 ; CODE XREF: sub_231B0+C0j .text:00023260 LDRH R2, [R10,R3] .text:00023264 MOV R0, R2,LSL#16 .text:00023268 STRH R2, [R10],#2 .text:0002326C MOVS R1, R0,LSR#16 .text:00023270 BNE loc_23260 .text:00023274 ADD SP, SP, #0x18 .text:00023278 LDMFD SP!, {R4-R11,PC} .text:00023278 ; End of function sub_231B0 sub_231B0功能: 按位置A 5 3 6 2 9 7 8 1 0 4取数 数在1 5 0 2 6 3 4 7 8 9 中位置 减去3 6 1 2 2 5 8 3 7 4 4 小于0加上A u8 pos[] = {1,5,0,2,6,3,4,7,8,9}; u8 sub[] = {3,6,1,2,2,5,8,3,7,4,4}; //u8 key_pos[] = {0xa,5 ,3,6,2,9,7,8,1,0,4}; u8 key_pos[] = {14,9,6,10,4,13,11,12,2,0,8}; u8 code[15]; //f(L"wh_cxh") = "048762306414292" num[] = {0,8,6,3,6,4,1,4,2,9,2}; for(int i = 0; i < 11; i++) { temp = num[i] + sub[i]; if(temp > 9) temp -= 0xa; code[key_pos[i]] = pos[temp]; } code[1] = 0; code[3] = 2; code[5] = 7; code[7] = 4; for(int j = 0; j < 15; j++) printf("%x", code[j]); //209287744639792 name : wh_cxh regcode : 209287744639792 如何用EVC跟踪dll文件,在无exe文件的情况下? 如果该dll已经加载,联机后,EVC 菜单Tools->Remote Process viewer可以找到动态库的加载地址,再设置断点。不过在动态库中,设置断点后,好像有问题: 因为EVC在设置的断点处插入一个无效指令,在dll处中断时好像并不恢复,所以要手工改回到原来指令,或者中止程序。[/color] |
第2篇:转自:http://www.pdafans.com/discuz/viewthread.php?tid=25552
[转载]如何破解PPC软件 --- 菜鸟快速入门实战篇
首先要说的是,如果你在本文的帮助下,成功地破解了什么东东,请不要随意传播或者出售他们….(此处省去废话100字)。
好了,现在我们该开始了。如果你已经有过破解Windows软件的经验,再和PPC操作系统打交道就比较容易了。PPC掌上电脑(后面用PPC表示 “掌上电脑”)的中央处理器不同于普通的PC个人电脑,他们使用不同的运作指令集,比较常见的PPC中央处理器有StrongARM, Mips 和 SH3。不同的PPC处理器的指令集也不相同。本文只针对目前最流行的英特尔StrongARM处理器。
要做软件破解,先要选择好的破解工具。直到今天,都还没有一个基于PPC/WinCE平台专门的反编译调试器,我们只能利用个人电脑来做这些工作了。开工啦,我们这个实例比较简单,不要害怕。破解一个Windows软件和PPC/WinCE软件有什么不同呢?主要差异是…..通常破解PPC/WinCE软件要简单些。 :-)
我把IDA 4.15版 和十六进制编辑器HIEW作为本文破解的工具。
我们今天的破解目标是ScaryBear公司的GamePack Ⅰ and Ⅱ(在http://www.scarybearsoftware.com 下载或者从下面的帖子下载)。它包含了几种采用相同软件保护方法的游戏。里面有个游戏叫LINES v1.1,我们拿它开刀。首先把它在安装在你的PPC里,运行看看,找到Options的About, 你可以看到他的提示信息, 它显示这个软件只是试用版,并要求你输入注册码。当随意输入一个号码并按OK后,没有任何反应。
看看这个软件的README.TXT 说明文件:
NOTE: These games have a 14-day trial period, after which, you will need to purchase a Game Pack 2 reg code to permanently activate all 3 games. For more details, please visit: http://www.scarybearsoftware.com (本游戏已过14天试用期,若想永久使用,请购买注册码。网站上有更多细节,请查阅。)
我们把系统的时间更改到试用版过期日,再玩这个游戏,一个对话框显示出来,除非注册,游戏不能再玩了。
现在把这个游戏的执行文件拷贝到你的个人电脑里,运行前面提到的IDA工具。当IDA 问你处理器的种类(processor type)时,请选择ARM Processor: ARM. 然后它会要求一些库文件,这个例子指AYGSHELL.DLL, 从你的PPC拷过来就可以了。
回到IDA用shift+F4打开the names window搜索“a14DayTrialPeri”,这个字符串来自游戏软件过期后的提示版。
最后,你在这个位置找到“a14DayTrialPeri”:
.text:00011704 ; ---------------------------------------------------------------------------
.text:00011704 STMFD SP!, {R4-R6,LR}
.text:00011708 MOV R4, R3 ;
.text:0001170C BL sub_13578 ; <-- 用子程序检查是否注册
.text:00011710 CMP R0, #1 ; <-- is R0 = 1 ?
.text:00011714 BNE loc_11744 ; <-- 不相等?好
.text:00011718 BL sub_13964 ; <-- 你玩这婊子超过14天了吗??
.text:0001171C CMP R0, #1 ; <-- is R0 = 1?
.text:00011720 BNE loc_11744 ; <-- 不相等?好,游戏开始
.text:00011724 LDR R2, =aError ; ------------------------------------
.text:00011724 ; <-- 你没有注册,立即显示弱智的
.text:00011724 ; 过期提示版
.text:00011728 MOV R3, #0
.text:0001172C LDR R1, =a14DayTrialPeri
.text:00011730 MOV R0, #0
.text:00011734 BL MessageBoxW
.text:00011738 B loc_11840 ; <-- 跳到这个位置,不返回
.text:00011738 ; ---------------------------------------------------------------------------
.text:0001173C off_1173C DCD a14DayTrialPeri ; DATA XREF: .text:0001172C r
.text:0001173C ; /"14-Day Trial Period is over.//nPlease vis/"...
.text:00011740 off_11740 DCD aError ; DATA XREF: .text:00011724 r
.text:00011740 ; /"Error/"
.text:00011744 ; ---------------------------------------------------------------------------
.text:00011744
请观察这一段
.text:00011718 BL sub_13964 ; <--你玩这婊子超过14天了吗??
.text:0001171C CMP R0, #1 ; <-- is R0 = 1?
.text:00011720 BNE loc_11744 ; <--不相等?好,游戏开始
★★★
在0001170C这一行里的BL调用一个子程序sub,用以检查你到底注册了没有,返回的结果被存在了R0。R0又和1作比较,如果R0不等于1,说明我们已经注册了这个游戏软件,那个弱智到期提示版就不会出现,可以继续玩。
现在我们只能把00011714这一行的BNE改为BEQ(或者B)。 NE表示不等于,EQ表示等于,我们把条件反过来,这样没有注册就变为已经注册了。
改了以后: 在0001170C这一行里的BL调用一个sub时,检查你到底注册了没有,返回的结果被存在了R0。R0又和1作比较,如果R0“等于”1,说明我们已经注册了这个游戏软件,那个弱智到期提示版就不会出现,可以继续玩。
但为了让这个游戏真的认为我们注册了它,我们应该重新考察一下sub_13578。研究了以后,我们发现这段子程序把一系列的错误的序列号带到同一位置:.text:00013680这一部分。
.text:00013578
.text:00013578 ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
.text:00013578
.text:00013578
.text:00013578 sub_13578 ; CODE XREF: .text:0001170C p
.text:00013578 ; .text:00011B4C p ...
.text:00013578 STMFD SP!, {R4,R5,LR}
.text:0001357C SUB SP, SP, #0xE0
.text:00013580 LDR R0, =aRegcode
.text:00013584 ADD R1, SP, #0x18
.text:00013588 BL sub_13BCC
.text:0001358C ADD R0, SP, #0x18
.text:00013590 BL wcslen
.text:00013594 CMP R0, #0xA
.text:00013598 BCC loc_13680 ; <-- WRONG KEY
.text:0001359C ADD R0, SP, #0x18
.text:000135A0 BL sub_1371C
.text:000135A4 MOVS R3, R0
.text:000135A8 BNE loc_13680 ; <-- WRONG KEY
.text:000135AC LDRH R3, [SP,#0x26]
.text:000135B0 MOV R4, #0
.text:000135B4 LDR R1, =aD
.text:000135B8 ADD R2, SP, #0x14
.text:000135BC ADD R0, SP, #0
.text:000135C0 STRH R3, [SP]
.text:000135C4 STRH R4, [SP,#2]
.text:000135C8 BL swscanf
.text:000135CC ADD R2, SP, #4
.text:000135D0 LDRH R3, [SP,#0x1E]
.text:000135D4 ADD R0, SP, #0
.text:000135D8 LDR R1, =aD_0
.text:000135DC STRH R3, [SP]
.text:000135E0 STRH R4, [SP,#2]
.text:000135E4 BL swscanf
.text:000135E8 ADD R2, SP, #8
.text:000135EC LDRH R3, [SP,#0x1C]
.text:000135F0 ADD R0, SP, #0
.text:000135F4 LDR R1, =aD_1
.text:000135F8 STRH R3, [SP]
.text:000135FC STRH R4, [SP,#2]
.text:00013600 BL swscanf
.text:00013604 ADD R2, SP, #0xC
.text:00013608 LDRH R3, [SP,#0x2A]
.text:0001360C ADD R0, SP, #0
.text:00013610 LDR R1, =aD_2
.text:00013614 STRH R3, [SP]
.text:00013618 STRH R4, [SP,#2]
.text:0001361C BL swscanf
.text:00013620 ADD R0, SP, #0x18
.text:00013624 BL sub_136A4
.text:00013628 LDRH R3, [SP,#0x2C]
.text:0001362C ADD R2, SP, #0x10
.text:00013630 MOV R5, R0
.text:00013634 LDR R1, =aD_3
.text:00013638 STRH R3, [SP,#0x18]
.text:0001363C ADD R0, SP, #0x18
.text:00013640 LDRH R3, [SP,#0x2E]
.text:00013644 STRH R4, [SP,#0x1C]
.text:00013648 STRH R3, [SP,#0x1A]
.text:0001364C BL swscanf
.text:00013650 LDR R3, [SP,#0x14]
.text:00013654 LDR R2, [SP,#0xC]
.text:00013658 CMP R3, R2
.text:0001365C BNE loc_13680 ; <-- WRONG KEY
.text:00013660 LDR R3, [SP,#4]
.text:00013664 LDR R2, [SP,#8]
.text:00013668 CMP R2, R3
.text:0001366C BNE loc_13680
.text:00013670 LDR R3, [SP,#0x10]
.text:00013674 MOV R0, #0 ; R0 = 0 你注册了
.text:00013678 CMP R5, R3
.text:0001367C BEQ loc_13684 ; <-- 呀,你的序列号是有效的
.text:00013680
.text:00013680 loc_13680 ; CODE XREF: sub_13578+20 j
.text:00013680 ; sub_13578+30 j ...
.text:00013680 MOV R0, #1 ; R0 = 1 你没有注册!
.text:00013684
.text:00013684 loc_13684 ; CODE XREF: sub_13578+104 j
.text:00013684 ADD SP, SP, #0xE0
.text:00013688 LDMFD SP!, {R4,R5,PC}
.text:00013688 ; End of function sub_13578
.text:00013688
观察这一行:
.text:00013680 MOV R0, #1 ; R0 = 1你没有注册!
要让程序认为我们使用了正确序列号的最简方法就是改变这行.text:00013680 MOV R0, #1
为.text:00013680 MOV R0, #0。
为什么这样改?因为这个程序会检查R0是不是等于1。显然,如果它等于1,游戏软件程序就知道它没有被注册。
现在到了把我们等候很久的十六进制编辑器HIEW押上床的时候了,更改PPC软件的代码要比windows软件难,那是因为我们不能简单地使用HIEW提供的PC汇编assembly-view。你需要知道指令集。(指令集参考见后面参考,市面上也有卖)
MOV (reg,values) xxxxA0E3
Mov R1,#0 0010A0E3
Mov R0,#1 0100A0E3
进入HIEW, 读入游戏程序/'lines.exe/', 找到下面这一段:
text:00013680 - 01 00 A0 E3 E0 D0 E2-30 80 BD E8 38 64 01 00
每个StrongARM精简型指令都包含4个字节,我们要修改的是:
01 00 A0 E3 (代表MOV R0, #1)
修改为
00 00 A0 E3 (代表MOV R0, #0)
把修改好的文件传回你的PPC, 覆盖掉原来的文件。(注意要完全退出这个游戏,覆盖才能成功)
祝你一次成功!
覆盖后,你再运行这个游戏软件看看,是不是破解成功了?
思考题:
本文“★★★”符号处提到“现在我们把00011714这一行的BNE改为BEQ,使条件反过来,这样没有注册就变为已经注册了。”
请问为什么不能直接改这里,完成软件的破解,而主张“为了让这个游戏真的认为我们注册了它,我们应该进一步考察….”?
本文到此为止,如果读者喜欢,今后还会编译更多的PPC/WinCE平台开发入门资料。