Modify return address on stack

我的梦境 提交于 2019-12-05 05:21:19

You're not going to be able to do this in vanilla C, you don't have control of how the compiler lays out the stack frame.

In x86-64, the return address should be at %rbp + 8. You could use some inline assembly to get that (gcc syntax):

uint64_t returnaddr;
asm("mov 8(%%rbp),%0" : "=r"(returnaddr) : : );

Similarly for setting it.

Even that is a bit sketchy, as you don't know whether the compiler is going to set up %rbp or not. YMMV.

Your basepointer is most likely just a pointer, so it has the size sizeof(int*). But there is also another value in between your variable ret and the base pointer. I would assume its value of a register (eax?). This would lead to something like the following, if you want an endless loop:

void foo(void)
{
    char ret;
    char *ptr;

    ptr = (char*)(&ret) + (sizeof(ret)  + 2*sizeof(int*)) ;
    *(int*)ptr -= 0x0c;
}

The return target which is modified assuming it has the size of a pointer (could differ for other instruction sets). By decrementing it, the return target is set to a point before the calling point of foo.

It seems you're using a 64-bit architecture, since RBP and RSP registers are 64-bit long. If you declare ptr as char* you will have to increment it 8 times to move through the stack. Instead you could declare it as uint64_t *. This data type is normally available in <stdint.h>.

However the stack frame definition varies depending on the target architecture and even on the compiler behaviour and optimizations. It's fine if you are experimenting, though.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!