Hacking around with C and ASM is fun! Here are two blobs of C code useful for future reference:
Use function return to actually call another function via the stored IP:
#include <stdio.h>
register void ** base_pointer __asm("%rbp");
register void ** stack_pointer __asm("%rsp");
int mycode(void * old_ip) {
printf("Mycode\n");
*(base_pointer + 1) = old_ip;
return 10;
}
int fun() {
void * old_ip = *(base_pointer + 1);
*(base_pointer + 1) = mycode;
stack_pointer = base_pointer;
__asm("movq %0, %%rdi"::"r"(old_ip));
return 4;
}
int main() {
printf("%i\n", fun());
return 0;
}
Dynamically generate code and execute it:
#include <sys/mman.h>
#include <stdio.h>
int seven() {
char * space = mmap(NULL,
7,
PROT_WRITE | PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
// mov 7, %rax; leave; ret
space[0] = 0xB8;
space[1] = 0x07;
space[2] = 0x00;
space[3] = 0x00;
space[4] = 0x00;
space[5] = 0xC9;
space[6] = 0xC3;
mprotect(space, 7, PROT_EXEC | PROT_READ);
goto *space;
}
int main() {
printf("%i\n", seven());
return 0;
}
And the buffer overflow version:
#include <stdio.h>
register void ** base_pointer __asm("%rbp");
register void ** stack_pointer __asm("%rsp");
int mycode(void * old_ip) {
printf("Mycode\n");
*(base_pointer + 1) = old_ip;
return 10;
}
int fun() {
void * old_ip = *(base_pointer + 1);
void * buffer[0];
buffer[1] = mycode;
stack_pointer = base_pointer;
__asm("movq %0, %%rdi"::"r"(old_ip));
return 4;
}
int main() {
printf("%i\n", fun());
return 0;
}
I think you need to escape the less than signs with <:
Thanks. Fixed
Also, obviously the binary code that I inlined is X86… I added a comment saying what it does.