我正在尝试从函数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
答案 0 :(得分:-3)
当我在gdb调试器中运行它时,它可以工作。所以代码写得很好,问题解决了。问题出在其他地方......