CTF PWN-攻防世界Overflow整数溢出漏洞

news2024/9/27 7:21:06

文章目录

  • 前言
  • 整数溢出
    • 有符号整数溢出
    • 无符号整数回绕
    • 截断与宽度溢出
  • int_overflow
    • 题目漏洞分析
    • EXP程序构造
  • 总结

前言

滴水穿石,非一日之功。继续练习攻防世界 PWN 题目,此次练习的题目是 int_overflow,顾名思义是整数溢出类型的漏洞:
在这里插入图片描述

整数溢出

做题不是目的,目的是为了学习不懂的知识。So 先来看看什么整数溢出漏洞吧。

C 语言中整数的分类及各自的大小范围如下所示:
在这里插入图片描述
正是因为这些类型的大小范围的限制才导致可能发生整数溢出。

整数溢出的异常有3种:

分类描述
溢出只有有符号数才会发生溢出;溢出标志OF可检测有符号数的溢出
回绕环绕特指的是无符号数,比如0减1时会变成最大的数,1字节的话会变为255,而255+1时会变为0;进位标志CF可检测无符号数的回绕
截断就是将一个较大宽度的数放入一个宽度较小的数中,高位将发生截断

有符号整数溢出

有符号整数溢出被分为上溢出和下溢出两种。

#include <stdio.h>
int main()
{
   //上溢出  
   int i = 2147483647;//int的最大值
   i++;
   printf("%d\n",i); //输出为最小负数

   //下溢出
   int j = -2147483648;//int的最小值
   j--;
   printf("%d\n",j);//输出为最大正数
   return 0;
}

运算结果如下:
在这里插入图片描述
【漏洞示例】

char buf[80];
void vulnerable() {
    int len = read_int_from_network();
    char *p = read_string_from_network();
    if (len > 80) {
        error("length too large: bad dog, no cookie for you!");
        return;
    }
    memcpy(buf, p, len);
}

此案例中,如果给 len 赋值一个负数,就可以绕过 if 判断,但是到 memcpy 时,因为第三个参数是 size_t(unsigned int) 类型,负数的 len 会被认为是一个很大的正数,从而复制大量内容到 buf,导致缓存区溢出。

无符号整数回绕

无符号数的计算不会溢出,但是会发生回绕。

#include <stdio.h>

int main()
{
   unsigned int i = 4294967295;
   i++;
   printf("%d\n",i); //输出为0
   return 0;
}

【漏洞示例】

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

相较于上一个漏洞例子,这个例子避开来缓冲区溢出的问题,但是如果 len 很大时,len+5 会回绕,比如若是 len = 0xFFFFFFFF,len + 5 = 0x00000004,这时只 malloc 了4个字节,然而之后会 read 大量数据,缓冲区溢出也会发生。

截断与宽度溢出

1、加法截断

0xffffffff + 0x00000001
= 0x0000000100000000 (long long)
= 0x00000000 (long)

【漏洞示例】

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,程序分配了内存来存拼接后的字符串。这里 total 的类型为 unsigned short int,如果攻击者提供的两个字符串总长度无法用 total 表示,则会发生截断,从而导致后面的缓冲区溢出。

2、乘法截断

0x00123456 * 0x00654321
= 0x000007336BF94116 (long long)
= 0x6BF94116 (long)

3、宽度溢出与整数提升

#include<stdio.h>
void main() {
    int l;  
    short s;
    char c;
    l = 0xabcddcba;
    s = l;
    c = l;
    printf("宽度溢出\n");
    printf("l = 0x%x (%d bits)\n", l, sizeof(l) * 8);
    printf("s = 0x%x (%d bits)\n", s, sizeof(s) * 8);
    printf("c = 0x%x (%d bits)\n", c, sizeof(c) * 8);
    printf("整型提升\n");
    printf("s + c = 0x%x (%d bits)\n", s+c, sizeof(s+c) * 8);
}

OUT:    
$ ./test
宽度溢出
l = 0xabcddcba (32 bits)
s = 0xffffdcba (16 bits)
c = 0xffffffba (8 bits)
整型提升
s + c = 0xffffdc74 (32 bits)

综上可以看出,在整数转换的过程中,有可能导致下面的错误:

  1. 损失值:转换为值的大小不能表示的一种类型;
  2. 损失符号:从有符号类型转换为无符号类型,导致损失符号。

