离开功能时重写转发地址

时间:2014-11-30 13:15:32

标签: c buffer-overflow

我正在尝试从函数foo()重写ret地址,以便在离开函数foo()后跳过第一条指令。我正在关注Smash堆栈的乐趣或利润以及Jon Erickson的Hacking。这是一个简单的代码,我想跳过“b = 2;”指令,所以在b中应该存储值为1。

在gcc中编译,设置:-fno-stack-protector -z execstack -g
我也关掉了ASLR。

#include <stdio.h>
int foo() {
    int c = 0;
    int *ptr;
    ptr = (int*) 0x00007fffffffdf38;
    // Second instruction after leaving from foo(). I also tried to skip all instructions before call printf function.
    *ptr = 0x0000000000400577; 
    return 0;
}

int main()
{
    int b = 1;
    foo();
    b = 2;
    printf("b = %d\n", b);      
    return 0;
}

该程序的输出是:“b = 2”。

我如何假设存储的位置RET指令:

(gdb) disass main
...
0x000000000040056b <+20>:   call   0x40052d <foo>
0x0000000000400570 <+25>:   mov    DWORD PTR [rbp-0x4],0x2
0x0000000000400577 <+32>:   mov    eax,DWORD PTR [rbp-0x4]
0x000000000040057a <+35>:   mov    esi,eax
...
(gdb) break 4       // set breakpoint 1 in function foo before int *ptr;
(gdb) break 7       // set breakpoint 2 in function foo after rewriting RET for checking
(gdb) run
(gdb) x/8x &c       // "x/8x $esp" doesn't work, it says: "Cannot access memory at address 0xffffffffffffdf30", so I'm looking into memory from &c
0x7fffffffdf2c: 0x00000000  0xffffdf50  0x00007fff  0x00400570
0x7fffffffdf3c: 0x00000000  0xffffe030  0x00007fff  0x00000000
// simple math tell me, it should be:
(gdb) x/8xb 0x7fffffffdf38
0x7fffffffdf38: 0x70    0x05    0x40    0x00    0x00    0x00    0x00    0x00

这是我找到RET地址的方式,它位于0x7fffffffdf38。到这个地方我正在下一条指令的地址 - 0x0000000000400577。 但是,即使RET成功重写,计算机仍然没有跳过指令b = 2。 如果确实替换了RET地址,我检查了它确认:

(gdb) c
(gdb) x/8xb 0x7fffffffdf38
0x7fffffffdf38: 0x77    0x05    0x40    0x00    0x00    0x00    0x00    0x00

所以RET地址真的被重写了,但是当程序从函数foo()离开时,它会跳转到原始地址0x0000000000400570,我想跳过...

它应该很简单,找到存储ret地址的位置然后放到这个地方其他地址。我究竟做错了什么? 谢谢你的每一个答案。

为了指定任务我正在添加dissasembled函数:

Dump of assembler code for function foo:
0x000000000040052d <+0>:    push   rbp
0x000000000040052e <+1>:    mov    rbp,rsp
0x0000000000400531 <+4>:    mov    DWORD PTR [rbp-0x4],0x0
0x0000000000400538 <+11>:   movabs rax,0x7fffffffdf38
0x0000000000400542 <+21>:   mov    QWORD PTR [rbp-0x10],rax
0x0000000000400546 <+25>:   mov    rax,QWORD PTR [rbp-0x10]
0x000000000040054a <+29>:   mov    DWORD PTR [rax],0x400577
0x0000000000400550 <+35>:   mov    eax,0x0
0x0000000000400555 <+40>:   pop    rbp
0x0000000000400556 <+41>:   ret    
End of assembler dump.
(gdb) disass main
Dump of assembler code for function main:
0x0000000000400557 <+0>:    push   rbp
0x0000000000400558 <+1>:    mov    rbp,rsp
0x000000000040055b <+4>:    sub    rsp,0x10
0x000000000040055f <+8>:    mov    DWORD PTR [rbp-0x4],0x1
0x0000000000400566 <+15>:   mov    eax,0x0
0x000000000040056b <+20>:   call   0x40052d <foo>
0x0000000000400570 <+25>:   mov    DWORD PTR [rbp-0x4],0x2
0x0000000000400577 <+32>:   mov    eax,DWORD PTR [rbp-0x4]
0x000000000040057a <+35>:   mov    esi,eax
0x000000000040057c <+37>:   mov    edi,0x400624
0x0000000000400581 <+42>:   mov    eax,0x0
0x0000000000400586 <+47>:   call   0x400410 <printf@plt>
0x000000000040058b <+52>:   mov    eax,0x0
0x0000000000400590 <+57>:   leave  
0x0000000000400591 <+58>:   ret    

1 个答案:

答案 0 :(得分:-3)

当我在gdb调试器中运行它时,它可以工作。所以代码写得很好,问题解决了。问题出在其他地方......