在GDB中分解C函数。气体组件说明的澄清
我在这里编写了一个C函数(它确实存在缓冲区溢出漏洞) 它在gdb中的组装转换为在GDB中分解C函数。气体组件说明的澄清,c,linux,assembly,gdb,gnu-assembler,C,Linux,Assembly,Gdb,Gnu Assembler,我在这里编写了一个C函数(它确实存在缓冲区溢出漏洞) 它在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 <f
|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
| 0x4005b4推送%rbp
|0x4005b5 mov%rsp,%rbp
|0x4005b8子$0x40,%rsp
|0x4005bc mov%rdi,-0x38(%rbp)
|0x4005c0 mov%fs:0x28,%rax
|0x4005c9 mov%rax,-0x8(%rbp)
|0x4005cd异或%eax,%eax
|0x4005cf movl$0x9,-0x24(%rbp)
|0x4005d6 mov-0x38(%rbp),%rdx
|0x4005da lea-0x20(%rbp),%rax
|0x4005de mov%rdx,%rsi
|0x4005e1 mov%rax,%rdi
|0x4005e4调用0x400490
|0x4005e9 mov-0x8(%rbp),%rax
|0x4005ed异或%fs:0x28,%rax
|0x4005f6 je 0x4005fd
|0x4005f8调用0x4004a0
|0x4005fd LEVEQ
|0x4005fe retq
rdi
包含传递给函数的原始字符数组的地址
1.在func+8
中,是否将此rdi值移动到-0x38(rbp)以将值保存在函数的局部变量str中,或者是否有任何其他含义
2.func+8
的指令有什么作用?在gdb或linux中是否还有其他方式可以查看fs段的内容
3.func+12
到func+25
的说明有什么作用
编辑:我在GCC4.6.3中用-O0编译了这篇文章,这只回答了上面问题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
$objdump-dS func.o
第节的分解。正文:
0000000000000000 :
#包括
void func(字符*str)
{
0:55推送%rbp
1:48 89 e5 mov%rsp,%rbp
4:48 83 ec 20分$0x20,%rsp
8:48 89 7d e8 mov%rdi,-0x18(%rbp)
字符缓冲区[12];
INTA=9;
c:c7 45 fc 09 00 movl$0x9,-0x4(%rbp)
strcpy(缓冲区,str);
13:48 8b 55 e8 mov-0x18(%rbp),%rdx
17:48 8d 45 f0 lea-0x10(%rbp),%rax
1b:4889D6MOV%rdx%rsi
1e:48 89 c7 mov%rax,%rdi
21:e8 00呼叫26
}
26:c9-Q
27:c3 retq
这至少可以告诉您编译器认为它在做什么。
func+8
将参数值存储在一个临时变量中,因为%rdi
将在func+45
上受到冲击。编译器可能会以不同的方式处理它,但我想这就是它在这种情况下所选择的
我不记得如何立即检查fs
段的内容,但我怀疑它正在读取一些已知的金丝雀值以放在堆栈上。我不太确定,但是func+12
到func+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
| 0x4005e9 mov-0x8(%rbp),%rax您关于fs段的问题的答案似乎是堆栈金丝雀。我发现一个博客似乎解释得很好,还有它的评论:
|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