导语:从目前结果来看,我已经能够对其进行逆向破解并写出POC,而攻击者可以通过其在此设备上获得特权代码执行,并且无需使用此设备的公开越狱所使用的“boot PIN”技巧。
这段时间,我花了一些时间去深入的了解了华为的E5573调制解调器。从目前的结果来看,我已经能够对其进行逆向破解并写出POC,而攻击者可以通过其在此设备上获得特权代码执行,并且无需使用此设备的公开越狱所使用的“boot PIN”技巧。
我的这种方法适用于E3372设备,并且应该在大多数(如果不是全部)华为4G调制解调器上工作。要明确的是,这并不是最好的黑掉它的方法,但是在进行这项工作之前,我找不到有关此主题的任何内容。所以,该方法完全是在我对该设备之前没有任何认知并且没有任何可参考文件的情况下完成的。
华为E5573设备是由澳大利亚Optus代售的4G调制解调器,可在全球任何地方使用。该设备有一个小巧的白色塑料外壳,打开时看起来像这样:
可识别的调试引脚如下:
1.顶部红色框中的引脚是UART。顶行的第二和第三个引脚分别是接收(数据输入)和发送(数据输出)。
2.左侧的三个引脚是黄色的,是另一组调试引脚:最下端的引脚是“boot PIN” – 如果该引脚在器件通电时接地,则它将启动到“usb dload”模式,可用于覆盖设备的启动加载程序(从而覆盖固件)。这是通常使用的来进行设备越狱的方法。
3.右侧的引脚大概是JTAG – 这个配置在华为的设备中看起来很常见,尽管我看不到任何逻辑分析仪的引脚。
观察Boot
我的第一步是观察器件通过UART boot的过程:
此设备然后启动Linux,并运行自定义密码提示。仅有的显示是密码长度必须为8个字符,再不提供其他信息。
仔细检查过程,我遇到了让我非常好奇的一行内容:
[0000028ms]Heap:0x57d3bbe0 -- 0x57d3c180, 1440Here, I [0000029ms]Please distribute uart with command L/V/M... [0000029ms] heap:0x57d3bbe0 -- 0x57d3c180, 1440
我们从4pda.ru中得到了一个来自 user forth32的线索:
将其插入Google翻译,我们了解到其可以通过UART连接到boot各个模块:“M3控制台”,VxWorks或Linux内核,来发送“m”,“v”或“l”。不过至少还有一种模式可用(“K”),能够通过公开可用固件的逆向工程来发现。
选择“L”选项可以进行常规启动,而选择V则提供非交互式VxWorks控制台(在E3372上,这是交互式的 – 我不知道为什么在这里关闭,并且不了解设备怎么去重新启用它)。
选择“m”会提供更有趣的提示:
这里可以通过脚本完成,通过-S选项传递到minicom,可以使其更容易一些,所以你不必在boot时按住“M”按钮。以上是此脚本的下载链接。
以下是能够帮助我们的内容:
[0000029ms]Welcomehelp [0000726C]exc: help(00000000, 00000000, 00000000, 00000000, 00000000, 00000000) [00007270] command list:24 [00007272][0] help [00007272][1] d [00007273][2] m [00007274][3] system_error [00007275][4] pm_set_debug [00007277][5] pm_print_debug [00007278][6] pm_wakeup_acore [00007279][7] pm_wakeup_ccore [0000727A][8] pm_appa9_wsrc_set [0000727C][9] pm_mdma9_wsrc_set [0000727D][10] pm_mcu_wsrc_set [0000727E][11] pm_appa9_wsrc_unset [00007280][12] pm_mdma9_wsrc_unset [00007874][13] pm_mcu_wsrc_unset [00007876][14] cpufreq_print_debug [00007877][15] dump_wdt_hook [00007878][16] ios_list_echo [0000787A][17] bsp_wdt_print_debug [0000787B][18] bsp_wdt_stop [0000787C][19] bsp_dump_bus_error_status [0000787E][20] set_pm_test_timer [0000787F][21] m3_send_a_ipc [00007881][22] m3_send_c_ipc [00007882][23] set_pm_dfs_profile [00007883]exc: help = 0
通过实验表明,“d”允许我们写内存,而“w”可以让我们转存内存。从这里开始,我就会将内存转储从0运行到0xFFFFFFFF,然后将结果记录到文件中。这个生成的输出格式如下:
应该要注意的是,你可能无法获得“完整”的内存转储 ,因为该设备似乎在输出内存几分钟后就会崩溃,需要通过电源循环来进行恢复。而且,这似乎并不符合正常的内存映射:也就是说,转储在0x0和0x10000000会产生相同的结果。我写了一个Python脚本来帮助从minicom捕获文件中提取这个脚本 ,这个脚本可以从上面的内容里找到。
跨文件运行的字符串显示,我们正在查看某些任意进程内存,或者更有可能是Balong MCU控制台本身:
不幸的是,内存转储不是一个完整的可执行格式,所以加载到IDA不会显示任何类型的标题。我们从启动日志中知道处理器是ARM,所以我们可以简单地将其加载到IDA中,并开始强制转换为ARM代码,现在来查看下我们获得的内容:
初始指令看起来不像有效的ARM,但是如果我们继续执行代码,我们可以看到有意义的ARM函数(包含正确的push / pop指令)以及开始形成的数据:
奇怪的是,我们看到了对0x10000000内存区域的几个引用。出于一种灵感,我决定将可执行文件重新编码为0x1000000,然后再试一次。这一次,代码很容易分开,IDA Pro的交叉引用功能亮相:这些神秘的DWORD大多是代码中其他地方的函数指针。
回到内存转储的开始,我们也可以识别一个类似的模式: 编码0不是编码,而是一个数组的dwords。
经过半小时的逆向,我已经闻到了成功的气息:IDA管理成功地将内存转储中的一个函数交叉引用到一个字符串中,这表明这是MCU控制台本身:
这似乎是一个可触发的参数数量检测,这已经完全足够我们开始证明我们可以通过MCU控制台单独执行任意代码而无需“boot PIN”。
修改代码流
为了证明我们可以执行任意代码,我们需要证明我们可以控制代码流。上面的检测是一个奇妙的开始:我们可以触发这个代码流,并且结果也是具有逻辑的:如果有超过5个参数,那么将显示一个说明有太多参数的消息,该命令将不会执行。因此,如果我们可以降低这个限制,那么我们可以控制代码的执行。
通过一个小实验,我们可以计算出,“m”命令允许我们一次编辑内存,但只能是一个双字节的,如下(必须提供一个完整的DWORD,否则将假设丢失的字节为零并覆盖您的目标地址):
m 0x1000F000 0xAABBCCDD
我们可以用这个来修改0x1000075C的检测,如下所示,保持字节顺序:
m 0x1000075C 0x0F02F1BB
这应该意味着我们可以为一个命令提供不超过两个参数,而在之前我们最多可以提供5个参数。首先,我们来测试一下,使用5个参数的“d”按照预期进行操作(下面的测试用例使用minicom脚本自动化,所以它缺少一些输出 – 但已经足够接近了)。
现在,我们在脚本中添加“m”命令,进行尝试:
我们也可以编辑错误信息:
成功!
最后的想法以及进一步的工作
1.识别出那个未知的二进制文件,并将其恢复为完整的格式进行进一步分析。
2.证明我们能够编辑二进制文件中的资源,以及执行任意代码。
3.证明此次的特权代码执行没有“boot PIN”的技巧,这是一个全新的启动加载程序(而不是从routerunlock.com上来对您的设备进行越狱)。
4.按理说应该足以加载任意特权代码,尽管通过UART非常缓慢。
虽然此设备存在比较普遍的越狱(而且要快得多)方式,但我相信我的这项工作可作为E5573设备和那些目前尚未完成越狱的其他设备进行逆向的一个基础思路。