深入解析RG35XX原厂固件逆向工程与系统定制

本文详细分析了Anbernic RG35XX复古游戏设备的原厂固件架构,包括内核启动流程、输入处理机制、模拟器修改方法,并提供了在Stock OS上编译SDL应用的完整工具链配置指南。

逆向工程RG35XX原厂固件

朋友给了我一台Anbernic RG35XX进行破解。这是一款复古游戏设备(专门用于模拟老式游戏主机)。设备预装两个操作系统:原厂系统(Stock OS)和大蒜系统(Garlic OS)。原厂系统是闭源的,而大蒜系统除内核部分外是开源的(所有内核都是闭源的)。用户可以通过菜单在两个系统之间切换。

内核部分

Anbernic不会发布ATM7039S的源代码,且找不到该SOC的数据手册。RG35XX原厂系统使用的内核与大蒜系统略有不同。有人曾成功编译旧款S500设备的内核并使GPU正常工作。RG35XX的Koriki系统基于该内核,但根据Discord上的信息,最新Koriki版本使用了原厂内核。

设备没有可访问的串口和调试接口,因此尝试破解内核将是一个痛苦的过程。

RG35XX原厂启动序列

内核以uImage文件形式存储在第一个分区(FAT32)上。内置引导程序(u-boot)会加载该文件,并挂载ramdisk.img。在ramdisk.img中,我们可以找到:/init、/init.rc、loadapp.sh。内核会启动基于Android init的/init(使用bionic libc)。/init会加载/init.rc,在最后几行包含启动loadapp.sh的指令:

1
2
service loadapp /system/bin/logwrapper /loadapp.sh
class core

loadapp.sh会加载/system/dmenu/dmenu_ln。dmenu_ln位于第二个分区(ext4),这只是一个shell脚本,会启动同样位于第二个分区的/mnt/vendor/bin/dmenu.bin。

dmenu.bin是操作系统的主shell。这是用C语言编写的,使用SDL1.2,但它使用自定义输入处理而不是SDL_WaitEvent。

自定义输入处理

有些人坚信RG35XX原厂系统的输入处理比其他替代系统更快。我感受不到差异,但原厂系统确实手动处理输入事件。

为了逆向工程其工作原理,我使用了Ghidra。由于这不是安全相关软件,没有保护或混淆措施,因此代码可以很清晰地反编译。

逆向工程

它首先打开/dev/input/查找名为gpio-keys-polled的设备(该名称通过使用EVIOCGNAME请求的ioctl调用获得)。然后,它会启动一个线程(使用pthread)来轮询该设备。电源按钮与其他所有按钮是分开的设备,重置按钮(位于电源按钮下方)硬连线以重置控制台。

模拟器修改

在第二个分区的appres/bin/game中,我们可以看到每个模拟器的多个二进制文件。所有这些都经过Anbernic修改:

  • 使用自定义错误处理
  • 菜单按钮设置为显示菜单(因此所有模拟器具有相同界面)
  • 添加了视频滤镜效果(如点阵),用C语言实现(不使用GPU)

为RG35XX原厂系统编译

通常我们需要SDK来编译应用程序,但由于我们知道目标架构、调用约定和使用的库,可以绕过这个问题。要编译在原厂系统上运行的简单SDL应用,我们需要编译器、头文件和一些库。

对于编译器,从此处下载Linaro工具链4.7(最接近系统上的现有二进制文件)(选择gnueabihf): https://releases.linaro.org/archive/12.11/components/toolchain/binaries/

对于头文件,下载最新的SDL1.2并使用默认SDL配置。对于库,我们可以使用第二个分区上/lib中的文件。删除libc.so和libm.so,这两个是bionic文件会导致错误。然后,添加usr/local/lib/arm-linux-gnueabihf中的文件(同样来自第二个分区)。

然后,您应该能够手动编译所有内容。stdout/stderr的输出不可见,因此使用dup2将这些重定向到文件。

小型演示应用

在此存储库中,您可以看到我的小型演示应用。我包含了所有库,以便任何人都能轻松开始(请将Makefile中的CC路径更改为您的安装目录): https://github.com/yohanes/rg35xx-stock-sdl-demo

这是一个非常简单的应用程序,用于替换dmenu.bin(请将原始dmenu.bin重命名为orig.bin),它只提供三个功能:

  • 测试按键事件
  • 启动ADB(用于传输文件和调试),我包含了自己的ADB_ON.sh,需要复制到与dmenu.bin相同的位置
  • 启动原始启动器(现在名为orig.bin)

我不打算继续开发这个。也许有人可以基于此制作更好的启动器。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计