How to modify return address on Stack in C or Assembly

2.3k views Asked by At

As you know, when a subroutine calls, current PC (program counter) value stores in stack. I want to modify it inside the subroutine, like below. I want do this on Intel Core-i7 3632QM using gcc compiler.

void main()
{
     foo();
}
void foo()
{
     pop return address from stack;
     modify return address;
     push it to stack;
}
1

There are 1 answers

0
Jester On BEST ANSWER

This is almost certainly an XY problem, you didn't say what you really want to do. Anyway, here is sample code that modifies the return address:

#include <stdio.h>
#include <stdlib.h>

void bar()
{
    puts("entered the bar ;)");
    exit(0);
}

void** search(void** addr, void* value) __attribute__((noinline));
void** search(void** addr, void* value)
{
    while(*addr != value) addr++;
    return addr;
}

void foo() __attribute__((noinline));
void foo()
{
    void** p = search((void**)&p, __builtin_return_address(0));
    *p = bar;
}

int main()
{
    foo();
    return 0;
}

See it in action.

Obviously foo must not be inlined for it to even have a return address, and I had to split out search into its own function for some obscure optimization issue whereby the compiler would otherwise remove the write to the return address. Searching for the return address like this makes it more tolerant of stack layout differences than if you just hardcoded some specific offset from a local variable.