在这篇文章中,我们会着重探讨三星S6调制解调器SM-G920F。我对这个设备的modem.bin文件结构非常好奇。虽然我还没能把这个文件完全解密/去模糊,但是希望这篇文章可以快速协助你了解这个文件并将其解码。
下载三星 SM-G920F Galaxy S6 固件
我使用OS X上的UnZip 5.52出现了点问题(PK compat.error),所以我在Ubuntu 15.04使用了UnZip 6.00代替。
unzip <firmware.zip> mv <firmware.tar.md5> <firmware.tar> tar xvf <firmware.tar>
你应该以这些内容为结束:
boot.img cache.img cm.bin hidden.img modem.bin recovery.img sboot.bin system.img
字节顺序:我们在modem.bin中看到的内容多数是由Little-Endian格式组成。最高有效字节位位于最高内存地址。举个例子:如果你看到下面的BOOT的SIZE,字节顺序是 48 2B 00 00,但是读取和发送都只有0x2B48作为非零数字前的任何十进制数。
TOC[0] = TOC
在十六进制编辑器中打开modem.bin,让我看看看这个文件发生了什么。
第一个2×200字节叫做TOC,我要提出一种非常有理想的猜测,它代表内容的表。它的功能是提供有关文件本身的信息,包括所有部分:TOC,BOOT,MAIN,NV 和 OFFSET,以及提供的指向这些部分的索引。
虽然上面的截图只显示了地址为0000h到0090h,其余字节都是0填充0×200字节。
TOC[1] = BOOT
如果你想要隔离文件中的BOOT部分,你需要计算基于头文件中的SIZE参数的偏移量。所以它看起来如下:
dd if=modem.bin bs=1 skip=512 count=11080 of=modem.bin_boot # calculated by using the 0x200 byte offset in decimal. skip=512 # calculated by using the 0x2B48 byte SIZE of BOOT in decimal. count=11080
TOC[2] = MAIN
和BOOT一样,你要使用下面的dd命令隔离MAIN:
dd if=modem.bin bs=1 skip=11592 count=40394816 of=modem.bin_main
*
- VERSION
是一种基于分析很多固件之后的猜想。 确保能够逆向 cbd
prepare_boot_args
或相关函数确定上面的分析是正确的。
TOC[3] = NV
TOC[4] = OFFSET
我从来没看过cbd进程或者发送这部分,所以我假设它的使用是本地到modem.bin文件而不是到CP。也许BOOT正在以某种方式使用它。
当查看BOOT代码时,你可能已经注意到了一些模式。下面我要告诉大家我从Dang et al的Practice Reverse Engineering 书 中学到的窍门:
The ability to recognize instruction boundaries in a seemingly random blob of data is important. Maybe you will appreciate it later.
在看起来是随机的blob的数据中识别命令界限的能力非常重要!你之后会非常感谢这个技能。
他说的非常棒是不是!
让我们重新回顾以下BOOT的chunk:
TL;DR – 这些ARM指令,我们接下来会反汇编sh*t。
查看这个部分很容易发现它的模式。几乎每4个字节都以0xE*结束-结果ARM分支指令使用最高位比特作为 条件码 。这些码控制指令的执行,并且通常基于在 应用程序状态寄存器 或APSR中的标志。所以,如果你想要告诉指令经常执行,你将使用AL条件,这个条件是1110b或者0xE。如果你有crackmes的经验,当你想改变一个条件JMP(x86)或B(ARM)的状态类似于转化Z或者0标志。
TODO:在文章后面这部分,我们将介绍BOOT逆向
下面内容是基于多次crash调制解调器的,逆向cbd和BOOT。
cbd # CP Boot Daemon lives in /sbin on the device CP # Cell Processor or Modem AP # Application Processor, where Android OS lives BOOT # BOOT section of the modem.bin
/dev/umts_boot0
由用于多数涉及CP boot链的I/O的rild打开。
misc_ioctl: IOCTL_MODEM_ON IOCTL_MODEM_BOOT_ON IOCTL_MODEM_DL_START # Starts `mem_start_download` IOCTL_MODEM_SET_TX_LINK # Sets Boot Link / Main Link IOCTL_MODEM_FW_UPDATE # Called after stages are sent to CP IOCTL_MODEM_BOOT_OFF # Sent after Stage 3 is sent to CP IOCTL_MODEM_BOOT_DONE # Final IOCTL for CP boot chain
start_shannon333_boot
…
shannon_normal_boot
LLI STATUS mount
prepare_boot_args
…
mem_start_download
通过抓取modem.bin的BOOT部分IOCTL_MODEM_DL_START触发,然后将它发送给CP启动boot代码。代码似乎来自Android内核中的link_device_bootdump.c。
magic == 0x424F4F54 or BOOT
std_dl_send_bin
通过BOOT代码发送解析的modem.bin到CP RAM。我觉得CMD = 是 private IOCTL command ID。
第1阶段:0×200字节头
第二阶段:0×2686040字节 MAIN
为MAIN检查CRC
我猜它是发送MAIN CRC到BOOT进行验证
第三阶段:0×100000字节 NVRAM
check_factory_log_path
设置 /sdcard/log/ ,SM-G920F没有SD卡槽,所以使用一个拙劣的虚拟SD守护进程,这个守护进程看起来没有正常工作,因为我没有在目录中找到任何存储信息。设置这个的方法应该非常简单。
std_udl_req_resp
我不确定为什么 cbd 调用了这些函数, 但是调用是在 std_dl_send_bin 之前进行的。
服务模式功能:三星在逆向过程中提供了很多帮助。
# Enable CP Debugging am broadcast -a android.provider.Telephony.SECRET_CODE -d android_secret_code://66336 <device resets> # Enable CP RAMDUMP am broadcast -a android.provider.Telephony.SECRET_CODE -d android_secret_code://9090 <device resets> # Cause CP RAMDUMP am broadcast -a android.provider.Telephony.SECRET_CODE -d android_secret_code://CP_RAMDUMP # SysDump, Copy to SD Card am broadcast -a android.provider.Telephony.SECRET_CODE -d android_secret_code://9900
我还需要弄清楚这些东西是如何组织的。希望这边文章能够帮助有兴趣的同学们进行研究。
*原文: Arm.ninja FB小编/FireFrank编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)