专栏首页FreeBuf以UPX漏洞为例介绍整数溢出(基础篇)

以UPX漏洞为例介绍整数溢出(基础篇)

*本文原创作者:tocttou,本文属FreeBuf原创奖励计划,未经许可禁止转载

我发现Freebuf上没有整数溢出漏洞的基础介绍,所以这篇文章通过分析我刚刚发现的UPX源代码中的整数溢出漏洞,介绍一下C/C++整数溢出漏洞的原理、触发和修复方法。这篇文章暂不涉及如何利用整数溢出达到远程代码执行,UPX的漏洞只是一个拒绝服务漏洞。

0x01 整数溢出原理

C/C++中的整数溢出基本原理非常简单,比如unsigned char number = 200 + 200;。最终number的值是400 mod 256=144。这是因为C++对于无符号整数(unsigned char, unsigned int等)溢出的处理是取模,导致的结果是两个整数相加,反而结果更小。C++中有符号整数溢出是未定义行为。下文中所有提到整数溢出,都指的是无符号整数溢出。整数溢出的利用一般都是用它来导致缓冲区溢出,进而利用缓冲区溢出技巧来代码执行、泄露内存或拒绝服务。

我认为对于文件解析一类的程序要特别注意整数溢出问题,因为有很多文件格式,它们的文件头中包含了长度、偏移信息。攻击者通过构造畸形文件可以直接控制这些信息,尝试触发整数溢出或其他缓冲区溢出漏洞。所以在写代码时我们需要关注的点有:第一,将整数运算的结果作为缓冲区长度分配内存;第二,将整数运算的结果作为偏移量读取内存。

对于第一点,比如这段代码:

如果len1是攻击者可控的值,那么这里就存在整数溢出问题。假设是32位程序,攻击者选取len1 = 0xFFFFFFC1,那么len1+40等于1,所以buffer的长度为1。第三行,作者错误地假设了下标0x10一定会在buffer分配的内存区间内,但实际上这里发生了越界写入。

对于第二点,看这段代码:

这里作者错误地假设了如果40 + offset这个index没有越界,则offset这个index也没有越界。但是如果我们取offset=255。则40 + offset = 39,那么我们就将buffer[255]这个越界地址写入了0。

0x02 分析UPX整数溢出漏洞

这个漏洞是我最近找出来的UPX开源项目的漏洞。因为最近研究UPX,随手在CVE数据库里搜索了一下有没有UPX的漏洞,结果还真有,CVE-2017-15056。漏洞报告在 https://github.com/upx/upx/issues/128 。这是一个畸形文件导致内存越界读取漏洞,我看了一下修复的commit。从commit来看,修复并不完美,而且正好可以拿来讲整数溢出。

我们重点看commit中PackLinuxElf32::PackLinuxElf32help1函数中添加在250-256行的校验:

file_size是用户输入的ELF文件的大小,e_phoff, e_phnum, e_shoff, e_shnum都是ELF文件头部的字段。这些值我们可以通过构造畸形ELF文件来控制。显然这里作者在避免缓冲区越界读取问题,检测e_shoff + e_shnum sizeof(Elf32_Shdr)这个偏移量是否依然在ELF文件大小之内。如果不在,就抛出异常,因为我们的缓冲区只有file_size这么大。作者想到了检查整数溢出,但是他的方法是把e_phoff和e_shoff从unsigned int转换成unsigned long。值得注意的是unsigned long的大小是:MSVC下永远是32位整数,gcc和clang下32位ELF就是32位整数,64位ELF就是64位整数。所以如果我们用32位UPX的话,(unsigned long)e_shoff + e_shnumsizeof(Elf32_Shdr)是可以溢出的,只要e_shoff足够大,让它们的和大于或等于2^32,它的值就可以小于file_size。

往下:

268至272行针对e_type不是ET_DYN (shared object file)情形,268行的len就是之前258行校验的值,按上文说的len是溢出之后的值,它小于file_size,但是e_phoff很大。所以到272行phdri=e_phoff + file_image又发生整数溢出,phdri会小于file_image。所以如果接下来phdri被用于读取Elf32_Phdr结构体的值,那么读到的实际上是缓冲区file_image以外的值。但是随后发现phdri使用之前会检查e_phoff是否为0x40。所以这个缓冲区越界读取是触发不了的。

