二进制漏洞-简单总结
常见漏洞
1 2 3 4 5
| 栈溢出漏洞(Stack-Overflow) 堆溢出漏洞(Heap-Overflow) 释放后重引用漏洞(Use-After-Free) 双重释放漏洞(Double-Free) 越界访问漏洞(Out-of-bounds)
|
栈溢出
原理
栈溢出是指程序在使用栈空间时,向栈中写入的数据超出了栈的大小,导致覆盖了栈的边界,破坏了程序的正常执行流程。
常见利用点
数组
危险函数:gets()、strcpy()、
好像C语言的库函数都挺不安全的...
修复
限制输入字符长度,修改危险函数的调用
堆溢出
原理
堆溢出的原理是当程序向堆中分配内存时,分配的内存空间大小超过了堆实际可用的内存空间大小,导致数据写入内存空间的位置超出了分配的内存范围,从而覆盖了其他重要的内存数据。
常见利用点
和堆溢出不同的就是
**栈溢出**是通过覆盖栈上的返回地址来达到劫持程序的执行流程
**堆溢出**则是通过覆盖物理上邻接的chunk块,
修改他的成员变量
1 2 3 4 5 6 7 8 9
| 覆盖与其物理相邻的下一个 chunk 的内容。 prev_size size,主要有三个比特位,以及该堆块真正的大小。 NON_MAIN_ARENA IS_MAPPED PREV_INUSE the True chunk size chunk content,从而改变程序固有的执行流。 利用堆中的机制(如 unlink 等 )来实现任意地址写入( Write-Anything-Anywhere)或控制堆块中的内容等效果,从而来控制程序的执行流。
|
需要构造一下 利用起来比较复杂,来达到对free函数达到利用(__free_hook)
UAF
原理
一块内存块由指针a指向,使用 free释放后,内存指针被继续使用
1 2 3
| 内存块被释放后,其对应的指针被设置为 NULL , 然后再次使用,自然程序会崩溃。 内存块被释放后,其对应的指针没有被设置为 NULL ,然后在它下一次被使用之前,没有代码对这块内存块进行修改,那么程序很有可能可以正常运转。 内存块被释放后,其对应的指针没有被设置为 NULL,但是在它下一次使用之前,有代码对这块内存进行了修改,那么当程序再次使用这块内存时,就很有可能会出现奇怪的问题。
|
常见利用点
可以利用的是后两种
这两种内存指针被称为 dangling pointer(悬空指针)
举一个简单的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include<stdio.h> #include<malloc.h> int main(){ char *a = (char *)malloc(sizeof(char)); char *a1 = (char *)malloc(sizeof(char)); *a = 1; *a1 = 2; printf("%d ",*a1); free(a); free(a1); char *a2 = (char *)malloc(sizeof(char)); *a2=4; printf("%d",*a1); free(a2); return 0; } 输出 ubuntu@ubuntu:~/Desktop/pwn/UAF$ ./uaf 2 4
|
由于a2是从a和a1在fastbin链上分配的空间,导致a2指向的就是a1的chunk,
但是a1在free后,并没有置空,所以还是a1指向的还是这个内存块
修复
对这些悬空指针置null
Double Free
这个漏洞在linux 中主要在就是fastbin上的
原理
也就是同一块内存被释放了两次 这么简单
难的是利用
常见利用点
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void *a = malloc(0x30);// a = 0x563f0d61b010 (0 void *b = malloc(0x30); // b = 0x563f0d61b030 (1 free(a); free(b); free(a); //这样 会造成bins为 0x563f0d61b010(0)-> 0x563f0d61b030 (1<- 0x563f0d61b010(0 //这个时候 再malloc一个chunk c 就会指向 0x563f0d61b010 void *c = malloc(0x30); // c = 0x563f0d61b010 //这个时候 通过编辑一下 构造一下chunk的fd指针 让fd为任意地址 strcpy(c,"/xef/xbe/xad/xde"); //这时 bins为 0x563f0d61b030(1)-> 0x563f0d61b010(0)->0xdeadbeef //再连续申请3个堆块,这样就能对0xdeadbeef进行读写 void *a1 = malloc(0x30);// a = 0x563f0d61b030 void *a2 = malloc(0x30);// a = 0x563f0d61b010 void *a3 = malloc(0x30);// a = 0xdeadbeef
printf("%p",a3); //输出 0xdeadbeef 后续就可以进行读写操作
|
修复
还是进行指针置空,这样在free到null的时候,程序抛出异常 终止程序执行。
格式化字符串漏洞
原理
没有正确使用format参数造成的漏洞,
例如printf(a);
如果a=’%p’,看程序的版本,x86会将栈中数据输出,x64则会将寄存器中的值泄露了再泄露栈上的数据
1
| 前5个参数是RSI、RDX、RCX、R8以及R9这5个寄存器,并且,RDI用来传递format参数,存放的是format的地址。
|
如果构造了’%s’去执行,就有可能导致段错误 原因就是访问了不可访问的地址
常见利用点
就是一些
1 2 3 4
| printf(a) a为format参数字符串,printf直接按照format参数对应的变量进行输出 scanf("%d",&a) a为指针,如果后面有对*a的输出(printf("%d",*a)),那么就能泄露任意地址
|
修复
修改参数的为正常内容
整数溢出
原理
对len进行了检验,len为短类型(short、char)这类,通过输出长度大于1字节或者2字节(2^8或者 2^16)导致溢出
比如:char len=2^8+1===>实际上 len=1
常见利用点
基本上就是帮助栈溢出啥的
修复
将变量类型修改一下 严格一点 数字就直接无符号类型 直接往大了上