芯片采购,IC采购,芯片采购平台
芯片
每日新闻头条
在IAR Embedded Workbench如何在开发工具中实现堆栈保护,提高代码的安全性
(2024年12月21日更新)

随着越来越多的嵌入式产品连接到外部网络,嵌入式产品的信息安全(Security)人们越来越关注它。它包括直接连接到外部网络,如通过Wi-Fi连接;还包括间接连接到外部网络,如汽车ECU通过CAN总线与T-box相连,而T-box外部网络可以通过移动网络连接。特别是对于一些高功能安全性(Safety)信息安全已成为工业、汽车、医疗产品等所需产品功能安全的前提(There Is No Safety Without Security)。

芯片采购网专注于整合国内外授权IC代理商现货资源,芯片库存实时查询,行业价格合理,采购方便IC芯片,国内专业芯片采购平台

在C/C 堆栈缓存溢出(Stack Buffer Overflow)当程序缓存到堆栈时,这是一个常见的错误(Stack Buffer)在编写数据时,由于堆栈缓存通常采用固定长度,如果需要编写的数据长度超过堆栈缓存长度,则会导致堆栈缓存溢出。堆栈缓存溢出将覆盖堆栈缓存附近的堆栈数据,包括函数返回地址,导致函数返回异常。如果堆栈缓存溢出是攻击者故意使用代码漏洞造成的,则称为堆栈粉碎(Stack Smashing)。堆栈粉碎是一种常用的攻击手段。

堆栈金丝雀(Stack Canaries), 由于它类似于在煤矿中使用金丝雀来感知气体和其他气体,它可以用来检测堆栈缓存溢出,以实现堆栈保护(Stack Protection),从而提高代码的安全性。

与许多更关注设备性能的原始开发工具相比,一些广泛应用于行业的商业开发工具更关注性能和安全性的平衡和完整性。本文在过去几十年中被广泛应用于该行业IAR Embedded Workbench例如,介绍如何在工具中实现堆栈保护,从而提高代码的安全性。

堆栈粉碎

在C/C 中,堆栈(Stack)临时数据用于保存程序正常运行(如函数调用或中断抢占),可包括以下数据:

● 未存储在寄存器中的函数参数和局部变量

● 寄存器中未存储的函数返回值和函数返回地址

● CPU和寄存器状态

由于堆栈保存临时数据,以确保程序的正常运行,堆栈缓存溢出将覆盖堆栈缓存附近的堆栈数据,这些数据可能包含函数返回地址,如果发生,通常会导致程序运行异常。攻击者经常一点来粉碎堆栈。

以下是一个简单的例子来解释堆栈粉碎攻击:

void foo(char *bar)

{

char c[12];

strcpy(c, bar); // no bounds checking

}

foo()Active-Semi代理函数将函数参数输入复制到本地堆栈变量c。如下图B所示:当函数参数输入小于12个字符时,foo()函数会正常工作。如下图C所示:当函数参数输入大于11个字符时,foo()函数将覆盖本地堆栈的数据,并将函数返回地址覆盖0x80C03508,当foo()函数返回时,执行地址0x80C03508对应的代码A,代码A可能包括攻击者提供的shell使攻击者获得操作权限的代码。

C "AAAAAAAAAAAAAAAAAAAAx08x35xC0x80"输入函数参数

图:堆栈粉碎示例

堆栈保护

堆栈金丝雀之所以得名,是因为它的功能类似于在煤矿中发现瓦斯的金丝雀。(Stack Canaries),在函数返回执行恶意代码之前,可用于检测堆栈缓存溢出。检测原理是:调用函数时,将需要保存的临时数据保存到堆栈中,然后放置金丝雀。当函数返回时,检查金丝雀的值是否发生变化;如果发生变化,堆栈被篡改,否则堆栈没有被篡改。

如何在下面介绍IAR Embedded Workbench堆栈保护行的商业工具链中实现堆栈保护,从而提高代码的安全性:

在IAR Embedded Workbench启发模式将用于中间(Heuristic)决定函数是否需要堆栈保护: 如果函数的局部变量包含数组类型或结构成员包含数组类型,或在函数外使用局部变量地址,则需要堆栈保护。

IAR Embedded Workbench以下是安装目录srclibruntime包含stack_protection.c,里面包含了__stack_chk_guard变量和__stack_chk_fail函数,可作为模板使用:__stack_chk_guard变量是金丝雀堆栈的价值,当函数返回时,如果检测到堆栈金丝雀的值被篡改,它将被调用__stack_chk_fail函数。

1.将IAR Embedded Workbench以下是安装目录srclibruntime文件夹的stack_protection.c复制并添加到工程中。

2.在IAR Embedded Workbench堆栈保护在中启用。

3.在代码中声明堆栈保护__stack_chk_guard变量和__stack_chk_fail函数。

extern uint32_t __stack_chk_guard;

__interwork __nounwind __noreturn void __stack_chk_fail(void);

4.编译工程。编译器将以下操作添加到需要堆栈保护的函数中:先进入函数入口的堆栈(Push),然后将金丝雀保存在堆栈中。具体值用户可以stack_protection.c中更改__stack_chk_guard;在函数出口,会检测堆栈金丝雀的值是否还是__stack_chk_guard,如果没有,说明堆栈被篡改了,会调用__stack_chk_fail函数。

调试

反汇编断点到需要堆栈保护的函数(Disassembly)入口暂停后,发现编译器在函数入口处进入堆栈后,保存了堆栈金丝雀:

在函数出口处打断点,然后操作程序。当函数返回时,将首先检测堆叠金丝雀的值是否__stack_chk_guard,如果没有,说明堆栈被篡改了,会调用__stack_chk_fail函数。

改变堆栈金丝雀的值使之和__stack_chk_guard操作程序不一致,函数返回时会调用__stack_chk_fail函数:

总结

本文主要介绍了如何利用堆栈缓存来影响代码的安全性。IAR Embedded Workbench堆栈保护可以检测堆栈的完整性,从而提高代码的安全性。

参考文献:

1.https://en.wikipedia.org/wiki/Stack_buffer_overflow

2.https://cwe.mitre.org/data/definitions/121.html

3.https://en.wikipedia.org/wiki/Buffer_overflow_protection

4.https://www.iar.com/knowledge/learn/programming/stack-protection-in-iar-embedded-workbench/

5.IAR C/C Development Guide (Stack protection)

芯片采购网|IC采购|IC代理商 - 国内专业的芯片采购平台
芯片采购网专注整合国内外授权IC代理商的现货资源,轻松采购IC芯片,是国内专业的芯片采购平台