接下来274行以下针对e_type是ET_DYN情形,类似地,因为我们取e_shoff为一个接近2^32的值,如0xFFFFE000,这样shdri= (Elf32_Shdr *)(e_shoff + file_image);指向的就是file_image内存之前的位置。然后进入elf_find_section_type(Elf32_Shdr::SHT_DYNSYM)函数:

for循环内shdri指针被用来读取shdri->sh_type的值。这时因为shdri不是一个有效的地址,这里就会触发崩溃。

所以我的PoC就直接把CVE-2017-15056的PoC拿来,把e_type改成3 (ET_DYN)、e_shoff改成0xFFFFE000、e_shnum改成0x00FF。这样e_shoff + e_shnum * sizeof(Elf32_Shdr)的值是0x07D8,小于file_size。shdri等于file_image - 0x2000。用32位UPX压缩PoC,就能看到崩溃:

当然这个整数溢出漏洞只能到拒绝服务为止了,应该是没法远程利用的(比如把内存写到输出文件里)。我也对UPX、ELF文件了解不多,所以就没深入研究其他位置有没有溢出问题。

0x03 修复

我提交了一个Pull request修复这个UPX漏洞,但是他们没用我的PR,他们自己写了一个commit。对于加法避免整数溢出的方法两种:加法运算的和如果小于任何一个加数,则有溢出:

另一种是转换成64位无符号整数:

乘法:转换成64位或者:

0x04 参考

https://github.com/upx/upx/issues/128 https://github.com/upx/upx/commit/ef336dbcc6dc8344482f8cf6c909ae96c3286317 https://github.com/upx/upx/pull/190 https://github.com/upx/upx/commit/90a1322929259b3049f11564d25cc1bc99ee54fa

*本文原创作者:tocttou,本文属FreeBuf原创奖励计划,未经许可禁止转载

本文分享自微信公众号 - FreeBuf(freebuf),作者:tocttou

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 2018年10月十大恶意软件,挖矿类仍然占据头牌

    Check Point近期发布了最新的全球安全威胁指数,该指数显示了近期的恶意软件、移动端恶意软件以及漏洞方面的变化趋势,可作为一定的参考。

    FB客服
  • 远控木马中的VIP:盗刷网购账户购买虚拟礼品卡

    为了省钱,很多人会尝试各种各样的方法免费获取网盘和视频网站的VIP权限。正因为有这种需求,各种所谓的“网盘不限速神器”或是“VIP助手”也就应运而生了。但这个工...

    FB客服
  • 技术讨论 | Windows 10进程镂空技术(木马免杀)

    在Win10 x64环境下替换正常的进程,是一个比较高超的技术。使用该技术,可以内存执行病毒、木马。在文件层面实现免杀。可以把一个木马使用DES加密,放在资源里...

    FB客服
  • 技术讨论 | Windows 10进程镂空技术(木马免杀)

    在Win10 x64环境下替换正常的进程,是一个比较高超的技术。使用该技术,可以内存执行病毒、木马。在文件层面实现免杀。可以把一个木马使用DES加密,放在资源里...

    FB客服
  • Visual Studio Installer打包安装项目VS2015

    使用VS2015的Visual Studio Installer打包安装项目,虽然整体操作很简单,但还是有几个特殊的点需要记一下,故写下此博客方便以后查阅

    vv彭
  • RxJava2 实战知识梳理(4) - 结合 Retrofit 请求新闻资讯

    如何通过结合Retrofit框架来进行网络请求,也是RxJava的学习过程中必须要掌握的一环。网上已经有很多开源项目和文章介绍了,今天这篇文章,我...

    用户2802329
  • 回顾 <程序员练级攻略>

    大约四五年前,小编偶然在网上看到这篇 <程序员练级攻略> (首发于酷壳网), 文笔流畅,内容实在,十分受用。到今天,技术届的发展天翻地覆,再来回顾这篇“大文”,...

    包子面试培训
  • 记一次应急中发现的诡异事件

    在一次应急响应中,无意发现来自不同地区和人员的攻击,两种留后门的方法,截然不同的操作,不同的技术手法。

    FB客服
  • 用AI实现C++、Java、Python代码互译,运行成功率最高达80.9%

    因为新冠疫情的缘故,美国一些地区的失业救济系统不堪重负,而这些系统都是上古语言COBOL写的。

    量子位
  • 用AI实现C++、Java、Python代码互译,运行成功率最高达80.9%

    因为新冠疫情的缘故,美国一些地区的失业救济系统不堪重负,而这些系统都是上古语言COBOL写的。

    代码医生工作室

扫码关注云+社区

领取腾讯云代金券