BOA中文网!

[原创] linux 内核安全增强(一)— stack canary-二进制漏洞-看雪-安全社区|安全招聘|kanxue.com

BOA中文网

栏目分类
[原创] linux 内核安全增强(一)— stack canary-二进制漏洞-看雪-安全社区|安全招聘|kanxue.com
发布日期:2025-01-04 16:20    点击次数:85
 版权声明:本文为CSDN博主「ashimida@」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/lidan113lidan/article/details/120318707更多内容可关注微信公众号 一、背景知识 —— aarch64的函数栈1. 栈生长方向与push/pop操作    栈是一种运算受限的线性表, 入栈的一端为栈顶,另一端则为栈底, 其生长方向和操作顺序理论上没有限定. 而在aarch64平台上:栈是向低地址方向增长的(STACK_GROWS_DOWNWARD)栈的PUSH/POP通常要先移动SP:PUSH操作为PRE_DEC,即 PUSH操作为 sp = sp -4; store;POP操作为 POST_INC,即POP操作为 read; sp=sp+4;2. 返回地址的存储    x86平台是call指令时自动push函数返回地址到栈; ret指令自动pop函数返回地址出栈;  这两步操作都是在callee执行前硬件自动完成的.    而在arm/aarch64平台发生函数调用时(blx),硬件负责将函数的返回地址设置到通用寄存器LR(/X30)中, callee中的代码负责将LR保存到栈中(需保存的寄存器参考AAPCS标准) 3. 函数栈分配    在不考虑动态分配的情况下, 函数中使用的栈大小在编译阶段就已经确定了(见备注1), 一个aarch64中的典型的程序栈如下所示:   和x86/arm平台的不同在于: x86和arm平台的函数返回地址通常都存于callee栈的栈底:x86平台是硬件完成的push/pop操作,故返回地址先入栈arm平台callee函数的首指令通常是先push通用寄存器, 函数返回前最后语句pop通用寄存器如:000005fc <test>:             5fc:   b590            push    {r4, r7, lr}                /* 先push通用寄存器和函数返回地址 */ 5fe:   b089            sub     sp, #36 ; 0x24              /* 再为局部变量预留存储空间 */ 600:   af00            add     r7, sp, #0 602:   6078            str     r0, [r7, #4]     ...... 634:   3724            adds    r7, #36 ; 0x24 636:   46bd            mov     sp, r7 638:   bd90            pop     {r4, r7, pc}      在此两个平台中若发生了栈溢出则直接可以覆盖到当前函数的返回地址.而aarch64通常是先预留栈再保存函数返回地址,如:0000000000400654 <test>:                                                                              /* 预留栈