int_overflow

接下来开始练习攻防世界的整数溢出题目:int_overflow。下载并查看附件,是个 32 位小端程序:
在这里插入图片描述
开启了 NX 保护,但是未开启 PIE 程序内存加载基地址随机化保护机制(即静态反汇编的地址可以直接使用)。

运行 elf 文件,程序要求用户依次输入用户名和密码,然后结束运行:
在这里插入图片描述

题目漏洞分析

将 elf 拖进 IDA Pro 中进行分析,F5 查看主函数伪代码如下:
在这里插入图片描述
逻辑很简单,用户输入整数 1 则进入 login(),跟进查看 login 函数:
在这里插入图片描述
两处 read 函数依次获取用户名、密码很正常,均不存在溢出,但是密码 buf 传递给了 check_passwd 函数,那就继续跟进:
在这里插入图片描述
分析下上述函数逻辑:

  1. 第 5 行代码定义了一个无符号 8 位整数变量 unsigned _int8 v3(取值范围 0-255);
  2. 第 7 行代码 v3 = strlen(s),取 check_passwd 函数中用户传递进来的密码字符串的长度作为 v3 的值。但是这里一定要注意的是: strlen 函数的返回值是 size_t 类型,在 32 位文件中即 unsigned int 类型,也就是无符号 32 位整型
  3. 第 8 行代码又限制 v3 变量的值(即输入的密码字符串的长度)需要大于整数 3 且小于整数 8;

以上过程存在漏洞的地方就在于:第 7 行代码 v3 = strlen(s) 是将 32 位的数据赋值给 8 位的变量,所以当 password 的长度 strlen(s) 超过 255 个字符时,将发生整数溢出漏洞,编译器将会自动进行截断,只留下后 8 位。此时只要满足 255+3 < strlen(s) <= 255+8,也就是 s 的长度在 (258,263] 这个范围内就可以满足判断条件。

进一步检查 dest 的栈结构:
在这里插入图片描述
在这里插入图片描述
程序为 check_password() 函数中的 dest 变量分配了 0x14 字节的储存空间,由于 strcpy(dest, s) 的 s 参数来源于 login() 函数第二个 read 函数,回溯发现其却可以读取 0x199 字节数据:
在这里插入图片描述
所以在利用整数溢出漏洞绕过 if 判断后,check_password() 函数中的 strcpy(dest, s) 处便显而易见地发生栈溢出

因此我们可以在 check_password 函数中通过整数溢出绕过 if 条件判断对输入字符串长度的限制,然后通过 strcpy 函数将输入字符串 s 先复制给 dest,同时在拷贝过程借助栈溢出漏洞将后门函数的地址赋值给 result,接着将 result 作为返回值返回给上层函数,也就是 check_passwd(),最后该返回值再作为 login() 函数的返回值返回给主程序,主程序便可以 getshell!

接下来寻找程序中是否存在后门函数,发现确实存在后门函数what_is_this:
在这里插入图片描述
偏移地址为 0x804868B,因为此程序未开启 PIE 内存加载基地址随机化保护机制,所以静态反汇编的地址可以直接使用:
在这里插入图片描述

EXP程序构造

综上所述,exp 利用程序的思路如下:

  1. 输入 password 字符串,位数大小在 (258,263] 这个范围内,利用整数溢出漏洞,绕过对字符串长度的判断;
  2. 利用 strcpy(dest, s) 函数处的栈溢出漏洞,将后门函数 what_is_this() 的地址填入缓冲区中并作为返回地址返回给主程序。

更细致点说就是:

  • 首先利用栈溢出,填充 dest 的 0x14 字节内存;
  • 然后再发送 4 字节内容覆盖栈底指针 ebp;
  • 接着用 system 函数的地址覆盖返回值;
  • 最后利用整数溢出漏洞,将字符串长度补充至 (258,263] 位,以此绕过对字符串长度的判断。

最终整体的栈结构将构造如下:
在这里插入图片描述
EXP 程序:

from pwn import *

