在GDB中拆解C函数 澄清GAS大会指示

我有写在这里的C函数(它有一个缓冲区溢出漏洞)

void func(char *str) { char buffer[12]; int a=9; strcpy(buffer,str); } 

它在gdb中的汇编转换为

 |0x4005b4 <func> push %rbp |0x4005b5 <func+1> mov %rsp,%rbp |0x4005b8 <func+4> sub $0x40,%rsp |0x4005bc <func+8> mov %rdi,-0x38(%rbp) |0x4005c0 <func+12> mov %fs:0x28,%rax |0x4005c9 <func+21> mov %rax,-0x8(%rbp) |0x4005cd <func+25> xor %eax,%eax |0x4005cf <func+27> movl $0x9,-0x24(%rbp) |0x4005d6 <func+34> mov -0x38(%rbp),%rdx |0x4005da <func+38> lea -0x20(%rbp),%rax |0x4005de <func+42> mov %rdx,%rsi |0x4005e1 <func+45> mov %rax,%rdi |0x4005e4 <func+48> callq 0x400490 <strcpy@plt> |0x4005e9 <func+53> mov -0x8(%rbp),%rax |0x4005ed <func+57> xor %fs:0x28,%rax |0x4005f6 <func+66> je 0x4005fd <func+73> |0x4005f8 <func+68> callq 0x4004a0 <__stack_chk_fail@plt> |0x4005fd <func+73> leaveq |0x4005fe <func+74> retq 

rdi包含传递给函数的原始字符数组的地址。

1.在func+8 ,是否将此rdi值移至-0x38(rbp)以将值保存在函数的局部variablesstr中还是具有其他含义?

2. func+8的指令是做什么的? 无论如何在gdb或在Linux中查看fs segment的内容?

3. func+25的指令func+12做了什么?

编辑:我用-O0编译了gcc 4.6.3

关于你的问题的答案似乎是堆栈金丝雀。 我发现了一个似乎很好的解释它的博客,以及它的评论:

http://xorl.wordpress.com/2010/10/14/linux-glibc-stack-canary-values/

func+8将参数值存储在一个临时变量中,因为%rdi将在func+45处被破坏。 编译器可以用不同的方式处理它,但我想这就是它为这种情况所选择的。

我不记得如何检查fs段的内容,但我怀疑它正在读一些已知的金丝雀价值,以堆积起来。 我不是很确定,但func+12func+25看起来像是设置了一些堆栈保护,因为稍后会检查该值,如果不相同则调用错误处理程序:

 |0x4005e9 <func+53> mov -0x8(%rbp),%rax <-- loads the value on the stack |0x4005ed <func+57> xor %fs:0x28,%rax <-- compare with original |0x4005f6 <func+66> je 0x4005fd <func+73> <-- if they are different |0x4005f8 <func+68> callq 0x4004a0 <__stack_chk_fail@plt> <-- call this 

这只是回答上面问题3的一小部分,但是xor %eax %eax清除了eax。

我没有用x86做太多的工作,所以我不能确切地告诉你在那里做什么序言,但objdump通常比gdb提供更好的反汇编:

  $ objdump -dS func.o Disassembly of section .text: 0000000000000000 <func>: #include <string.h> void func(char *str) { 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 83 ec 20 sub $0x20,%rsp 8: 48 89 7d e8 mov %rdi,-0x18(%rbp) char buffer[12]; int a=9; c: c7 45 fc 09 00 00 00 movl $0x9,-0x4(%rbp) strcpy(buffer, str); 13: 48 8b 55 e8 mov -0x18(%rbp),%rdx 17: 48 8d 45 f0 lea -0x10(%rbp),%rax 1b: 48 89 d6 mov %rdx,%rsi 1e: 48 89 c7 mov %rax,%rdi 21: e8 00 00 00 00 callq 26 <func+0x26> } 26: c9 leaveq 27: c3 retq 

那至少应该告诉你编译器认为它在做什么。