[GJ高端娴熟又技术的SE]DQ5反烧录技术深度解析

转自互联网

 

不出所料~高端娴熟的技术的SE在这次DQ5上果然使用了新的反烧录技术~比较牛×的是这次更是连模拟器IDEAS都成功封杀掉了~
俺这两天由于没日没夜的赶课程设计~所以第一时间没有去研究ROM~直到昨天终于浩浩荡荡的写完了700行的课设程序~闲下来的时候才发现日本牛人们早都发出了不死机版老金~说实话至今都很费解日本那帮牛人们是怎么总能第一时间搜出这不死机的关键地址的~不过嘛~算了~既然都有了~正好偷点懒~借着这个现成的成果~逆向追溯了一下高端娴熟又技术的SE的最新反烧录技术~特此公开~

这次有一点特别庆幸的~IDEAS模拟器也被这次的反烧录代码给撂倒~因此用IDEAS的调试器可以很清晰的看到该代码的工作过程~经过几个小时的研究~得到以下结论~

1,新反烧录代码原理说明

首先大致介绍这次烧录卡们出现纰漏的地方~也就是这次被SE利用的烧录和Z卡的关键不同之处~
那便是ROM的读取方式~
Z卡上~ROM是直接通过DS内置BIOS内的初始化代码载入到内存中的~而在烧录卡上~ROM的载入则始终是靠烧录卡的模拟完成~尽管现在技术已经模拟的很牛×了~但是注定还是出现了一个人们平时压根不会注意到的纰漏~那就是Secure Area~

The Secure Area is located in ROM at 4000h..7FFFh, it can contain normal program code and data, however, it can be used only for ARM9 boot code, it cannot be used for ARM7 boot code, icon/title, filesystem, or other data.

以上这段是在GBATEK中对Secure Area的解释~大致意思是说~这是一段被定义在ROM偏移量4000h..7FFFh处的区域~用作存放ARM9的启动代码~
这里要特别注意这段话的最后一句~这段区域绝对不能为ARM7启动代码~图标标题~文件~或者其他任何数据~……意思是说~放在ROM这个地方的数据是仅仅能被DS的BIOS在开机载入时访问的~其他任何时候都无法访问该区域~
这点在通常情况都会被人们给忽视掉~因为从来没有游戏或者程序将数据写入该区域并在主程序中试图访问该区域~……因此~也从来没有烧录卡为该区域写验证模拟~
那么如果说真的有游戏无聊到在程序中试图访问该段地址会得到什么样的结果呢?~用NO$GBA测试后~结果是无论读取的是8000h前的任何地址的数据~最终返回的必然是以8000h为开头的200字节(ROM访问以200字节为单位)~……

相信说到这里~看懂了的人已经能猜到这次娴熟的SE所玩弄的手腕了吧~

DQ5的烧录检测程序~依次访问0000h,0200h,0400h,8000h,8200h,8400h这6个地址~然后对输出的200字节取特征码~……根据前面的理论~如果使用的是Z版卡的话~这里将出现的结果是0000h,0200h,0400h,8000h得到的结果全部一致~而8200h,8400h则顺利读取到其他数值~
但是由于前面也说到~没有任何烧录有设计过该段区域的溢出检测~事实上就连IDEAS都没有该检测~所以在烧录卡上运行的结果便会是这6个值全部不同~(因为烧录卡允许游戏读取ROM的Secure Area~)……

因此~只要这里依次查看这6个输出值~就能很清楚的检测出玩家是在使用烧录还是用Z卡了~……

2,新反烧录代码分析

首先根据那个不死机金手指追溯下来~起作用的最基层的一个检测函数的调用为~
:02007EB8 E12FFF30 blx r0 (Jump to addr_0200819C)
:02007EBC E3500000 cmp r0,#0x0
:02007EC0 11A03004 movne r3,r4                  ;r3=1(0x1)
:02007EC4 01A0300A moveq r3,r10                  ;r3=0(0x0)

再往内深入则直接是检测的实现部分~
但是由于高端的SE的第二个新技术~使得这里我却不便放出代码了~
这新技术便是代码的动态加密解密~……

