@makdbb wrote:
最近在看ios下的arm汇编代码的时候看到有个stack_chkguard 和stack_chk_fail,记录下,以下代码均来自linux64下gcc编译器编译的二进制文件,代码已经备注的很详细了。
gcc中的编译器选项可以设置是否开启栈保护:-fstack-protector -fstack-protector -fno-stack-protector gcc 4版本中默认已经启用的stack-protector
c源代码如下:
#include <stdio.h> int main(int argc, char* argv[]){ int i; char a[64]; i = 0; a[0] = 'a'; return 0; } 1_nosp 为强制关掉stack_protector的反汇编代码。 (gdb) file 1_nosp Reading symbols from 1_nosp...(no debugging symbols found)...done. (gdb) disas main Dump of assembler code for function main: 0x00000000004004d6 <+0>: push %rbp // 保存栈基址 0x00000000004004d7 <+1>: mov %rsp,%rbp // 设置新的栈指针 0x00000000004004da <+4>: mov %edi,-0x54(%rbp) // argc 0x00000000004004dd <+7>: mov %rsi,-0x60(%rbp) // argv 0x00000000004004e1 <+11>: movl $0x0,-0x4(%rbp) // 设置i的值 0x00000000004004e8 <+18>: movb $0x61,-0x50(%rbp) // 设置a[0] = 'a' 0x00000000004004ec <+22>: mov $0x0,%eax // 设置返回值 0x00000000004004f1 <+27>: pop %rbp // 弹出栈基址 0x00000000004004f2 <+28>: retq End of assembler dump. 1_sp 为默认开启stack_protector的反汇编代码。 (gdb) file 1_sp Reading symbols from 1_sp...(no debugging symbols found)...done. (gdb) disas main Dump of assembler code for function main: 0x0000000000400546 <+0>: push %rbp // 保存栈基址 0x0000000000400547 <+1>: mov %rsp,%rbp // 设置新的栈指针 0x000000000040054a <+4>: sub $0x70,%rsp // 开辟新的栈空间 0x000000000040054e <+8>: mov %edi,-0x64(%rbp) // argc 0x0000000000400551 <+11>: mov %rsi,-0x70(%rbp) // argv 0x0000000000400555 <+15>: mov %fs:0x28,%rax // canary 值 0x000000000040055e <+24>: mov %rax,-0x8(%rbp) // 这里是canary 0x0000000000400562 <+28>: xor %eax,%eax // 清空eax 0x0000000000400564 <+30>: movl $0x0,-0x54(%rbp) // 设置i的值 0x000000000040056b <+37>: movb $0x61,-0x50(%rbp) // 设置a[0] = 'a' 0x000000000040056f <+41>: mov $0x0,%eax // 设置返回值 0x0000000000400574 <+46>: mov -0x8(%rbp),%rdx // 0x0000000000400578 <+50>: xor %fs:0x28,%rdx // 检测canary值 0x0000000000400581 <+59>: je 0x400588 <main+66> // 如果为0则直接返回 否则调到保护代码区。 0x0000000000400583 <+61>: callq 0x400420 <__stack_chk_fail@plt> 0x0000000000400588 <+66>: leaveq 0x0000000000400589 <+67>: retq End of assembler dump. (gdb) disas __stack_chk_fail Dump of assembler code for function __stack_chk_fail@plt: 0x0000000000400420 <+0>: jmpq *0x200bf2(%rip) # 0x601018 0x0000000000400426 <+6>: pushq $0x0 0x000000000040042b <+11>: jmpq 0x400410 End of assembler dump.
等于保存了两份一份在%fs:0x28处,另外一份在-0x8(%rbp)处,最终检测canary值是否被修改
当参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9。当参数为7个以上时, 前 6 个与前面一样, 但后面的依次从 “右向左” 放入栈中,即和32位汇编一样。xor %fs:0x28,%rdx,如果没有被修改直接返回,如果被修改了就跳到_stack_chk_fail中去。
linux64位汇编参数传递方式:参数个数大于 7 个的时候 H(a, b, c, d, e, f, g, h); a->%rdi, b->%rsi, c->%rdx, d->%rcx, e->%r8, f->%r9 h->8(%esp) g->(%esp) call H
最后的最后,欢迎大家与我多多交流,vx号:nicholas_mcc
Posts: 4
Participants: 2