一个简单的STM32固件分析

IoT 2年前 (2022) admin
774 0 0

一个简单的STM32固件分析

本文为看雪论坛精华文章

看雪论坛作者ID:烧板侠


看完论坛的 STM32固件逆向(https://bbs.pediy.com/thread-272811.htm)帖子后,又在评论区发现这个求助贴 stm32芯片程序有xtea加密算法,但是数据排序的问题研究不明白(https://bbs.pediy.com/thread-272872.htm),于是想着分析分析练练手。

一个简单的STM32固件分析

根据求助贴内容,概括下有用的信息。

一个名为stm32f103RCT6.bin的固件,从固件名可以得知MCU型号为stm32f103RCT6。
MCU与设备A通信时用到了XTEA加密。
MCU注册时用到的密钥为 BA2F96A9。
MCU与设备A通信时的两个加密样例如下:
明文110 BE 62 F8 E8 DC 34 46密文18C 79 F5 D1 5E A9 46 2D 明文20E 77 50 C8 C6 27 E1 BF密文236 0A 1A 6E 6E FE F0 84


接下来目标就是根据上面信息,找到加密函数,还原加密过程。



开始


首先用IDA打开stm32f103RCT6.bin文件,选择ARM小端序,然OK进入即可。

一个简单的STM32固件分析


直接以Binary file打开,可以看到,IDA没有识别出任何函数。


一个简单的STM32固件分析


习惯性的把前几个字节”D”三下,如下图,可以大胆的猜测加载基地址为0x8000000,事实上也确实如此,当然可以根据MCU型号stm32f103RCT6去查datasheet。不过更多确定基地址的方法请参考论坛的这个帖子 固件安全之加载地址分析(https://bbs.pediy.com/thread-267719.htm),里面详细介绍了多种方法来确定基地址,这里就不再赘述了。


一个简单的STM32固件分析


Edit > Segments > Rebase program… 重设基地址为0x8000000,设置好基地址后,就已经往成功路上迈向一大步了。

一个简单的STM32固件分析

接下来,Alt + L从前面几个地址之后开始选择,一直到末尾,右键选择”Analyze selected area”。

一个简单的STM32固件分析

一个简单的STM32固件分析


出现下面提示框,选择Analyze,然后静待IDA分析过程结束。

一个简单的STM32固件分析


这时候,可以看到,IDA已经识别出许多函数了。


一个简单的STM32固件分析


接下来使用Findcrypt插件搜索加密常量,看看有没有什么发现,Search > Find crypto constants,如下图,可以看到,有个TEA的delta加密常量,这正好对应前面提到的MCU通信时使用了XTEA加密。

一个简单的STM32固件分析

跟踪查看引用该常量的sub_800E288函数,F5结果如下图所示:

一个简单的STM32固件分析

对比网上的XTEA加密C代码,可以知道,sub_800E288函数的参数从左到右为,加密密钥、加密输入、加密输出。

一个简单的STM32固件分析

对照上面XTEA加密C代码,就可以对一些变量重命名了,如下图所示,可以看到,加密时的密钥输入并不直接作为XTEA加密的密钥,而是经过了一些运算进行了变换。


一个简单的STM32固件分析


接下来详细分析加密过程,首先时最前面的这部分,存在大量的 左移24、左移16和左移8,熟悉的朋友可能很快就反应过来,这个是大小端转换。所谓大小端指的是”大端序”(BigEndian)和”小端序”(LittleEndian)。用一句话来说”大端序”就是高位在前,低位在后,”小端序”就是低位在前,高位在后。举个简单例子对于同一个4字节的byte数组”12 34 56 78″,在大端序里面把它当成4字节的int的话它就是0x12345678,而在小端序里面把它当成4字节的int的话它就是0x78563412了。下面的”<<24 <<16 <<8″作用就是用来将4个byte的数组转为大端序的整数(MCU是小端序的,直接用*(int *)类型强转的话得到的结果就是一个小端序的int)。

一个简单的STM32固件分析

忽略左移24、左移16和左移8这些端序转换的部分,我们能发现,其实对于输入in在正式XTEA加密前没有做任何特殊处理,而对于密钥的每一个字节则与一些常量进行了异或处理。同样地,看到”0x66、0x6F …”,这些值,熟悉的情况下,很容易反应过来,这些可能是ASCII码。

一个简单的STM32固件分析


TAB键切换查看反汇编代码,如下图,可以看到这些常量都是基于地址0x8030A30开始的偏移量。


一个简单的STM32固件分析


查看0x8030A30地址,”A”一下,可以得到一个字符串,如下图所示,看得出来这是个有故事的字符串。

一个简单的STM32固件分析


回到反编译代码窗口,重新F5一下,可以看到,反编译代码更清晰明了了,密钥在用于XTEA加密之前,每个字节会与上面的字符串相对应的字节进行异或处理。


一个简单的STM32固件分析


再来看后面这部分,如下图,后面的其实就是标准XTEA加密,只不过对于加密结果的输出,同样有大小端的转换,”HIBYTE(x) BYTE2(x) BYTE1(x)”与上面的”<<24 <<16 <<8″一样,常见于数据大小端转换。

一个简单的STM32固件分析

到这里就结束了吗?– 答案是还没有,求助贴里面提到的MCU注册密钥是”BA2F96A9″,只有4个字节大小的密钥,但是这个加密函数的密钥输入却有16个字节,所以从MCU注册密钥”BA2F96A9″到加密密钥userKey中间还有一些过程需要去分析。


对 sub_800E288 “X”一下,查看sub_800E288函数的交叉引用,如下图,可以看到只有一处调用。

一个简单的STM32固件分析

查看该调用,如下图,可以看到第一个参数加密密钥是以地址0x20000104传入的,所以加密密钥就储存在0x20000104地址处,接下来只要查看哪些函数有往0x20000104地址写数据,即可找到密钥变换的函数。

一个简单的STM32固件分析


接下来Text Serach搜索0x20000104,看哪些函数使用了0x20000104地址。

一个简单的STM32固件分析

如下图,搜索的结果并不多,挨个查看后,可以看到只有sub_800F3C8函数中有往0x20000104地址写数据的代码,而且sub_800F3C8函数参数为unsigned int类型(刚好是4个字节大小),所以基本上可以确定这个函数就是MCU注册时的密钥变换为加密密钥的函数。

一个简单的STM32固件分析

一个简单的STM32固件分析


接下来将sub_800F3C8和sub_800E288这两个函数反编译伪代码提取出来,用VS Code简单写个程序验证下,代码如下:

#include <stdio.h>#include "defs.h"void keyExpand(unsigned int key, _BYTE *outKey);void XTEA(_BYTE *userkey, _BYTE *in, _BYTE *out); void keyExpand(unsigned int key, _BYTE *outKey){  int i; // r0   for ( i = 0; i < 16; i = (i + 1) )    *(i + outKey) = key >> (8 * (3 - i % 4));} void XTEA(_BYTE *userkey, _BYTE *in, _BYTE *out){  unsigned int v3; // r3  unsigned int v4; // r4  unsigned int v5; // r5  unsigned int i; // r6  int v7[4]; // [sp+0h] [bp-34h]  unsigned int v8; // [sp+10h] [bp-24h]  unsigned int v9; // [sp+14h] [bp-20h]   char aStefanlovesmay[] = "StefanLovesMaya!";   if ( userkey !=0  && in!=0 && out!=0 )  {    v8 = (*in << 24) + (in[1] << 16) + (in[2] << 8) + in[3];    v9 = (in[4] << 24) + (in[5] << 16) + (in[6] << 8) + in[7];    v7[0] = (userkey[3] ^ aStefanlovesmay[3])          + ((*userkey ^ aStefanlovesmay[0]) << 24)          + ((userkey[1] ^ aStefanlovesmay[1]) << 16)          + ((userkey[2] ^ aStefanlovesmay[2]) << 8);    v7[1] = (userkey[7] ^ aStefanlovesmay[7])          + ((userkey[4] ^ aStefanlovesmay[4]) << 24)          + ((userkey[5] ^ aStefanlovesmay[5]) << 16)          + ((userkey[6] ^ aStefanlovesmay[6]) << 8);    v7[2] = (userkey[11] ^ aStefanlovesmay[11])          + ((userkey[8] ^ aStefanlovesmay[8]) << 24)          + ((userkey[9] ^ aStefanlovesmay[9]) << 16)          + ((userkey[10] ^ aStefanlovesmay[10]) << 8);    v7[3] = (userkey[15] ^ aStefanlovesmay[15])          + ((userkey[12] ^ aStefanlovesmay[12]) << 24)          + ((userkey[13] ^ aStefanlovesmay[13]) << 16)          + ((userkey[14] ^ aStefanlovesmay[14]) << 8);    v3 = v8;    v4 = v9;    v5 = 0;    for ( i = 0; i < 0x20; ++i )    {      v3 += (((16 * v4) ^ (v4 >> 5)) + v4) ^ (v7[v5 & 3] + v5);      v5 -= -0x9E3779B9;      v4 += (((16 * v3) ^ (v3 >> 5)) + v3) ^ (v7[(v5 >> 11) & 3] + v5);    }    *out = HIBYTE(v3);    out[1] = BYTE2(v3);    out[2] = BYTE1(v3);    out[3] = v3;    out[4] = HIBYTE(v4);    out[5] = BYTE2(v4);    out[6] = BYTE1(v4);    out[7] = v4;  }} int main() {    unsigned int key=0xBA2F96A9;    _BYTE outKey[16];     keyExpand(key, outKey);    printf("outKey: ");    for (int i=0; i<16; i++) {        printf("%02x ", outKey[i]);    }    printf("n");    // _BYTE in[] = {0x10, 0xBE, 0x62, 0xF8, 0xE8, 0xDC, 0x34, 0x46};    _BYTE in[] ={0x0E, 0x77, 0x50, 0xC8, 0xC6, 0x27, 0xE1, 0xBF};    _BYTE out[8];    printf("in: ");    for (int i=0; i<8; i++) {        printf("%02x ", in[i]);    }    printf("n");    XTEA(outKey, in, out);     printf("out: ");    for (int i=0; i<8; i++) {        printf("%02x ", out[i]);    }    return 0;}


输出结果,如下图所示,下面输出结果用到例子为上面样例的第2组数据(使用第1组效果也一样),可以看到加密结果与预期一致,至此,成功还原了整个XTEA加密过程。

一个简单的STM32固件分析




一个简单的STM32固件分析


看雪ID:烧板侠

https://bbs.pediy.com/user-home-855195.htm

*本文由看雪论坛 烧板侠 原创,转载请注明来自看雪社区

一个简单的STM32固件分析

峰会回顾:https://mp.weixin.qq.com/s/eEbc8k8H9Pc2K0d_AHG3BA



# 往期推荐

1.CVE-2022-21882提权漏洞学习笔记

2.wibu证书 – 初探

3.win10 1909逆向之APIC中断和实验

4.EMET下EAF机制分析以及模拟实现

5.sql注入学习分享

6.V8 Array.prototype.concat函数出现过的issues和他们的POC们



一个简单的STM32固件分析


一个简单的STM32固件分析

球分享

一个简单的STM32固件分析

球点赞

一个简单的STM32固件分析

球在看



一个简单的STM32固件分析

点击“阅读原文”,了解更多!

原文始发于微信公众号(看雪学苑):一个简单的STM32固件分析

版权声明:admin 发表于 2022年10月30日 下午6:05。
转载请注明:一个简单的STM32固件分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...