首页 > 其他分享 >C代码审计之指针诡计

C代码审计之指针诡计

时间:2023-05-08 22:56:41浏览次数:30  
标签:诡计 审计 循环 缓冲区 函数指针 buff 溢出 指针

指针诡计(pointer subterfuge)是指通过修改指针值(函数指针、对象指针)来利用程序漏洞的方法。

发生溢出的缓冲区被用于修改函数指针或对象指针的值。
攻击函数指针使得攻击者能够直接将程序的控制权转移到由其提供的任意代码,对对象指针进行修改并赋值的能力导致任意内存写。

 

缓冲区循环类型

缓冲区溢出通常是由边界不足的循环引起的。通常,有以下这些循环类型:
由上界限制的循环:循环重复执行N次,其中N小于或等于p的边界,指针指定一系列对象,例如,从p到p+N-1。
由下界限制的循环:循环重复执行N次,其中N小于或等于p的边界,指针指定一系列对象,例如,从p到p-N+1。

缓冲区能被用于指针覆写的条件:
  1、缓冲区与目标指针在同一个段(bss或data或栈)内。
  2、上界限制、空终止符限制的循环,缓冲区往高地址增长,缓冲区比目标指针地址低。
        下界限制的循环,缓冲区往低地址增长,缓冲区比目标地址地址高。
  3、缓冲区界限不充分,易被缓冲区溢出利用。

ELF包含data段和bss段。data段包含已初始化的全局变量和常量,bss段包含未初始化的全局变量。

函数指针覆写

void good_function(const char *str) {...}

int main(int argc, char *argv[]){
  static char buff[BUFFSIZE];
  static void (*fucPtr)(constr char *str);
  funcPtr = &good_function;
  strncpy(buff, argv[1], strlen(argv[1]));
  (void)(*funcPtr)(argv[2]);
}

解析:程序对strncpy不安全的错误,当strlen(argv[1])大于BUFFSIZE时,就会发生缓冲区溢出。buff缓冲区和funcPtr函数指针都是未初始化的静态变量,位于bss段,因此可以利用缓冲区溢出将函数指针funcPtr的值覆写为攻击者控制的代码(shellcode)地址。当执行到最后一行代码,即执行由funcPtr标识的函数时,shellcode将取代good_function执行。

对象指针覆写
C和C++中的对象指针用于指向动态分配的结构、函数的引用参数、数组等。

void foo(void *arg, size_t len){
  char buff[100];
  long val = ...;
  long *prt = ...;
  memcpy(buff, arg, len);
  *prt = val;
  ...
  return;
}

解析:memcpy进行无界复制(没有对源数据进行检查),当len>100时buff会发生溢出。在溢出缓冲区后,可以覆写ptr和val,接下来在*ptr=val时就会发生任意内存写。

缓解方案

导致指针诡计的根本原因是缓冲区溢出,因此预防指针诡计的最佳措施就是消除产生缓冲区溢出的条件。

标签:诡计,审计,循环,缓冲区,函数指针,buff,溢出,指针
From: https://www.cnblogs.com/jimmy-hwang/p/17383414.html

相关文章

  • C语言--指针的进阶3
    指向函数指针数组的指针intAdd(intx,inty){ returnx+y;}intmain(){ //pf函数指针 int(*pf)(int,int)=Add; //pfArr函数数组指针 int(*pfArr[4])(int,int)={Add}; //ppfArr是一个指向[函数指针数组]的指针 int(*(*ppfArr)[4])(int,int)=&pfArr;......
  • 指针学习
    #include<stdio.h>intmain(void){inta;int*p;printf("%d\n",sizeof(a));printf("%d\n",sizeof(p));return0;在上面这段代码中,用sizeof的方式显示了int和int*有占据多少字节,验证了指针变量的字节根据系统位数形成,而拿我使用的64位系统举例,输......
  • 1 字符串 、2 指针 、3 结构体 、4 方法、 5 接口
    目录1字符串2指针3结构体4方法5接口1字符串packagemain//字符串funcmain(){ //1定义字符串 //vars="中alqz" //2字符串可以按下标取值,不能改 //s[0]=98 //fmt.Println(s[0])//取字节,是个数字 //fmt.Println(s[3]) //fmt.Printf("%T\n",s[3])/......
  • Rust语言中级教程之指针
    Rust语言中级教程一、指针什么是指针指针是计算机引用无法立即直接访问的数据的一种方式(类比书的目录)数据在物理内存(RAM)中是分散的存储着地址空间是检索系统指针就被编码为内存地址,使用usize类型的整数表示。一个地址就会指向地址空间中的某个地方地址空间的范围是......
  • C语言指针说明
    地址 说到指针,先说说地址,看一段小程序#include"stdio.h"intmain(){  inta=10;  int*p=&a;  printf("%p\n",p);  return0; }//output0x7fff8b6a378c"0x7fff8b6a378c"是系统RAM中的特定位置,通常以十六进制的数字表示,系统通过这个地址,就可......
  • C语言--指针的进阶2
    函数指针存放函数地址的指针。intAdd(intx,inty){ returnx+y;}intmain(){ inta=10; intb=20; //printf("%d\n",Add(a,b));//&函数名,函数名,都是函数的地址。 //int(*pa)(int,int)=&Add; int(*pa)(int,int)=Add;//对于函数指针的解引用下面都......
  • Java 双指针项目中的实际应用
    背景说明最近在做财务相关的系统,对账单核销预付款从技术角度来看就是将两个数组进行合并对账单核销预付款前提条件:对账单总金额必须等于未核销金额数据示例对账单数据单号金额B0001100B000280B0003120预付款数据单号未核销金额PRE0011......
  • C语言函数指针数组,GCC编译问题
    使用C语言函数指针数组实现简单的计算器,代码如下#include<stdio.h>#include<stdlib.h>doubleadd(doublea,doubleb){return(a+b);};doublesub(doublea,doubleb){return(a-b);};doublemul(doublea,doubleb){return(a*b);};doubl......
  • 空指针指向地址问题
    //src=data.path;charfilepath2[64]={0};strcpy(filepath2,"/tmp/mnt/usb1_1/gw_upgrade/V1.0.0.bin");src=filepath2;空指针指向地址问题空指针指向地址问题空指针指向地址问题空指针指向地址问题......
  • 双指针|长度最小的子数组
    给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其和≥target的长度最小的连续子数组[numsl,numsl+1,...,numsr-1,numsr],并返回其长度。如果不存在符合条件的子数组,返回0。输入:target=7,nums=[2,3,1,2,4,3]输出:2解释:子数组[4,3]是该条......