freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

关于thumb2指令下函数运行地址对齐问题及验证固件分析
buailiulian 2022-10-28 11:24:34 712105
所属地 北京

近期,在分析Thumb2指令的一个固件文件时,发现Thumb2指令集下执行函数的运行地址不对齐?

于是,为了分析一下原因,找了手头上现有的一款基于Cortex3内核的一块板子来实际执行看一下,结合编译后的Hex文件,通过IDA来进一步验证一下Thumb2运行地址不对其的现象。

操作示例:

  • 固件代码

找了一个FreeRTOS的示例工程,加入几行打印函数地址的日志:

1666926068_635b45f4e2399c170c40d.png!small

  • 通过hex2bin将编译后的Hex文件转成二进制bin文件

执行情况:

1666926085_635b4605be7806fe44221.png!small

  • 通过ue打开bin文件备用,如下1666926167_635b4657340201244067c.png!small
    • 通过Keil-IDE加载测试代码,如下:

    通过IDE debug调试后,板子reset之后在内部时序逻辑的控制下,将0x00000000地址的内容读取到SP;将0x00000004地址的内容读取到PC。此时SP中存放的是栈顶地址,PC中存放的是Reset_Handler复位处理函数地址。

    1666926217_635b46890b6a30a71df34.png!small1666926222_635b468ea62827b73f0d2.png!small
  • 通过IDA Pro加载上述第二步生成的bin文件,配置过程如下:1666926770_635b48b210ddf4314c2ee.png!small1666926776_635b48b8049b96d062afd.png!small

    通过在示例工程中的配置,来定义加载到IDA中的内存及存储映射地址,如下:

    1666926788_635b48c4943454a04b403.png!small1666926797_635b48cd0c686e801f0eb.png!small
  • ida加载后如下:1666926807_635b48d7dc6f496d42cf5.png!small
  • 顺利找到程序入口地址:1666926834_635b48f2676d50a25465c.png!small1666926848_635b49008ac77f67cd39c.png!small

    进而找到main函数的执行地址,发现通过ldr加载到寄存器时的地址为main函数真正地址+1;通过debug,也可以验证,如下:

    1666926860_635b490c36bee96286f3a.png!small1666926865_635b4911f36fe9c5942ca.png!small

    通过资料了解到ARM指令是4字节对齐的,Thumb-2指令是2字节对齐的,所以这里main函数和函数Delay_nS的地址应该是2字节对齐的,但是打印出来的值却是:08000BB1和080002D9。main函数的地址和test函数的地址都成了奇数地址了。

    这个问题在于有些ARM处理器即能使用ARM指令,又能兼容Thumb指令,同一个应用程序中可能同时存在ARM指令和Thumb指令,这两者的处理方式肯定是大不相同的,所以为了切换ARM状态和Thumb状态,在跳转到Thumb指令编写的代码块的时候,将程序地址的最低位置1(因为不管是ARM指令还是Thumb指令,都至少是2字节对齐的,所以最低位一定是0,所以最低位可以拿来用于区分ARM状态和Thumb状态),这样处理器识别到最低位为1的话就会切换到Thumb状态,否则则是ARM状态。Thumb2指令集也是为了兼容以前的ARM状态和Thumb状态所以这样做的。

    所以编译器编译STM32F1的程序的时候,会把函数的真实地址 加上1 作为常量放在ROM空间(如果这个函数的地址有被用到的话),获取函数的指针的时候就会获取到最低位被置1的一个地址。如下图,获取Delay_nS的地址的时候,到0x08000BC4地址处读取到了0x080002D9的值,这其实就是Delay_nS的真实地址0x080002D8 + 1得到的。

    1666926886_635b49268ca23acb2bddc.png!small

    程序debug,打印出的日志如下:

    1666926896_635b493079a44fe6cda3a.png!small

    最后,在ue中固件文件中也找到了相应的Delay_nS函数的入口地址,实际在flash中的地址也是+1的,如下图:

    1666926909_635b493d4ad9100306df5.png!small
# 渗透测试 # 黑客 # CTF # 灰产圈 # ARM汇编
本文为 buailiulian 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
buailiulian LV.2
这家伙太懒了,还未填写个人描述!
  • 2 文章数
  • 2 关注者
智联网车辆的安全攻击和防御手段总结
2024-10-08