Oops-re's Blog.

简单复习--二进制漏洞

字数统计: 1.3k阅读时长: 5 min
2023/04/30

二进制漏洞-简单总结

常见漏洞

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上的

chunk_struct

原理

也就是同一块内存被释放了两次 这么简单

难的是利用

常见利用点

例子

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

常见利用点

基本上就是帮助栈溢出啥的

修复

将变量类型修改一下 严格一点 数字就直接无符号类型 直接往大了上 
CATALOG
  1. 1. 二进制漏洞-简单总结
    1. 1.1. 栈溢出
      1. 1.1.1. 原理
      2. 1.1.2. 常见利用点
      3. 1.1.3. 修复
    2. 1.2. 堆溢出
      1. 1.2.1. 原理
      2. 1.2.2. 常见利用点
    3. 1.3. UAF
      1. 1.3.1. 原理
      2. 1.3.2. 常见利用点
      3. 1.3.3. 修复
    4. 1.4. Double Free
      1. 1.4.1. 原理
      2. 1.4.2. 常见利用点
      3. 1.4.3. 修复
    5. 1.5. 格式化字符串漏洞
      1. 1.5.1. 原理
      2. 1.5.2. 常见利用点
      3. 1.5.3. 修复
    6. 1.6. 整数溢出
      1. 1.6.1. 原理
      2. 1.6.2. 常见利用点
      3. 1.6.3. 修复