From https://www.allegro.cc/forums/thread/617807
If I don't call abort on line 44, my program crashes with SIGILL.
Why doesn't it exit cleanly? I put the value of the frame pointer back where it was but the stack is still corrupt. I suspect there is an extra frame on the stack from calling into i_never_called_this_code
that I didn't account for.
This is a personal exercise so I can learn about the stack.
Note: Run the code at your own risk.
Bugsquasher
EDITAs per the comment, here is the code.
#warning RUN @ YOUR OWN RISK NEWBIE #include <stdio.h> #include <stdlib.h> typedef void (*VOIDFUNC)(); typedef VOIDFUNC* VOIDFUNCPTR; static VOIDFUNC old_data = (VOIDFUNC)0; static VOIDFUNCPTR return_address = (VOIDFUNCPTR)0; static VOIDFUNCPTR stack_address = (VOIDFUNCPTR)0; void put_it_back() { if (return_address) { /// Put back the previous value fprintf(stderr , "Returning data {%p} to %p\n" , old_data , return_address); *return_address = old_data; } } void i_never_called_this_code() { fprintf(stderr , "\n\nArbitrary code execution... oops!\n\n"); /// Attempt to repair the damage, so it goes back to the 'CORRECT' frame put_it_back(); stack_address = return_address; fprintf(stderr , "***Stack Address is %p ***\n" , stack_address); /// We better abort before shit gets crazy // abort(); /// haha just kidding /// No really // abort(); /// you really want to know what happens, don't you? /// Ahem abort(); } void break_the_stack(char* stackptr) { /// Store the old data (ie, return address we're SUPPOSED to be going to old_data = *(VOIDFUNCPTR)(stackptr); return_address = (VOIDFUNCPTR)stackptr; fprintf(stderr , "Reading data {%p} at %p\n" , old_data , return_address); /// Smash the stackptr, /// When we find the return address stored on the stack, we replace it with our function address /// that's where it will go next /// Basicallly, we're calling our code without calling it /// Once that's done, 411 UR B4535 B310NG 2 US *(VOIDFUNCPTR)(stackptr) = i_never_called_this_code; } int main(int argc , char** argv) { char* stack = (char*)&stack; (void)argc; (void)argv; while (1) { stack -= sizeof(unsigned int); fprintf(stdout , "0x%lx\n" , (unsigned long int)stack); break_the_stack(stack); put_it_back(); if (stack_address) {/// == (VOIDFUNCPTR)stack) break; } else { /// Cleanliness is next to godliness /// *return_address = old_data; } } fprintf(stderr , "What just happened?\n"); return 0; }