固件解密
Last updated
Last updated
有些IOT设备会对固件加密甚至签名来提高研究门槛和升级时的安全性,因为加解密比较耗费资源,这类设备一般配置会比较高,比如一些路由器和防火墙。
判断固件是否加密比较简单,有经验的小伙伴有二进制编辑器打开就能看出一二,一般会存在以下特性。
除了固件指示头没有可见字符,(除去header)数据按比特展开01频率基本一致binwalk(-e)无法解析固件结构,且(-A)没有识别出任何cpu架构指令。
如果满足上述特点,就会猜测固件已被加密,固件解密一般会从这几个角度,但也不局限于下面的方法。
此种方法只限于固件始终以加密状态存在,当系统启动时才通过解密解包加载至flash,且设备缺乏(UART/JTAG等)动态调试手段。由于flash中有完整的解密过程,可以通过编程器读取flash,逆向解密算法和密钥,达到解密固件的目的。比如从某设备的读取的flash内存分布如下:
显然我们需要的加密过程在boot section中,我们需要从中找到加密算法和密钥,一般加密都采用AES等公开分组算法,关键是找到分组模式,IV(非ECB)和密钥。将boot加载到IDA pro中,并没有自动识别:
可以通过对比ARM代码最开始部分的中断向量表结构手动识别,常见的入口代码如下所示。
之后可以就可以逆向得到加密算法为AES,密钥通过设备序列号的sha256哈希获得。
通过IDA pro识别此类结构将在后文介绍RTOS时探讨,利用这种固件加密方式的设备安全级别教高,一般设备只在升级时进行解密验证。
这个方法最容易理解,即在设备启动后利用UART、JTAG、Console或网络等手段把固件(打包)回传,这样就绕过了解密环节。值得注意的是需要设备提供这些接口,具体方法因设备不同而异,这些接口的使用将会在硬件篇里作介绍。
此种方法适用于厂商一开始没采用加密方案,即旧版固件未加密,在某次升级中添加了解密程序,随后升级使用加密固件。这样我们就可以从一系列固件中找到加密和未加密之间的边界版本,解包最后一个未加密版本逆向升级程序即可还原加密过程。
通过下载上图所示某路由器固件,解包后通过搜索包含诸如“firmware”、“upgrade”、“update”、“download”等关键字的组合定位升级程序位置。当然存在调试手段也可以在升级时ps查看进程更新定位升级程序和参数:
通过IDA pro逆向encimg程序很快得到加解密过程代码,采用了AES CBC模式:
此种方法适用于已经通过接口或边界版本得到升级程序,可以利用分组算法的盒检测工具来判别加密算法和定位位置,当然binwalk也可以解析某些简单情况,比如某工控HMI固件:
直接加载升级程序,定位openssl调用很容易就得到解密命令:
如果找不到边界版本,又找不到调试接口或不熟悉硬件调试,可以考虑采用历史版本漏洞先获取设备控制权,在拿到升级程序逆向加密算法。这种方法比较取巧,需要设备存在RCE漏洞的历史固件,通过降级操作植入漏洞获取权限,下载所需升级程序,然后逆向得到加密算法。