首页
社区
课程
招聘
[原创]Arm裸机程序分析
发表于: 2023-5-18 14:07 14244

[原创]Arm裸机程序分析

2023-5-18 14:07
14244

Arm裸机程序分析

在很多时候,程序在实际运行的时候是没有操作系统的,属于裸机运行模式,在Linux中无法直接运行。因此,这个时候就需要使用其他的方式进行分析。以一道ctf题目为例子,来学习一下ARM架构的裸机程序的分析。

程序地址:

b50K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8W2)9J5k6h3A6S2M7Y4k6A6M7$3!0B7i4K6u0W2j5$3!0E0i4K6u0r3j5$3S2S2L8r3I4W2L8X3N6W2k6X3W2D9k6i4y4Q4x3V1k6U0L8$3&6X3N6i4y4W2k6p5q4d9e0g2)9J5k6h3S2W2P5q4)9J5k6h3j5@1k6e0j5I4y4U0f1@1y4h3k6X3x3h3p5I4z5o6f1J5y4X3t1&6k6o6q4U0z5e0m8W2j5e0j5@1z5r3k6X3

这个程序是STM32F103X8,因此可以在这个网站上找到对应的dataset:a0dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2S2L8r3I4V1j5i4c8S2M7$3S2W2k6i4c8Q4x3X3g2U0L8$3#2Q4x3V1k6Q4c8e0y4Q4z5o6m8Q4z5o6t1`.

用ida打开该程序,把程序设置成arm小端序:

Dataset中其内存映射如下图:


打开后,首先是如下图的数据:

可以看到,这些数据并没有被识别位代码,第一个0x20000730,根据上面的内存映射可以知道这里是SRAM区域,紧跟着第二为0x8000101位于SRAM区域下面的那一块儿内存区域中的Flash memory中。内存映射图的最下面的详细的内存映射如下图:

可以看到Reset是在0x00000004处,指向了0x00000101,并且在stm32中支持重映射,其会将0x08000000开始的内容重映射到首地址0x00000000中。查看这两处内存的内容:

0x00000000:

0x08000000:

可以看到这两处内存中的内容是一样的。

也就是说在ida中看到的第二个数据0x8000101就是reset所执行的地址,也就是reset。到0x8000101处:

可以在0x8000104这条指令的地方有一个start,这个start是sp,也就是说0x20000730是堆栈地址,那么0x08000100基本上就可以确定是程序的入口地址了。在0x080000f6处有一个比较大的跳转,调用了函数sub_8001084。看一下sub_8001084:

伪代码如下图:

可以看到满足某些条件就可以输出出来flag。但是这些红色的内存看起来不太好看,可以在Edit->Segments->Creat segment来创建一个段,把这些内存区域包括进去就好了。那么看来函数sub_8001084就是主函数。

接下来使用MDK动态调试一下程序,在开始之前先去下载对应的包(853K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2C8k6h3W2D9i4K6u0W2j5i4u0E0i4K6u0W2j5$3!0E0i4K6u0r3M7r3q4U0K9%4y4Q4x3V1k6Q4x3U0W2Q4x3V1y4Q4c8e0g2Q4z5o6S2Q4z5f1u0Q4c8e0g2Q4b7V1u0Q4b7V1q4Q4c8e0g2Q4b7e0g2Q4b7V1c8Q4c8e0g2Q4b7U0N6Q4b7e0g2Q4c8e0N6Q4b7e0S2Q4z5p5u0Q4c8e0g2Q4z5e0m8Q4z5p5g2Q4x3V1y4Q4c8e0c8Q4b7V1k6Q4b7f1g2Q4c8e0k6Q4z5e0c8Q4b7U0W2Q4c8e0W2Q4z5o6g2Q4z5p5c8Q4c8e0N6Q4b7V1c8Q4b7f1g2Q4x3@1p5`.

按CTRL+f5开始调试,然后在下方command窗口将源文件load进去:

然后点左上方的RST按钮:

然后程序就会自动跳到0x08000000处并且断下:

从上面知道函数入口点在0x08000000,主函数在0x08001084,直接运行到0x08001084:

根据主函数中的伪代码,可得知加密函数的key的地址为:0x2000000C,解密后的flag的地址为:0x2000031C。在主函数中sub_8000560和sub_800055C都对key进行了操作,那么这俩肯定不是解密函数,只剩下了sub_8000248函数。

那么直接运行程序貌似就可以直接输出flag了:

但是提交flag是错误的。

想一想好像也只能是解密函数出问题了,运行到地址0x080010EA调用sub_8000248函数的地方:

根据结合上面的函数的参数分析,sub_8000248函数的第三个参数应该是解密的key,从上面调试来看,传入sub_8000248函数的key的地址是0x2000000C,但是调用sub_8000248函数之前sub_800055C函数对key进行了处理,也就是说key传错了,传入的是处理之前的key,因此这个地方要传入的应该是0x2000026c,所以把传入的地址改为0x2000026c就可以了。因此直接在MDK中修改R2寄存器的值为0x2000026c:

然后运行,因为是临时修改所以只有第一个flag是正确的输出:


当然也可以直接给程序打patch,在程序中把代码改掉。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2023-6-4 10:58 被kanxue编辑 ,原因:
上传的附件:
收藏
免费 6
支持
分享
最新回复 (4)
雪    币: 15661
活跃值: (18963)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-5-18 14:26
0
雪    币: 338
活跃值: (85)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
分析这种程序得用firmloader或者svdloader加载对应的svd文件再进行分析
2023-6-3 19:35
1
雪    币: 303
活跃值: (1757)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
接下来使用MDK动态调试一下程序,在开始之前先去下载对应的包(09eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2C8k6h3W2D9i4K6u0W2j5i4u0E0i4K6u0W2j5$3!0E0i4K6u0r3M7r3q4U0K9%4y4Q4x3V1k6Q4x3U0W2Q4x3V1y4Q4c8e0g2Q4z5o6S2Q4z5f1u0Q4c8e0g2Q4b7V1u0Q4b7V1q4Q4c8e0g2Q4b7e0g2Q4b7V1c8Q4c8e0g2Q4b7U0N6Q4b7e0g2Q4c8e0N6Q4b7e0S2Q4z5p5u0Q4c8e0g2Q4z5e0m8Q4z5p5g2Q4x3V1y4Q4c8e0c8Q4b7V1k6Q4b7f1g2Q4c8e0k6Q4z5e0c8Q4b7U0W2Q4c8e0W2Q4z5o6g2Q4z5p5c8Q4c8e0N6Q4b7V1c8Q4b7f1g2Q4x3@1q4Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4x3X3c8Q4c8e0S2Q4b7V1k6Q4z5e0W2Q4c8e0c8Q4b7U0S2Q4b7f1q4Q4c8e0k6Q4z5e0S2Q4b7f1k6Q4c8e0S2Q4b7e0k6Q4z5o6q4Q4c8e0g2Q4z5f1y4Q4b7e0S2Q4c8e0N6Q4b7e0q4Q4b7f1y4Q4c8e0c8Q4b7V1u0Q4b7U0k6Q4c8e0c8Q4b7U0S2Q4z5p5q4Q4c8e0S2Q4b7U0m8Q4z5o6y4Q4c8e0S2Q4b7f1k6Q4z5e0g2Q4c8e0g2Q4z5e0m8Q4z5e0N6Q4c8f1k6Q4b7V1y4Q4z5f1j5`.
2024-1-22 20:19
0
雪    币: 5621
活跃值: (31896)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享
2024-1-23 09:30
1
游客
登录 | 注册 方可回帖
返回