Buffer Overflow Not Setting Variable in Parent Function
I'm working on a security challenge involving a buffer overflow vulnerability, but I'm having trouble affecting a variable in the parent function. Here's a simplified version of the code:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <unistd.h>
typedef struct {
char name[64];
char time[64];
char reason[64];
int id;
} appointment_t;
typedef struct node_s {
appointment_t data;
struct node_s *prev;
struct node_s *next;
} node_t;
int main();
char MSG_HEADER[] = "YOUR APPOINTMENT IS IN OUR SYSTEM! HERE IT IS:";
node_t **DB_HEAD = NULL;
void backdoor() {
char *argv[] = {"/bin/sh", 0};
printf("Here's your appointment:\n");
execv(argv[0], argv);
}
void add_appointment(node_t *it, char *name, char *time, char *reason, int id) {
it->next = malloc(sizeof(node_t));
it->next->prev = it;
it = it->next;
strcpy(it->data.name, name);
strcpy(it->data.time, time);
strcpy(it->data.reason, reason);
it->data.id = id;
}
void init() {
DB_HEAD = malloc(sizeof(node_t *));
*DB_HEAD = malloc(sizeof(node_t));
add_appointment(*DB_HEAD, "Koyossu", "16:00 TUE", "stubbed toe", 0x1);
add_appointment((*DB_HEAD)->next, "Lev", "13:00 THU", "PTSD", 0x12);
add_appointment((*DB_HEAD)->next->next, "Honesty", "10:00 FRI", "SARS-COV2.5", 0x420);
add_appointment((*DB_HEAD)->next->next->next, "Pinebel", "13:37 MON", "PWN overdose", 0x1337);
}
void interact() {
node_t *it = *DB_HEAD;
char *msg = MSG_HEADER;
unsigned int actions = 2;
char cmd[16];
while (actions > 0) {
printf("> ");
read(0, cmd, 256);
if (!strncmp("NEXT", cmd, 16)) {
it = it->next;
} else if (!strncmp("PREV", cmd, 16)) {
it = it->prev;
} else if (!strncmp("PRINT", cmd, 16)) {
puts(msg);
printf("NAME: %s\nTIME: %s\n REASON: %s\n", it->data.name, it->data.time, it->data.reason);
} else {
printf("Unknown command: %s\n", cmd);
return;
}
actions--;
}
}
int main() {
int is_admin = 0;
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
init();
puts("AVAILABLE COMMANDS:");
puts("NEXT");
puts("PREV");
puts("PRINT");
interact();
if (is_admin == 0x1337) {
backdoor();
}
return 0;
}
The Problem
There's a clear buffer overflow in the interact()
function where it reads up to 256 bytes into a 16-byte buffer. I'm trying to use this to set is_admin
to 0x1337
to trigger the backdoor()
function.
I can see the buffer overflow working in GDB - I've corrupted the stack successfully. Here's my GDB output at the return of interact()
:
rbp = 0x6161616e6161616d
rsp = 0x7fffffffde28
What I've Tried
- I tried overflowing the buffer with a cyclic pattern and found I can control the saved RBP and return address
- Used 40 bytes of padding followed by the value 0x1337
- Tried different offsets thinking it might be a stack alignment issue
Here's my current exploit attempt:
from pwn import *
p = process("./program")
payload = b"A" * 40 + p64(0x1337)
p.sendlineafter(b"> ", payload)
p.interactive()
The Question
How can I use this buffer overflow to modify the is_admin
variable in the parent function? I understand I can't directly overwrite it due to stack frame separation, but there must be some way to influence it when interact()
returns to main()
.
Note: The binary has Intel CET enabled, so I can't directly overwrite the return address.
Any insights on how register state preservation between function calls could help here would be appreciated.