虽然这个技术已经不能在新版本上使用了,但是还是有许多学习价值的。
刚开始学,与大家分享一下,直说自己不是很明白的几个点,然后是参考的文章。
实例代码如下:
/* Heap overflow vulnerable program. */ #include <stdlib.h> #include <string.h> int main( int argc, char * argv[] ) { char * first, * second; /*[1]*/ first = malloc( 666 ); /*[2]*/ second = malloc( 12 ); if(argc!=1) /*[3]*/ strcpy( first, argv[1] ); /*[4]*/ free( first ); /*[5]*/ free( second ); /*[6]*/ return( 0 ); }
我们要知道堆是从内存低址到内存高址增长的,很明显第三行代码strcpy有堆溢出。
此时如果传入的数据过多,就会覆盖second的堆首、堆身数据。
payload条件如下:
- prev_size = even number and hence PREV_INUSE bit is unset.
- size = -4
- fd = free address – 12
- bk = shellcode address
这里fd、bk都是指second中要被覆盖的信息。
下边重点解释一下:
怎么判断堆是被占用还是free呢 ,就是看prev_inuse位
怎么确定second堆是处于占用还是free呢 就是查看second的下一个堆的prev_inuse位。
这样通过first-8+size(first)+size(second)+4(pre_size),就可以确定second是否被占用。
此时我们覆盖size为-4,所以上边的计算就是first-8+size(first)
也就是
认为second的下一个chunk就是second本身,这样通过覆盖second的prev_inuse,就可以使second chunk处于free状态。
在free( first );时,因为first chunk和second chunk都处于free状态,发生unlink操作。
fd保存first chunk 下一个chunk的地址,再加上12就是下一个chunk的bk ,unlink操作将其覆写为first chunk的bk
bk保存first chunk上一个chunk的地址,再加上8就是上一个chunk的fd地址,unlink将其覆写为fd的地址
简单点来说就是:
- fd+12 is overwritten with bk.
- bk+8 is overwritten with fd.
此时我们将fd设置为free address – 12,bk 设置为shellcode address,所以fd+12正好就是free@got的地址,正好将其覆盖为shellcode的地址,这样以后调用free函数时,我们的shellcode就可以执行了。
- fd = free address – 12
- bk = shellcode address
参考资料:
5. http://wooyun.jozxing.cc/static/drops/tips-16610.html
等。