分析固件解密流程

Posted Neil-Yale

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分析固件解密流程相关的知识,希望对你有一定的参考价值。

本次实验中我们首先在官网上根据体积、日期等判断固件特点,结合binwalk确定要分析的对象,之后将一步步通过IDA的动态调试学习固件解密的流程。
之前的实验中我们学习了通过过渡版本的固件的解密程序来解密新版本固件,本次实验我们再次进行另一款路由器固件的测试,也是使用相同的办法,不同的是,本实验的重点,在于分析解密程序的执行流程,掌握使用ida进行远程动态调试的方法。
在这里插入图片描述

根据版本号,我们知道1.20是最新的,根据体积,我们判断1.10或者1.12可能是过渡版本。经过测试1.10是过渡版本。接下来我们以这两个版本的固件进行实验。
先分别用binwalk扫一下
这是最新版本
在这里插入图片描述

这是过渡版本
在这里插入图片描述

可以看到最新版本是加密过的。
接下来还是一样,用之前的办法对其进行解密,看是否可行。
cp $(which qemu-mipsel-static) ./
在这里插入图片描述

可以看到成功解密了。
在这里插入图片描述

接下来我们来分析该程序实际运行情况。
进行远程调试
sudo chroot . ./qemu-mipsel-static -g 1234 ./b
in/imgdecrypt dir.bin
在这里插入图片描述

win上,ida载入本地的Imgdecrypt
然后在ida端进行如下设置
在这里插入图片描述

applcaiton要填入完整的路径,input file填到所在文件夹就可以了
注意这里的hostname和之前不一样,因为这次实验中用的是远程的windows,这里hostname写ubuntu的ip,端口为之前指定的端口
点击ok之后
在这里插入图片描述

如上所示附加调试
在这里插入图片描述

点击ok
我们打开windows stirng搜索(view->open subview->string)
注意到之前解密固件结束时会打印key:xxxx
所以可以搜搜关键字key
在这里插入图片描述

双击后来到view-pc
在这里插入图片描述

双击decrypt_firmware进入其中,选中然后”x”查看交叉引用
在这里插入图片描述

如上图所示,点击ok
来到了Main函数里面
在这里插入图片描述

接下来开始我们的分析之旅
看名字也能大概智能decrpt_firmware是解密固件最关键的函数,我们在调用前一定会传参的,而bal指令有跳转的功能,所以我们选中bal decrypt_firmware下断点
按F2即可下断点,按F9命中
传参如果小于等于4个,分别由a0~a3负责,我们来看一下
在这里插入图片描述

此时还不清楚其作用,按F7跟进
看到了pem文件,这是openssl用来存储证书和密钥的
在这里插入图片描述

我们知道la用于把主存中的地址拷贝到寄存器中(把pem文件地址拷贝到寄存器中),sw用于把一个字的数据从寄存器读到存储器中;也就相当于把pe文件地址保存到存储器中,li指令用于将立即数保存到寄存器中。在这里的作用就是覆盖$v0.这里我们在li $v0,0xfffffff下断点,然后f9
在这里插入图片描述

接着f7单步跟,然后到了sub_40215c(要f7好几次)
在这里插入图片描述

可以看到第一个参数为之前看到的pem文件,第二个是0
看到了OpenSSL_add_all_algorithms_noconf函数,用于将所有算法添加到加密主题,但不使用配置文件。

接下来fopen打开pem文件
接着f8继续跟
来到了rsa_new, 分配并初始化RSA结构,PEM_read_RSAPublicKey原型为:*PEM_read_RSAPublicKey(FILE *fp, RSA **x,pem_password_cb *cb, void *u);用来读取RSA公钥
在这里插入图片描述

继续f8,回到了decrypt_firmware,在下图中看到了关键字key
在这里插入图片描述

f7进入了sub_402554
继续f7来到sub_40108c, AES_set_decrypt_key原型为:int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey);
配置aeskey以使用bit位的bit密钥key解密。密钥必须指向8位字节。
在这里插入图片描述

在jalr $t9,aes_set_decrypt_key下断点,f9命中
$a2中保存的地址76fff574里面存的就是密钥,如下图所示(选中hex view ,按G键,输入地址)
在这里插入图片描述

再往下,可以看到aes_cbc_encrypt,同样在jalr指令下断点,f9命中
AES_cbc_encrypt,原型如下:
在这里插入图片描述

一共六个参数,第一个是输入,第二个是输出,第三个是长度,第四个是密钥,第五个是初始化向量,就是前面RSA的公钥。AES_cbc_encrypt()在CBC模式下使用128位密钥和128位初始化向量ivec从头到尾加密len个字节。如果enc为0,则AES_cbc_encrypt()执行相应的解密。
在这里插入图片描述

执行完该函数后,f8,在$t7寄存器中保存的地址中指向最后输出的key

在这里插入图片描述

和我们解密时的key是一样的
在这里插入图片描述

接下来一路f8又回到了decrypt_firmware
在这里插入图片描述

但是如果继续单步调试的话,会发现还一直在循环loc_402710,我们注意到左边有/tmp/firmware.orig,我们在后面的jal sub_401780下断点
一共三个参数,第一个是输入的固件名称,第二个.orig文件(orig通常为备份文件),第三个是密钥
在这里插入图片描述

然后就进入了解密固件的函数,就不再继续跟了,直接f8步过,会执行rsa_free,用于释放rsa结构及其组件,执行后将在内存返回系统之前将密钥擦除。
在这里插入图片描述

继续f8,回到了main
可以看到decrypt_firmware执行完后接着就来到了main的最后,调试完毕。

以上是关于分析固件解密流程的主要内容,如果未能解决你的问题,请参考以下文章

Glide万字解密

OpenSSL 中 RSA 加密解密实现源代码分析

SSH 登录流程分析

eos中签名验签流程和eosjs中的加解密原理

HTTPS加密流程超详解

python中的AES加密与解密