一、做栈题的心得:
1、看栈的大小
2、判断栈溢出的字节数(够的话直接栈上操作再跳回main函数再次操作,不够的话,栈迁移到bss上)
命令:cyclic n cyclic -l 报错(4位)
3、如果开了canary,先泄露出canary(覆盖低字节或者格式化字符串泄露),记得函数调用完要回填canary
4、如果开了pie,先利用write或者puts函数(覆盖0截断)或者格式化字符串泄露基地址
5、NX开了的话,一般不管,没开的话直接填shellcode,可以手写也可以工具直接生成
6、一般的题目都是先栈溢出泄露出真实地址,再次回跳main最后填system去getshell
二、做格式化字符串题的心得:(一定是写指针!!!)
1、判断漏洞点格式化字符串
2、判断能写的字符数限制,看下能不能同时泄露出canary和真实地址和基地址(%n$p,n就是写入开始的地方,用int(,16)去接收)
3、写地址(要么用工具直接写,记得加pause,要么手写,”%128c”+”%12$hhn”)
4、如果got表能改,一般直接填got表到栈中,再改写got表
5、如果got不可改,则需要泄露出栈地址,然后通过计算栈的偏移,来得到ret的地址,将ret填到栈中,分2步填写,然后改写ret中的libc_start_main函数为onegadget,或者直接改写为rop链子
6、如果是bss上的格式化字符串漏洞,就先找出栈上的有3个栈地址的2个值,然后改写第三个值为ret地址,另外一个改写为ret+2,接着改写倒数第二个地址,就可以实现改写ret上的libc_start_main了,或者改第三个为got地址,接着改第二个为onegadget,相当于间接改got表。
7、堆的操作,如果可改写got表,改free真实地址为printf_plt,然后在堆上写格式化字符串,就可以实现这个漏洞了
三、做堆题的心得:
一、边分析边写函数,把malloc、free、edit、puts等写出来(看到漏洞了,在旁边标明出来)
二、分析堆块结构,写出结构体
1、UAF漏洞是指指针的内容没有清空:
free(0x600280)
如果加上
*(0x600280)=0
这样就没有UAF漏洞了
如果有UAF漏洞,一般这么用:
1、申请unsorted_bin大小的chunk再free,泄露出libc地址,适用于double free。
2、当堆块上有某个地址时,通过UAF申请同样大小的chunk,(注意申请和释放的顺序)写内容时覆盖那个地址为got表或者其他地址,再调用,即可实现执行。
也可以用来实现unlink的操作,2个unsortedbin的free,接着再申请大于这两个堆块的bin,就可以编辑unlink了
四、Double free,指针未清空,头部检查而已:
free(0x600280)
0x600280 = 0
表示bss指针清空,那么就表示没有double free
2、double free的题目有个固定的套路,构造fake_chunk,第四次申请时改malloc_hook(可能可以用onegadget和realloc实现)
double free还用于没有edit函数时,申请出一个只要size头满足条件的chunk块即可(house of spirit),可以是bss上的,也可以是栈上的
double free 还可以用于改写堆的末尾使其指向有0x7f的地址,这种用于构造IO_file的攻击泄露地址
或者double free由修改bss上的堆块的末尾造成!
这里还有个叫做双链攻击(没有0x7f大小的情况下,但是有真实地址),一个搞size头,另一个申请出来,改写topchunk到malloc_hook前面,前提是有真实地址
3、offbyone
这种题目一般观察输入中的for循环有没有在末尾多了一个字节的操作,或者判断中有小于等于,导致最后一个字节有溢出现象,溢出一个字节
利用的话,最常见的就要数overlap chunk了,比如有12345堆块,这种做法是通过改写3号块造成溢出一个字节,改写4号块的状态变为free状态,然后presize写好前面3个堆块的大小,再free掉1号块,再free掉4号块实现。接着就是切割unsortedbin了,可以一样大小的,这样就可以实现我们的double free,只要堆块构造合理即可(2,3可以是0x7f大小,1号必须是unsortedbin,4号也是unsortedbin,也就是一定要大于0x80),还可以是1234,改写1号堆块,将2号堆块的size改大,同时在3号块中伪造好nextsize,这样free掉2号堆块时,就可以实现得到unsorted bin大小的堆块,再次申请就是切割的问题了,也可以触发double free(申请到同一个堆块3),这种技巧叫做extend the chunk,当然还有种叫做shrink the chunk,效果相同(当无法控制我们的presize时)
4、offbynull
这种漏洞,一般都是overlap the chunk,申请固定大小的0xf8,得到0x101,利用offbynull实现overlap the chunk,相当于有UAF 和 double free(可以攻击global max fast)
offbynull或者offbyone还可以用来触发unlink(没有开pie的情况下,got表可改)。任意长度堆溢出也可以用来实现unlink的操作。
5、unlink:
1、fake_chunk的构造,一般是edit时堆溢出修改下一个chunk块的presize和size,ptr一定是合并后的大块的地址
接着就是写got表,改got表泄露地址,实现onegadget(一般是free_hook的地址),前提有堆溢出
2、申请2个unsorted_bin大小的chunk,再申请大于这两个块的chunk2,会得到原来的2个chunk,那么通过修改大块的内容,从而伪造fake_chunk,实现unlink,前提是有UAF漏洞(got可改,pie没开)
3、堆块大小固定,可以打印出堆块地址时,堆块错位的方法实现伪造unsorted_bin大小的堆块,unlink就可打印出libc的地址,然后一把操作。
还有一种,开了pie,但是可以泄露出堆地址的unlink,填合并的自己的地址,这样会free掉大块,再次申请得到同样堆块,可以实现double free和UAF
4、无符号数比较时,整数溢出0x80000000,造成堆溢出
house of force(倒着切割堆块,前提能输入负数)
house of orange(前提能改到topchunk的size,改小,再malloc一个大于topchunk的size的堆块)(用于没有free的情况下,或者没有unsorted bin的情况下)
house of storm(一个大于0x400的堆块在unsortedbin中,一个在largebin中),把unsorted bin的largebin插入到倒数第二个,实现攻击,一般会禁用fastbin
unsorted bin的attack,攻击bk指针(主要bk指针连着,就不会断),bk换成想要改写的地址-0x10,就可以改写为0x7f的main_arena,一般是攻击global_max_fast,这样就是fastbin的天下了
house of romain,硬核爆破
house of Lore smallbin的attack,伪造出一个fd和bk链,使得能够被申请出来
tcache,有double free不会报错,不检查size头,7个填满为止
条件竞争:多线程时,可以sleep一下
沙箱,先看下有没有,禁用了什么函数(可以调用mprotect函数,开辟出空间,再open,read,write去打印出flag)
free、malloc、edit函数看洞
四、打patch技巧
1、栈要么改read的size,要么改leave ret 为ret ret
2、格式化字符串,改printf为puts函数
3、UAF漏洞,加个0,offbynull或者one的话,直接删掉
4、溢出的话,改size即可
5、条件竞争,nop掉sleep
6、实在没招式了,删free函数