io = remote("161.147.171.105", 61383)
cat_flag_addr = 0x0804868B
io.recvuntil("choice:")
io.sendline("1")
io.recvuntil("username:")
io.sendline("name")
io.recvuntil("passwd:")
payload = b'A'*(0x14 + 0x4) + p32(cat_flag_addr) + b'A'*(256-0x14-4-4+3)
io.sendline(payload)
io.interactive()

成功获取 Flag:cyberpeace{dee51b69c2224dbf4814ac4f6f941d20}
在这里插入图片描述
在这里插入图片描述

总结

本文学习了缓冲区溢出漏洞常见的一种场景:整数溢出,一旦不认真考虑整数变量的范围,此类漏洞缺陷很容易在程序员的编码过程中发生,这也是安全工作人员需要注意审计的地方。

本文参考文章:

  1. 整数溢出-From Ghostasky;
  2. 【攻防世界pwn-int_overflow】;
  3. 攻防世界 pwn 新手练习区 int_overflow;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/805393.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小波分解机械信号

function [ output_args ] ex4_2( input_args ) %EXAMPLE4_2 Summary of this function goes here % Detailed explanation goes here clc; clear; load sumsin; s sumsin; % 进行3层小波分解&#xff0c;小波基函数为db3 [c,l] wavedec(s,3,db3); figure(1) subplot(21…

flutter minio

背景 前端 经常需要上传文件 图片 视频等等 到后端服务器&#xff0c; 如果到自己服务器 一般会有安全隐患。也不方便管理这些文件。如果要想使用一些骚操作 比如 按照前端请求生成不同分辨率的图片&#xff0c;那就有点不太方便了。 这里介绍以下 minio&#xff0c;&#xff0…

Vue如何实现页面跳转路由,实现单页面跳转

1、#锚链接&#xff0c;#后面的就是锚链接 2、#之后都是hash地址&#xff0c;这些都是在浏览器的F12中获得的 3、在浏览器查询链接地址的方法&#xff0c;href代表着当前的浏览器地址&#xff0c;&#xff1a; 使用location.href: 4、只想获取#链接地址&#xff0c;后面加loc…

Linux设备模型之input子系统详解

在键盘驱动代码分析的笔记中&#xff0c;接触到了input子系统.键盘驱动&#xff0c;键盘驱动将检测到的所有按键都上报给了input子系统。Input子系统是所有I/O设备驱动的中间层&#xff0c;为上层提供了一个统一的界面。例如&#xff0c;在终端系统中&#xff0c;我们不需要去管…

Redis(五)—— Redis进阶部分

一、Redis配置文件详解 注意这是Redis服务本身的配置文件&#xff0c;相当于maven的settings.xml&#xff0c;而不是我们在springboot去配置Redis的那个application.yml。 核心部分include 引入其他redis配置文件&#xff0c;相当于spring的<import>bind 设置IP&#xf…

【Java|golang】2500. 删除每行中的最大值

给你一个 m x n 大小的矩阵 grid &#xff0c;由若干正整数组成。 执行下述操作&#xff0c;直到 grid 变为空矩阵&#xff1a; 从每一行删除值最大的元素。如果存在多个这样的值&#xff0c;删除其中任何一个。 将删除元素中的最大值与答案相加。 注意 每执行一次操作&#…

【Vue3】递归组件

1. 递归组件mock数据 App.vue <template><div><Tree :data"data"></Tree></div> </template><script setup lang"ts"> import { reactive } from vue; import Tree from ./components/Tree.vue; interface Tr…

【数学】差分数组(一维差分)

一.简介 差分数组是指对一个一维数组进行差分操作得到的新数组。差分操作是指计算原数组中相邻元素之间的差异&#xff0c;并将这些差异作为新数组的元素。 具体而言&#xff0c;对于一个长度为n的一维数组x&#xff0c;其差分数组diff的第i个元素可以通过以下公式计算得到&am…

【Rust笔记】意译解构 Object Safety for trait

意译解构Object Safety for trait 借助【虚表vtable】对被调用成员函数【运行时内存寻址】的作法允许系统编程语言Rust模仿出OOP高级计算机语言才具备的【专用多态Ad-hoc Polymorphism】特性。 计算机高级语言中的“多态”术语是一个泛指。它通常可被细化为 基于继承关系的“子…

时间复杂度介绍及其计算