在ROM很多地方大概可以看到类似这样的代码~
:02007F84 E92D0001 stmdb r13!,{r0}
:02007F88 E1A0000F mov r0,r15                  ;r0=33587088(0x2007f90)
:02007F8C E2800010 add r0,r0,#0x10
:02007F90 EB0000D1 bl 020082DC
:02007F94 E8BD0001 ldmia r13!,{r0}
:02007F98 EA000000 b 02007FA0
:02007F9C EB004AE2 bl 0201AB2C
…………
:020080BC EA018A51 b 0206AA08
:020080C0 EB004AE2 bl 0201AC50
……
或者像这样~
:0200822C E92D0001 stmdb r13!,{r0}
:02008230 E1A0000F mov r0,r15                  ;r0=33587768(0x2008238)
:02008234 E2800010 add r0,r0,#0x10
:02008238 EB000027 bl 020082DC
:0200823C E8BD0001 ldmia r13!,{r0}
:02008240 EA000000 b 02008248
:02008244 EB002CD7 bl 020135A8
…………
:0200828C EA01D343 b 0207CFA0
:02008290 EB002CD7 bl 020135F4
:02008294 E92D0001 stmdb r13!,{r0}
:02008298 E1A0000F mov r0,r15                  ;r0=33587872(0x20082a0)
:0200829C E2400014 sub r0,r0,#0x14
:020082A0 EB000029 bl 0200834C
:020082A4 E8BD0001 ldmia r13!,{r0}

我举例的这两段代码可以看出核心部分都是调用了020082DC这个函数~该函数就是我所谓的动态解密代码~这个函数会处理紧随其下在2句相同的EB00****(****的值在不同地址不同)之间的代码~将所有代码全部变换解密~然后在运行完后再对其加密回去~……
也就是说~在上述2段代码中~我所标注……号的地方~所有的静态反汇编结果全是已经被加密了的结果~也就是说是错误的代码~……最恼人的是~这些加密代码还都被伪装成合法代码~十分具有误导性~……

经过动态解密跟踪后~我所得到的关于检测代码的结论已经在第1条里讲的很清楚了~所以这里就不再放代码了~……因为静态汇编结果无效~所以动态的长代码手动打出来很麻烦~……

3,解决手段

如同上面所述~由于检测代码的内部加密手段繁杂~再加上先后6次读取ROM~因此要从根本原因上处理该检测代码会十分麻烦~因此这里就直接修改第一层调用的返回结果就可以了~也就是第2条里开头放出的那段代码~
:02007EB8 E12FFF30 blx r0 (Jump to addr_0200819C)
:02007EBC E3500000 cmp r0,#0x0
:02007EC0 11A03004 movne r3,r4                  ;r3=1(0x1)
:02007EC4 01A0300A moveq r3,r10                  ;r3=0(0x0)

这里只需要将moveq r3,r10改成mov r3,r10即可~也就是把02007ec7处的01改成e1~

但是还有个很烦躁的问题~就是这次的DQ5的arm9还是被lz压缩过的~……(其实明明就只有600+k根本没有压缩的必要~纯粹是技术的SE的刁蛮~……)因此该内存地址还无法直接对应上ROM里的偏移~

这里稍微跟踪一下解压代码~最后得到在ROM中的对应偏移量为0a37b~
所以静态修改的话~即为把OFFSET:[a37b]的01改变为e1即可从根本上解决掉验证代码~

4,后话

写到这里~说实话很佩服高端娴熟又技术的SE对于开发新反烧录技术的执着~这次的新反烧录代码不管是从原理还是从实现上~都比上次那个仅仅检测DMA的代码要高端了数个档次~……

另外想说一下~这次之后~我大概也不会像现在这么热衷于DS上一些冷僻的技术了~因为前段时间陪伴了2年的DS彻底宣告死亡~说实话很心碎~……经过这几天的等待~终于在E3上等来了TMD不出新机的消息~……因此唯一的换新机的理由也泡汤了~……忙了几天正事后~大概也想通了~……以后~就暂时隐退算了~……以上~

你可能感兴趣的:(游戏,c,加密,汇编,解密,代码分析)