一、题目:pwn1
先checksec下:
保护全开,ida分析一波:
1 | void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) |
常规的菜单题,然后分析一波漏洞点:
1、malloc:
1 | unsigned __int64 malloc_0() |
这个漏洞点的利用,第一次见,所以比较生疏,后期多多积累,下面继续分析:
2、show
1 | ssize_t show() |
这个是puts函数打印堆块内容
3、free
1 | __int64 free_0() |
free这里很明显的UAF漏洞,就是指针清空,内存不清空。
那么结合show函数是可以泄露出libc地址和堆地址的
最后exit是退出,那么一波操作先得到libc地址和堆地址:
这里学到一个新姿势,实现unsorted_bin的不合并链接:
malloc(0x100)—>malloc(0x20)—>malloc(0x100)—>malloc(0x70)—>top_chunk
这样chunk1和chunk3之间有个隔开的chunk,就不会合并,chunk4是用来隔开top_chunk的合并。
1 | malloc(0,0xf0-8,'A'*(0xf0-8)) |
记得当我们需要使用到堆块的presize时,那么size需要为基数,比如0xf8或者0x78这样,而不是0x100或者0x70
因为只有3次申请的机会,所以要重复利用,3个当4个用,free再malloc~
这题在heap下很难做,同时漏洞是在size那里,当size为可读可写的地址时,可以写入0,那么想到写到堆块上,vmmap分配内存,那么第一步先使得分配失败,然后跳出main_arena,使用vmmap堆基地址分配内存,就要先得到vmmap堆基地址才行,怎么得到呢?其实vmmap下的攻击手段和heap下是差不多的,工具利用时看内存和arenainfo(命令)来看堆块布局,泄露出vmmap堆基地址的方法和前面差不多,堆块格挡下,然后迁到unsorted_bin中,然后去打印出来,得到地址(vmmap堆的基地址,双链表下的):举个栗子
0x00007f7158000078—->0x00007f71580000b3(top_chunk)
那么就可以想到其他堆块是链接在0x00007f7158000078上的
1 | malloc(0,heap+0x1,'A') |
那么我们得到了vmmap下分配的堆块的基地址,那么在malloc时就可以往任意地址写0
这里可以看到,我们通过申请0x70-8大小的堆块,改写0x100那个堆块的pre_size大小为0x160(0xf0+0x70),那我们需要把160旁边的0x101改写为0x100,表示前一个堆块为free状态,才能实现unlink,那么我们通过offbynull,将这个位置写成0:
1 | malloc(1,0x70-8,'E'*(0x70-8-8) + p64(0x160)) |
这样0x160的free堆块就生成了,那么我们再申请0x100大小堆块再free就可以触发unlink了:
成功unlink了,接着就可以通过申请0x160大小堆块去改写0x70堆块的指向为fake_chunk
1 | py = '' |
先写入fake_chunk,然后申请2次得到fake_chunk,改写malloc_hook为onegadget,得到shell~,下面是完整的exp:
1 | #coding=utf8 |