时间复杂度 1.算法效率 如何衡量一个算法的好坏呢&#xff1f;看这段代码&#xff1a; long long Fib(int N) {if(N < 3)return 1;return Fib(N-1) Fib(N-2); }这是斐波那契数列的递归代码&#xff0c;非常简洁&#xff0c;那么这就一定说明它好吗&#xff1f;答案显而易…

智能家居是否可与ChatGPT深度融合?

​ ChatGPT自2022年面世以来&#xff0c;已为亿万网民提供智能问答服务。然而我们是否曾想到&#xff0c;这一人工智能驱动的聊天机器人&#xff0c;是否可为智能家居赋能? 要实现ChatGPT与智能家居设备之间的无缝对话&#xff0c;单单依靠一台终端是远远不够的。ChatGPT必须…

Java基础_多线程

Java基础_多线程 什么是多线程并发, 并行多线程的实现方式继承Thread类实现Runnable接口实现Callable接口和Future接口实现方式对比 常见的成员方法常见方法进程的优先级守护线程礼让线程插入线程 线程安全线程的生命周期售票模拟同步代码块同步方法lock锁 死锁 生产者和消费者…

【C语言】通讯录1.0 (静态版)

前言 通讯录是一种记录联系人信息的工具&#xff0c;包括姓名、电话号码、电子邮件地址、住址等。 此通讯录是基于自定义类型的基础上进行制作&#xff0c;通讯录&#xff08;静态版&#xff09;&#xff0c;后期会进行通讯录的更新 ****** 有需要源代码&#xff0c;见文章末尾…

大于号在python中怎么打,python大于等于怎么写

大家好&#xff0c;小编为大家解答python中大于并小于一个数代码的问题。很多人还不知道python中大于等于且小于等于&#xff0c;现在让我们一起来看看吧&#xff01; 1、python 中不等于怎么表示 #!/usr/bin/python a1 b2 if ab: print "a 等于 b" if a!b: print &…

ArcGIS Pro 制作一张立体地形图

在各位关掉文章之前,先把成果贴上来 下面开始操作步骤贴图,这个真的很简单,没有什么复杂的软件联动和操作 这是哥斯达黎加部分区域的30mDEM,数据链接我放在最后。 首先,找到工具【栅格函数】—【统计分析】,选择下载好的栅格,领域设置行列数都改为6,点击创建新图层。然…

从官网认识 JDK,JRE,JVM 三者的关系

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ JVM 是一些大厂面试必问点&#xff0c;要想解决 OOM、性能调优方面的问题&#xff0c;掌握 JVM 知识必不可少&#xff0c;从今天开始&#xff0c;将为大家介绍 JVM 的常用知…

ShardingSphere Pipeline 兼容 MySQL 时间类型 解读

背景 ShardingSphere 在日常中&#xff0c;开发者经常会用到时间类型&#xff0c;如果熟悉的时间类型涉及到了时区、精度&#xff0c;哪种时间类型更合适&#xff1f;JDBC 驱动中又有哪些注意事项&#xff1f;因此&#xff0c;对数据库时间类型有更深入的了解&#xff0c;有助于…

android framework车载桌面CarLauncher的TaskView详细源码分析

1、构建相关的TaskView&#xff0c;装载到对应的ViewGroup b站免费视频教程讲解&#xff1a; https://www.bilibili.com/video/BV1wj411o7A9/ //packages/apps/Car/Launcher/src/com/android/car/carlauncher/CarLauncher.java void onCreate() { //ignoresetContentView(R.…

管理类联考——写作——记忆篇——论证有效性分析——析错口诀

析错口诀 概念不明确&#xff0c;我就说它概念模糊&#xff0c;并做不利它的解释。【有概念模糊之嫌&#xff0c;A是理解1&#xff1f;还是理解2&#xff1f;】概念有变换&#xff0c;我就说它混淆概念&#xff0c;并指出混淆的环节。&#xff08;概念推概念&#xff0c;我就看…

类方法(成员方法)与构造方法的区别与联系

&#xff08;粗略理解为&#xff1a;除了构造方法以外的所有方法都是成员方法&#xff09; 区别&#xff1a; 构造方法在创建对象时用new调用&#xff0c;是为了给对象的数据进行初始化&#xff0c;没有返回值。 成员方法是实现对类中成员变量的操作&#xff0c;提供某些功能…