固件解密
有些IOT设备会对固件加密甚至签名来提高研究门槛和升级时的安全性,因为加解密比较耗费资源,这类设备一般配置会比较高,比如一些路由器和防火墙。
一、固件加密判断
判断固件是否加密比较简单,有经验的小伙伴有二进制编辑器打开就能看出一二,一般会存在以下特性。
除了固件指示头没有可见字符,(除去header)数据按比特展开01频率基本一致binwalk(-e)无法解析固件结构,且(-A)没有识别出任何cpu架构指令。
如果满足上述特点,就会猜测固件已被加密,固件解密一般会从这几个角度,但也不局限于下面的方法。
二、硬件获取密钥
此种方法只限于固件始终以加密状态存在,当系统启动时才通过解密解包加载至flash,且设备缺乏(UART/JTAG等)动态调试手段。由于flash中有完整的解密过程,可以通过编程器读取flash,逆向解密算法和密钥,达到解密固件的目的。比如从某设备的读取的flash内存分布如下:
0x000000-0x020000 boot section
0x020000-0x070000 encrypt section
0x070000-0x200000 encrypt section
0x200000-0x400000 config section
显然我们需要的加密过程在boot section中,我们需要从中找到加密算法和密钥,一般加密都采用AES等公开分组算法,关键是找到分组模式,IV(非ECB)和密钥。将boot加载到IDA pro中,并没有自动识别:

可以通过对比ARM代码最开始部分的中断向量表结构手动识别,常见的入口代码如下所示。
.globl _start
_start:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
...
_irq:
.word irq
之后可以就可以逆向得到加密算法为AES,密钥通过设备序列号的sha256哈希获得。

通过IDA pro识别此类结构将在后文介绍RTOS时探讨,利用这种固件加密方式的设备安全级别教高,一般设备只在升级时进行解密验证。
三、调试直接读取
这个方法最容易理解,即在设备启动后利用UART、JTAG、Console或网络等手段把固件(打包)回传,这样就绕过了解密环节。值得注意的是需要设备提供这些接口,具体方法因设备不同而异,这些接口的使用将会在硬件篇里作介绍。
四、对比边界版本
此种方法适用于厂商一开始没采用加密方案,即旧版固件未加密,在某次升级中添加了解密程序,随后升级使用加密固件。这样我们就可以从一系列固件中找到加密和未加密之间的边界版本,解包最后一个未加密版本逆向升级程序即可还原加密过程。

通过下载上图所示某路由器固件,解包后通过搜索包含诸如“firmware”、“upgrade”、“update”、“download”等关键字的组合定位升级程序位置。当然存在调试手段也可以在升级时ps查看进程更新定位升级程序和参数:
/usr/sbin/encimg -d -i <fw_path> -s <image_sign>
通过IDA pro逆向encimg程序很快得到加解密过程代码,采用了AES CBC模式:
AES_set_decrypt_key (
// user input key
const unsigned char *userKey,
// size of key
const int bits,
// encryption key struct which will be used by
// encryption function
AES_KEY *key
)
AES_cbc_encrypt (
// input buffer
const unsigned char *in,
// output buffer
unsigned char *out,
// buffer length
size_t length,
// key struct return by previous function
const AES_KEY *key,
// initializatin vector
unsigned char *ivec,
// is encryption or decryption
const int enc
)
五、向升级程序
此种方法适用于已经通过接口或边界版本得到升级程序,可以利用分组算法的盒检测工具来判别加密算法和定位位置,当然binwalk也可以解析某些简单情况,比如某工控HMI固件:
iot@attifyos ~/Documents> binwalk hmis.tar.gz
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
34 0x22 OpenSSL encyption, salted, salt:0x5879382A7
直接加载升级程序,定位openssl调用很容易就得到解密命令:

六、漏洞获取密钥
如果找不到边界版本,又找不到调试接口或不熟悉硬件调试,可以考虑采用历史版本漏洞先获取设备控制权,在拿到升级程序逆向加密算法。这种方法比较取巧,需要设备存在RCE漏洞的历史固件,通过降级操作植入漏洞获取权限,下载所需升级程序,然后逆向得到加密算法。
Last updated