有关于二进制漏洞和利用的碎碎念
划水作品
偷闲记录一下二进制方面的各种概念,各种原理,各种利用等等,方便过后查阅,也为之后的学习路线列一个大的框架,主要内容还是针对CTF中的pwn,实际漏洞也有这些方面,不过就需要花更多的精力慢慢硬磕了。
栈溢出
由于种种原因,这是本人学习时间最长的一种漏洞,学的时候还有乌云,学完。。。
栈溢出原理很简单,就是栈上的数据没有合理的被控制,从而使得输入数据超出它本应该在的范围,越界少的可能只是局部变量覆盖,多的就是劫持控制流,不同情况造成不同的后果。
栈溢出是二进制漏洞的起源,也是无数大黑客起家的地方,也是入门二进制的必经之路。不过鉴于关于栈的缓解措施越来越多,各种安全函数,各种编译选项,使得程序员在栈上的粗心大意几乎不会造成漏洞,所以现实中的栈溢出漏洞越来越少,CTF中关于这类题目也不是很多了。
栈溢出的花哨之处就在于劫持控制流之后让程序跳转至哪里,从最经典的jmp esp,到后来的ROP,以及更高级的ROP,还有各种花式技巧,都表明了栈溢出的利用确实越来越难,保护措施越来越完善,不过依然有很多值得学习的地方。
还没系统的总结过栈溢出的题目方法之类的,等遇到好的题目再统一整理。
简单说一下基本的利用:
直接跳至栈中,执行shellcode,NX出现之后,几乎绝迹了
ret2libc、ROP,通过gadget布置栈空间,导致libc库函数顺利执行,从而达到目的
ropchain,通过gadgets构造出一串完整的汇编指令,通常是int 80开启一个shell
stack privot,劫持栈指针指向攻击者所能控制的内存处,然后再在相应的位置进行ROP
frame faking,伪造栈帧
__libc_scu_init,64位下函数参数会放在寄存器中,就需要一些好的gadgets
等等
格式化字符串漏洞
个人觉得跟栈溢出很像,但是由于格式化的参数配置,导致了这种漏洞的可利用性很强,而且利用范围很广。我还没有系统的学习过这类漏洞,前几天看了看感觉过去像是错过了一个宝藏,最近会整理一下这类漏洞,也会分析一些题目来对这类漏洞的利用做一下巩固。
简单说一下原理和利用:
由于在调用printf,scanf等具有格式化结构的函数时,没有格式化的内容做过滤或者做限制,如:
printf(format)
就可以获取到栈中的内容,如果printf中的format直接使用的用户输入,则就可以造化意想不到的后果。
程序崩溃:当函数通过format访问到无效地址时,就会造成程序崩溃。
泄露内存:直接通过format简单构造,就可以泄露出栈上的内存,或者某个参数的值,另外,由于带有格式化函数的第一个参数往往是format地址,如果我们通过格式化覆盖了这个地址,就可以造成任意地址泄漏。
覆盖内存:%n不输出字符,但是把已经成功输出的字符个数写入对应的整型指针参数所指的变量。可以通过一些技巧进行栈内存覆盖和任意地址覆盖。
这里就是简单的记录一下,没有详细讲解,具体的讲解等总结时根据实际例子进行解释。
堆溢出
本人从学习堆溢出开始,进度就快了,后面的一系列利用更多的是在pwn题中学习,没有做过整理,接下来会陆续对这些内容进行系统的整理,不过估计需要很久。
堆溢出与栈溢出类似,也是数据超出范围,不过不同的是,堆并不能直接劫持程序流,而经常需要通过泄漏覆写等方式来getshell。
我遇到过的堆溢出就是通过伪造堆块,然后结合unlink,fastbin之类的攻击或者利用,造成任意地址读或写,然后劫持控制流。堆溢出重在要清晰的了解堆的结构,知道相应位置对应的堆的数据是什么,这样伪造的堆块才能生效。
还有一种利用方式就是house of force,通过堆溢出控制top chunk大小,从而申请到任意地址空间内的块。这种方式利用的限制还是挺多的,比如不能限制分配的次数以及堆块的大小,还要能保证不会在利用的过程中造成top chunk更新等,这属于比较极端的一种方式。
关于堆溢出的其他利用等遇到了,再继续总结。
off-by-one
说一下在堆中的单字节或者NULL字节溢出
之前遇到过的一个题目,可以通过单字节溢出造成可控堆块大小发生变化,从而造成堆溢出。
而NULL字节溢出往往是会造成地址的改变,从而可以达到某种目的。
这种单字节溢出的类型,能不能利用往往是看溢出的字节造成了什么影响。
这种漏洞往往无法直接造成很大的影响,但是和别的漏洞结合起来,花样就多了。
how2heap对于Null字节溢出有一个例子:
假设我们申请了三个堆块a,b,c,大小分别是0x100, 0x200, 0x100,
a对b可以产生Null字节溢出,也就是可以将b的大小以及标志为修改为0x200,
为了能够成功让b以大小0x1f0释放,我们在b+0x1f0的位置写上0x200,从而可以成功释放,
但是,对于c来说,他上面的块大小依然是0x200大小,而不是0x1f0,所以这个差别就产生了利用方式,
假设我们又申请了两个堆块,大小之和不超过0x1f0,地址就都位于原来b的内存中,
当我们释放完第一个堆块,再去释放c时,他会查看前一个堆块是否空闲,也就是释放后的第一个堆块,然后就会把原来的b和c合并,
再次申请时就可以申请到这一块0x300的内存,但是,在其中还包含了一个我们没有最任何处理的堆块。
unlink
堆中的一种攻击方式,可以造成任意地址写,基本的利用方式就不详解了,网上有很多资料。
目前这种攻击方式主要的难点就是绕过针对于前后堆块的检测,对于small bin大小的块,会检测释放块将要合并的块的指针是否指向正确,比如后一块的前一块和前一块的后一块是否是同一块之类的,而对于large bin大小的块,还要检测块的大小是否正确。
这里简单记录一下在内存管理过程中,会调用unlink的地方,总感觉这些都会被利用到:
释放small bin或者large bin大小的堆块时,会检查该块的前后堆块是否是空闲块,如果是就调用unlink合并(最基本的也是最常见的unlink攻击的地方)
在malloc中的unlink:
申请堆块,从large bin中取出时,调用的unlink
合并fast bin加入到unsorted bin时会调用unlink
同上,等遇到不错的题目了再接着总结。
UAF
UAF是最常见也是最容易理解的漏洞,个人觉得这种漏洞的利用花样很多,不同的题目,不同场景下的指针,都可以造成不同的后果,利用方式也有很大差异,往往都取决于题目所给的环境,所以题目的难度一般来说不会很小。
原理就是利用释放后未清零的指针,该指针可以用来伪造块,控制某些本来不该控制的块,访问某些无法访问的块,等等,主要取决于这个指针怎么想方设法的去利用。
这类题目还是蛮多的,慢慢学习吧
fastbin attack
这里将double free在这个地方说一下,最常见的double free的利用就是fastbin attack。
fastbin中的double free产生的原因主要是由于fastbin的一种防double free机制,它会检测当前要释放的堆块和fastbin链顶的块是否为一个块,如果是,就出发double free异常,所以我们常常通过释放第二个堆块之后在释放第一个堆块来造成double free,当然,能再次释放的前提就是UAF,需要有一个依然指向堆中的指针。
fastbin attack可以算作是有关于fastbin的利用的总称,可以细分几类:
fastbin double free:原理就是上面说的double free,当对同一个堆块释放两次后,在fastbin链中就会出现两个块的地址是相同的,所以我们如果申请下来第一块,修改其中的数据时,还在fastbin链中的数据也会被修改,我们最简单的利用方式就将fastbin可控的那一块的指向下一块的指针覆盖为任意的地址,只要可写,我们就可以申请位于任意地址的块,从而便于进行下一步利用。
house of spirit:简单来说,就是伪造fastbin chunk,从而造成分配到任意地址块的目的,这种方式的难点在于伪造这个块,有时还需要前后堆块的配合,还要注意标志位,大小对齐等,how2heap中利用了一个数组伪造了fastbin链,有兴趣可以学习一下。
其余的等遇到了再补充吧。
堆块扩展/收缩(Chunk Extend / Shrink)
在这里只举几个例子简单说明一下。
- 三个unsorted bin大小的块,释放中间一个,若能修改其中的大小位,则再次申请时就会申请到一个更大的块,有可能直接包含了下一块。
- 同Null字节溢出举的例子相同,造成的后果就是获得了一个更大的堆块,同时还有overlapping
- 对于堆块收缩,同样还是那个例子,当我们申请小一点的堆块,即只包含后来的那两个堆块,就造成了堆块收缩
这里需要注意的是,堆块的扩展和收缩,一般都与overlapping相结合的,不然没有利用意义。
unsorted bin大小不定,而且只有一个链,所以最有可能出现堆块大小的变化。
Unsorted Bin Attack
这里利用了一个类似于unlink的攻击,就是从unsorted bin中取块时,虽然并没有调用Unlink,但是取出来的方式也有类似的利用方式,同样也可以造成任意地址写,只是,写入的内容不可控制。
victim = unsorted_chunks(av)->bk
bck = victim->bk;
unsorted_chunks(av)->bk = bck;
bck->fd = unsorted_chunks(av);
基本的利用就是申请一个大小位于unsorted bin中的块,然后释放,通过修改在unsorted bin中的块的指针,所以再把该块取出来的时候就会造成任意地址写。
House of Lore
修改small bin中的最后一个块的后指针,则有可能申请到任意地址的块。
House of Orange
出自HITCON CTF 2016,通过漏洞利用获得free的效果。
_IO_FILE
待续。。。
结:
最后的几个都是待学习的分类,二进制还是不能只看pwn赛题,多看看实际漏洞才是王道,现在的pwn题也越来越趋向于复现实际漏洞了。
还是需要学习。
二进制,干就对了。