Files
ctf/cscg25/pwn/intro3/intro-rop.c
2025-03-11 20:12:21 +01:00

254 lines
8.0 KiB
C

#define _GNU_SOURCE
#include <dlfcn.h>
#include <fcntl.h>
#include <link.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
// intro-rop: gcc intro-rop.c -o intro-rop
// --------------------------------------------------- SETUP
void ignore_me_init_buffering() {
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
}
typedef struct ropgadget {
unsigned int length;
unsigned char gadget[32];
} ropgadget_t;
typedef unsigned long long u64;
// --------------------------------------------------- ROP GADGETS
void gadget_0();
void gadget_1();
void gadget_2();
void gadget_3();
void gadget_4();
void gadget_5();
void gadget_6();
void gadget_7();
void gadget_8();
void gadget_9();
void gadget_10();
void gadget_11();
void gadget_12();
void gadget_13();
void gadget_14();
void gadget_15();
__asm(".intel_syntax noprefix \n"
".global gadget_0 \n"
".global gadget_1 \n"
".global gadget_2 \n"
".global gadget_3 \n"
".global gadget_4 \n"
".global gadget_5 \n"
".global gadget_6 \n"
".global gadget_7 \n"
".global gadget_8 \n"
".global gadget_9 \n"
".global gadget_10 \n"
".global gadget_11 \n"
".global gadget_12 \n"
".global gadget_13 \n"
".global gadget_14 \n"
".global gadget_15 \n"
"gadget_0: \n"
" pop rax \n"
" ret \n"
"gadget_1: \n"
" add rbx, r9 \n"
" ret \n"
"gadget_2: \n"
" mov rcx, qword ptr [rbx] \n"
" ret \n"
"gadget_3: \n"
" mov rax, r8 \n"
" mov rbx, r9 \n"
" mov rcx, r10 \n"
" ret \n"
"gadget_4: \n"
" xor rcx, rdi \n"
" xor rbx, rdi \n"
" ret \n"
"gadget_5: \n"
" push rax \n"
" ret \n"
"gadget_6: \n"
" xor rax, rax \n"
" xor rsi, rsi \n"
" ret \n"
"gadget_7: \n"
" sub rax, 0x8 \n"
" idiv rdi \n"
" ret \n"
"gadget_8: \n"
" add rdi, r8 \n"
" ret \n"
"gadget_9: \n"
" nop \n"
" ret \n"
"gadget_10: \n"
" imul rbx, rax \n"
" ret \n"
"gadget_11: \n"
" xor r9, r8 \n"
" xor r8, r9 \n"
" xor r9, r8 \n"
" ret \n"
"gadget_12: \n"
" mov rcx, rsi \n"
" add rcx, r10 \n"
" ret \n"
"gadget_13: \n"
" xor rdi, rcx \n"
" xor rsi, rcx \n"
" ret \n"
"gadget_14: \n"
" pop rbx \n"
" push rdi \n"
" push rbx \n"
" ret \n"
"gadget_15: \n"
" pop rbp \n"
" pop rsi \n"
" ret \n"
".att_syntax prefix \n");
void *gadgets[] = {
gadget_0, gadget_1, gadget_2, gadget_3, gadget_4, gadget_5,
gadget_6, gadget_7, gadget_8, gadget_9, gadget_10, gadget_11,
gadget_12, gadget_13, gadget_14, gadget_15,
};
// --------------------------------------------------- HELPER FUNCTIONS
// get the address of a libc function
u64 get_libc_addr(const char *func) {
void *handle = dlopen("libc.so.6", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "Error opening libc: %s\n", dlerror());
return 0;
}
u64 func_addr = (u64)dlsym(handle, func);
if (!func_addr) {
fprintf(stderr, "Error getting symbol address: %s\n", dlerror());
dlclose(handle);
return 0;
}
dlclose(handle);
return func_addr;
}
// libc usually contains a "/bin/sh" string, this function finds it
u64 get_binsh_str() {
void *handle = dlopen("libc.so.6", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "Error opening libc: %s\n", dlerror());
return 0;
}
struct link_map *map;
if (dlinfo(handle, RTLD_DI_LINKMAP, &map) != 0) {
fprintf(stderr, "Error getting link map: %s\n", dlerror());
dlclose(handle);
return 0;
}
dlclose(handle);
return (u64)memmem((void *)map->l_addr, 0x10000000, "/bin/sh\x00", 8);
}
// get the address of the puts GOT entry
u64 get_puts_got() {
void *dyn = _DYNAMIC;
Dl_info info;
if (dladdr(dyn, &info) == 0) {
fprintf(stderr, "Error getting dynamic address: %s\n", dlerror());
}
u64 needle = get_libc_addr("puts");
return (u64)memmem((void *)info.dli_fbase, 0x10000, (void *)&needle,
sizeof(void *));
}
// --------------------------------------------------- Challenge
void print_stuff() {
u64 *new_stack = (u64 *)malloc(1024 * 1024);
puts("Enter the index of each ROP gadget");
puts("Finish your ROP chain with the index -1");
signed int lastIndex = 0;
int counter = 0;
int maxIndex = sizeof(gadgets) / sizeof(gadgets[0]);
u64 diff_puts_Binsh = get_binsh_str() - get_libc_addr("puts");
u64 diff_puts_System = get_libc_addr("system") - get_libc_addr("puts");
u64 puts_got = get_puts_got();
while (lastIndex != -1) {
printf("\n> Enter gadget index: ");
scanf("%d", &lastIndex);
if (lastIndex >= maxIndex || (lastIndex < 0 && lastIndex != -1)) {
printf("Invalid index, bye!\n");
exit(-1);
}
new_stack[counter++] = (u64)gadgets[lastIndex];
}
printf("Lets goooo ! :)\n");
u64 rbp = 0; // Get stack address of return pointer to overwrite it
__asm("mov %%rbp, %0\n" : "=r"(rbp));
rbp += 8; // Adjust for return address
memcpy((void *)rbp, (void *)new_stack, counter * 8);
__asm(".intel_syntax noprefix\n"
"mov rsp, %0\n"
"mov r8, %1\n"
"mov r9, %2\n"
"mov r10, %3\n"
"leave\n"
"ret\n"
".att_syntax prefix\n"
:
: "r"(new_stack), "r"(diff_puts_System), "r"(puts_got),
"r"(diff_puts_Binsh));
}
// --------------------------------------------------- MAIN
void main(int argc, char *argv[]) {
ignore_me_init_buffering();
print_stuff();
}