de1ctf_2019_weapon writeup
buu刷题记录—de1ctf_2019_weapon
静态分析
checksec一波,保护全开,ida分析,发现时经典的堆菜单题目。有add,delete和edit操作,没有show函数,并且保护全开无法劫持got表。那么这题大概率是要用IO来泄露libc了。
add函数把堆块申请范围限制在了0x60以内,也就是说我们只能申请fastbin大小的堆块。edit函数就是中规中矩的按照之前的size修改堆块的内容。delete函数在堆块被free之后没有把指针置空存在UAF的漏洞。那么我们的思路大概就是先通过uaf进行堆块重叠然后修改size,free之后得到一个unsorted bin,然后再修改回fastbin将它申请到stdout附近通过IO泄露libc地址,最后再来一次fastbin attack劫持malloc hook放上onegadget 去getshell,这题需要用realloc 调整栈来适应onegadget,我们后面再说。
泄露libc的地址
因为地址都是未知的,所以一开始要通过释放两个相同大小的fastbin来让其中一个fastbin中留下另一个fastbin的地址,再通过修改最后一字节让fastbin的fd来让第二个chunk申请到可以造成堆重叠的地方便于我们修改size。
1 | add(0x58,0,b'a'*0x48+p64(0x61))#在合适的地方伪造chunk |
可以看到第一个chunk的fd已经有了第四个chunk的地址,并且在第一个堆块中存在一个伪造的0x61作为fake chunk的size,所以接下来我们只要edit 0 \x50就能够产生fastbin attack了。
1 | edit(0,p8(0x50)) |
这一波操作就能成功泄露libc了,但是由于内存页是后三位对齐,我们填充是以字节为单位的,所以这里需要爆破一半个字节。
劫持malloc_hook
这里没什么好说的,就是通过uaf的方法把堆块申请到malloc_hook-0x23的地方,写mallochook为reallochook,再把realloc hook写上对应的one gadget,这里需要注意的是realloc不一定直接就行了,需要适当跳过一些push或这pop之类的指令来调整栈中的0到合适的位置,这里我用了第2个onegadget,用realloc + 4的地方来调整栈
1 | #one=[0x45226,0x4527a,0xf03a4,0xf1247] |
exp
最后附上爆破的脚本
1 | from pwn import * |
结果