nes逆向
https://blog.csdn.net/fogota/article/details/6767758
背景
一、如何找到Mapper=0的NES游戏?
你自然有不少的NES文件,同时也知道上哪去下载这些文件,你可以多下载一些你觉得简单的游戏。我下面介绍查看mapper值的方法。
我已经找到几个Mapper=0的游戏:超级玛丽、坦克大战
方法有两个
方法(1) VirtuaNES
用VirtuaNES 打开NES文件,点菜单“文件-ROM信息”就可以查看mapper值了。
方法(2) NesHeader
用网友“疾风の迅雷”写的一个软件NesHeader.exe,可以批量读取整个文件夹上所有NES文件的ROM信息。
**
找到Mapper0的NES游戏之后,我们来确定机器码的运行首地址。
Mapper0的nes只有一段机器码段,这就好办了。其首地址有可能是
$8000 或 $C000
先不要问我为什么有两个可能性,我先来教你判断。
二、怎样判断Mapper0的NES游戏的机器码的首地址。
第一步:我提供两个办法。
先看NES文件的大小,
NES文件
另一个办法:用上面提到的NesHeader.exe,查看PROM大小,
第二步:如果nes大小=24K则要查看游戏程序的运行地址区域。
用Fcdebug打开ROM,点菜单DEBUG,打开“指令显示/控制”窗口。按“暂停”,查看(运行)地址。(这时看到的是正在运行任一条指令)
本办法是针对Mapper0的NES而设计的,对于别的Mapper值则完全不适用。
钻牛角的人要跑来问“别的Mapper是如何找到首地址?”
我在文章的后面解答一下吧。
**
接下来要将机器码从NES文件上分离出来。
你要知道,NES文件是由文件头(Head)、程序ROM(即PROM)、图形ROM(即VROM)组成。在ROM里面,连接的顺也是Head-PROM-VROM。其中Head固定占16字节;PROM占[n x 16K],n是一个倍数;VROM占[m x 8K],m是一个倍数。
朋友们看出来了,这个PROM的大小和VROM的大小在ROM信息中出现过。
PROM一般是16K为1页(1 bank),也有8K,4K为单位的。因不同的Mapper值而异。(NES文件中统统以16K为单位记录)
我们专门说Mapper0,这个号是不切页的,所以可以看成只有1页,也就是说:
注:机器码首地址,指机器码运行时在寄存器中的首地址,不是NES文件上的地址。
NES大小
PROM大小
机器码首地址
机器码末地址
机器码长度
40K
在上面的述中揭示了一些东西。要是看不明白也没关系,下面可以照着做。
三、如何才能将机器码从NES文件上分离出来?
我提供两个办法。上面用到的地址,我都算准了。
方法(1)DUMP法:
用FCdebug(NES_debug)运行ROM,点菜单DEBUG,打开“指令显示/控制”窗口。按“暂停”,在窗口的最底行,找到“内存”,在边上的两个编辑框里,填入首地址和末地址,建议末地址统一填FFFF,其中$号省略。然后按“DUMP下来”,保存成mem文件。
FCdebug是VirtuaNES的一个改版,加入了debug功能。
方法(2)HEX编辑法:
用HEX类编辑软件,打开ROM。例如Hex Workshop。
将这个地址以下的部分(包括这个分界点)删除或剪切走。留下的部分另存为mem文件。
**
终于到了反汇编软件上场了。
有人会问:“这个mem是什么文件?”
这个是内存文件,其实就是机器码,里面没有别的东西了。这个后缀名不重要,因为都没有关联软件。你叫他bin文件或别的都行。我只为统一叫法。
四、如何将mem文件显示成汇编代码呢?
我用这个
看图标,这是我用的“反汇编器”。它可以对多种CPU进行反汇编。
(1)打开它,先要选CPU,在窗口右上角选6502。
(2)用这个反汇编软件,打开mem文件。
(3)然后点选项“BIN文件”,在开始地址,填上“首地址”,
(4)确定提勾“立即反编译”,点“确定”就OK
(5)保存反汇编的asm文档,结束。
**
汇编代码是反出来了。可是问题来了:“从何看起?”
针对NES的结构,机器码是有一个入口的,这个入口的地址写在一个固定的地方。我们叫“指针”。共有3个指针,都放在一起,分别指向NMI、RESET、IRQ|BRK。其中RESET就是主程序的入口,NMI是中断的入口,IRQ|BRK是另一种中断入口。
五、如何找到程序的入口?
将asm文件(用记事本)打开,滚动条向下拉,拉到底。看到FFFA到FFFF的数据,抄下来。
记a,b 是一组指针,实际地址为ba,即a为低位,b为高位。如此类推得3组指针
NMI = ba
RESET = dc
IRQ|BRK = fe
NMI = $8035
RESET = $8000
IRQ|BRK = $805C
六、注意事项
反汇编的结果不是全都是代码,其中有部分可能会是数据,也有可能整页都是图型(CHR)数据。反汇编器总是优先将能够反成代码的译成代码。于是你会发现在DB旁边出现没有作用的代码,有时发现代码去读一个指令,其实是在读指针或数据。
另外一些软件生成的ROM会加入一些没机会运行的代码。这可能是优化不完全。
七、局部反汇编,只做第三步和第四步就行。其中第三步用dump法。具体,多接触就会了解。
疑难解答:
Mapper是什么?
Mapper是一个编号,用于区分不同电路结构的卡带。NES模拟器拿一个ROM当作是一个卡带来模拟,那么卡带的电路也要区分才能模拟的。卡带不是标准统一的,当时不同的NES游戏开发商都开发出自己独有的保密的卡带;还发展出多个不同的升级产品,可以令游戏性能更理想;同时对游戏程序有保密作用。
为什么Mapper0的ROM机器码首地址有可能是$8000或$C000?
Mapper0就是表示卡带电路没有任何特别,卡带的寄存器是直接接到CPU总线上的。也就是有可能
(1) 16K的寄存器接到$8000-$BFFF的地址上并镜像到$C000-FFFF。
(2) 32K的寄存器接到$8000-$FFFF的地址上。
在(1)情况下,$8000-$BFFF和$C000-FFFF的机器码是完全一样的。主要是看程序的作者,将代码(基于).org $8000还是.org $C000进行编译的。
我本来想在“判断首地址”的方法用程序入口的办法,但这个不准确,因为在(1)情况下我可以恶作剧的将程序入口改成对应镜像的位置,程序一样是正常运行的。
Mapper0以外的ROM是如何找到首地址?
只有Mapper0不切页,换句话说,Mapper0是静态将寄存器接入总线。其余的Mapper都是动态的将寄存器接入总线。也就是说,是通过程序控制接入某一块寄存器接入总线上某地址段,而原接入的块(页)断开。
答案就是:你要先知道最早是默认接入的寄存器页,将之按mapper0的方法反汇编。然后从程序入口,一行一行看代码,看调入了哪一页,然后计算这一页的位置,将它分离出来。再反汇编。如此直到掌握全部页的动向。
FCEUX使用
debug ppu viewer
右键可以更改颜色
https://fceux.com/web/help/PPUViewer.html
介绍
NES 架构包括一个 6502 CPU 以及一个称为 PPU(图片处理单元)的自定义视频控制器。PPU 的视频内存与主 CPU 内存分开,可以通过特殊端口进行读/写(请参阅 PPU 内存)。
PPU 查看器将仅显示当前 PPU 内存的内容。它不会以任何方式更改游戏数据。
使用 PPU 查看器
在扫描线上显示
此选项使其显示屏幕绘制该特定扫描线时 PPU 的外观。它对于像 SMB 这样的游戏很有用,这些游戏会在帧中交换模式表(例如,用于状态栏内容)。
右键单击其中一个 PPU 面板将更改显示它的调色板,在图案调色板之间循环,然后是 sprite 调色板,然后是第九个固定的灰色调色板(如果所有调色板当前都是黑色的,则可用于检查 CHR)。
将鼠标光标放在图块上将显示图块地址。将光标移动到调色板颜色上将给出调色板地址。
当 Code/Data Logger 运行时,您还可以使用 “Mask unused graphics” 功能。或者,您只能遮罩已使用(绘制或以其他方式访问)的图块,并强调未使用的图块(例如,为了查找秘密 Sprite)。
注意:此功能仅适用于使用 CHR ROM 的游戏,因为代码/数据记录器仅记录对 CHR ROM 的访问。
debug cheat
先看ram search 确定变量
再cheat 可以导入随机数
例题
例题xctf chase
mapper为0
看到机器码从8000
ida用二进制打开 以6502的形式
flag01
可以直接ce开挂,
TPCTF{D0_Y0U_L1KE_
也可用FCEUX自带的cheat改动
flag02
法1
经过不断调试发现AB对应的值和场景有关,每个场景对应值固定且范围普遍在0-60之间,那么尝试爆破,调整AB的值,改内存时发现会有随机性,相同的值不保证每次的闪烁结果相同,这里是尝试到0x15时看到flag2:
法2
第二段有点misc的感觉,猜测也是在内存里面只不过不会加载到屏幕上,由于每段flag开头都会有THE FLAG PT我们搜索这几个字符的tile 34 28 25,一共发现两个其实一个是第一段flag,tile D2就是代表字符2 D1也就是字符1
这段是flag1
第二段是flag2
1 |
|
THE FLAG PT2 FOR YOU IS PLAY1N9_6@M3S_ LBRDTRPLGXAQRPAQGXCSRPEUGXCSRPIYGXGWRPFVGXHXIPFPDPAP GWWWH H H H @@@LEVEL GEMS LIVES CDMLO@0
flag03
看ppu viewer
ON_Y0UR_N3S?}
FLAG:TPCTF{D0_Y0U_L1KE_PLAY1N9_6@M3S_ ON_Y0UR_N3S?}