论坛首页 逆向工程技术区 阅读主题

[原创]一个简单的STM32固件分析

56 浏览 6 回复
#1 楼主 2026-06-01 21:09:05
看完论坛的 STM32固件逆向 帖子后,又在评论区发现这个求助贴 stm32芯片程序有xtea加密算法,但是数据排序的问题研究不明白 ,于是想着分析分析练练手 根据求助贴内容,概括下有用的信息一个名为stm32f103RCT6.bin的固件,从固件名可以得知MCU型号为stm32f103RCT6MCU与设备A通信时用到了XTEA加密MCU注册时用到的密钥为 BA2F96A9MCU与设备A通信时的两个加密样例如下接下来目标就是根据上面信息,找到加密函数,还原加密过程首先用IDA打开stm32f103RCT6.bin文件,选择ARM小端序,然OK进入即可 直接以Binary file打开,可以看到,IDA没有识别出任何函数 习惯性的把前几个字节"D"三下,如下图,可以大胆的猜测加载基地址为0x8000000,事实上也确实如此,当然可以根据MCU型号stm32f103RCT6去查datasheet。不过更多确定基地址的方法请参考论坛的这个帖子 固件安全之加载地址分析 ,里面详细介绍了多种方法来确定基地址,这里就不再赘述了 Edit > Segments > Rebase program... 重设基地址为0x8000000,设置好基地址后,就已经往成功路上迈向一大步了 接下来,Alt + L从前面几个地址之后开始选择,一直到末尾,右键选择"Analyze selected area" 出现下面提示框,选择Analyze,然后静待IDA分析过程结束 这时候,可以看到,IDA已经识别出许多函数了 接下来使用Findcrypt插件搜索加密常量,看看有没有什么发现,Search > Find crypto constants,如下图,可以看到,有个TEA的delta加密常量,这正好对应前面提到的MCU通信时使用了XTEA加密 跟踪查看引用该常量的sub_800E288函数,F5结果如下图所示 对比网上的XTEA加密C代码,可以知道,sub_800E288函数的参数从左到右为,加密密钥、加密输入、加密输出 对照上面XTEA加密C代码,就可以对一些变量重命名了,如下图所示,可以看到,加密时的密钥输入并不直接作为XTEA加密的密钥,而是经过了一些运算进行了变换 接下来详细分析加密过程,首先时最前面的这部分,存在大量的 左移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) 忽略左移24、左移16和左移8这些端序转换的部分,我们能发现,其实对于输入in在正式XTEA加密前没有做任何特殊处理,而对于密钥的每一个字节则与一些常量进行了异或处理。同样地,看到"0x66、0x6F ...",这些值,熟悉的情况下,很容易反应过来,这些可能是ASCII码 TAB键切换查看反汇编代码,如下图,可以看到这些常量都是基于地址0x8030A30开始的偏移量 查看0x8030A30地址,"A"一下,可以得到一个字符串,如下图所示,看得出来这是个有故事的字符串 回到反编译代码窗口,重新F5一下,可以看到,反编译代码更清晰明了了,密钥在用于XTEA加密之前,每个字节会与上面的字符串相对应的字节进行异或处理 再来看后面这部分,如下图,后面的其实就是标准XTEA加密,只不过对于加密结果的输出,同样有大小端的转换,"HIBYTE(x) BYTE2(x) BYTE1(x)"与上面的"<<24 <<16 <<8"一样,常见于数据大小端转换 到这里就结束了吗?- 答案是还没有,求助贴里面提到的MCU注册密钥是"BA2F96A9",只有4个字节大小的密钥,但是这个加密函数的密钥输入却有16个字节,所以从MCU注册密钥"BA2F96A9"到加密密钥userKey中间还有一些过程需要去分析对 sub_800E288 "X"一下,查看sub_800E288函数的交叉引用,如下图,可以看到只有一处调用 查看该调用,如下图,可以看到第一个参数加密密钥是以地址0x20000104传入的,所以加密密钥就储存在0x20000104地址处,接下来只要查看哪些函数有往0x20000104地址写数据,即可找到密钥变换的函数 接下来Text Serach搜索0x20000104,看哪些函数使用了0x20000104地址 如下图,搜索的结果并不多,挨个查看后,可以看到只有sub_800F3C8函数中有往0x20000104地址写数据的代码,而且sub_800F3C8函数参数为unsigned int类型(刚好是4个字节大小),所以基本上可以确定这个函数就是MCU注册时的密钥变换为加密密钥的函数 接下来将sub_800F3C8和sub_800E288这两个函数反编译伪代码提取出来,用VS Code简单写个程序验证下,代码如下输出结果,如下图所示,下面输出结果用到例子为上面样例的第2组数据(使用第1组效果也一样),可以看到加密结果与预期一致,至此,成功还原了整个XTEA加密过程 明文1

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-274788.htm
#2 2026-06-01 21:09:05
代码复制到VS studiow 2022,生成解决方案时下面错误,请教下怎样解决。百度回来的解决方法没效。
严重性 代码 说明 项目 文件 行 禁止显示状态错误(活动) E1696 无法打开 源 文件 "defs.h" XETA C:\Users\Lhm\source\repos\XETA\XETA\xete.c 2
错误(活动) E0020 未定义标识符 "_BYTE" XETA C:\Users\Lhm\source\repos\XETA\XETA\xete.c 3
错误 C1083 无法打开包括文件: “defs.h”: No such file or directory XETA C:\Users\Lhm\source\repos\XETA\XETA\xete.c 2


最后于 2022-10-21 12:11
被wx_一叶_733编辑

,原因:
#3 2026-06-01 21:09:05
wx_一叶_733


代码复制到VS studiow 2022,生成解决方案时下面错误,请教下怎样解决。百度回来的解决方法没效。严重性 代码 说明 项目 文件 行 禁止显示状态错误(活动) E1696 无法打开 源 文件 ...

defs.h是IDA定义的头文件可以在IDA安装目录的plugins\hexrays_sdk\include下找到,或者下载附件就可以找到
#4 2026-06-01 21:09:05
烧板侠

defs.h是IDA定义的头文件可以在IDA安装目录的plugins\hexrays_sdk\include下找到,或者下载附件就可以找到 谢谢大佬的回复。加了defs.h后,生成解决方案报C4146错误:
错误        C4146        一元负运算符应用于无符号类型,结果仍为无符号类型。  对应代码   v5 -= -0x9E3779B9;尝试关闭SDL检查重新生成时,报以下错误:        
错误        LNK2019        无法解析的外部符号 _WinMain@16,函数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) 中引用了该符号        
错误        LNK1120        1 个无法解析的外部命令        


最后于 2022-10-21 19:42
被wx_一叶_733编辑

,原因:
#5 2026-06-01 21:09:05
wx_一叶_733


烧板侠

defs.h是IDA定义的头文件可以在IDA安装目录的plugins\hexrays_sdk\include下找到,或者下载附件就可以找到 ...

第一个错你把v5 -= -0x9E3779B9;改成v5 += 0x9E3779B9;试试,后面两个我也不知道什么错,你有没有试过直接编译我附件的代码,也是报一样的错?mac和linux下编译是正常的,要不你换个编译器试试,试试直接用gcc命令编译?
#6 2026-06-01 21:09:05
谢谢,直接用你附件的代码也报同样的错误。直接用gcc命令编译成功,没有报错。
#7 2026-06-01 21:09:05
感谢,我才知道IDAPRO生成的函数形都可以修改

请登录后参与讨论

立即登录 注册账号