作者:huity
出处https://www.cnblogs.com/huity35/p/11252574.html
版权:本文版权归作者所有。文章在博客园、看雪、个人博客同时发布。
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任。

0x00 前言

这一节开始,我们学习整数溢出相关漏洞。
实验环境:Win10专业版+VMware Workstation 15 Pro+Win7 x86 sp1
实验工具:VS2015+Windbg+KmdManager+DbgViewer

0x01 漏洞原理

整数溢出

整数分为有符号和无符号两种类型,有符号数以其最高为作为其符号位,即正整数最高为0,负整数最高为为1,而无符号数无此类情况,其取值范围是非负数。平常在编程时。最常用到的整型变量有 short int(2B),unsigned int(2B),int(4B)和long int(4B)。不同类型的整数在内存中均有不同的取值范围,当我们向其存储的数据超过该类型整数的最大值,就会导致整数溢出。溢出后的数据,可能会被截断,而造成程序出现错误。

Demo(基于栈的整数溢出)

#include "stdio.h"
#include "string.h" int main()
{
int i;
char buf[];
unsigned short int size;
char overflow[]; memset(overflow,,sizeof(overflow)); printf("Input the num:\n");
scanf("%d",&i); size=i;
printf("size:%d\n",size);
printf("i:%d\n",i); if(size>)
return -;
memcpy(buf,overflow,i);//栈溢出 return ;
}

上面的demo中,size为无符号短整数(0-65535),当我们输入大于65535是就会造成溢出,例如我们输入65536,最终得到的size为0,从而绕过边界检查,但是在memcpy函数复制数据时,使用的是int类型的i参数,导致栈溢出。

Demo(基于堆的整数溢出)

#include "stdio.h"
#include "string.h"
#include "Windows.h"
int main()
{
int heap;
unsigned short int size;
char* v1,*v2;
HANDLE HeapHandle; printf("int put size: \n");
scanf("%d",&size); HeapHandle = HeapCreate(HEAP_GENERATE_EXCEPTIONS,0x100,0xfff); if(size <=0x50)
{
size-=;
printf("size:%d\n",size);
v1=(char*)HeapAlloc(HeapHandle,,size);
v2=(char*)HeapAlloc(HeapHandle,,0x50);
}
HeapFree(HeapHandle,,v1);
HeapFree(HeapHandle,,v2);
return ;
}

上述demo中size为unsigned short int,小于5时,例如,当size=2时,size减去5则得到负数,但size取值范围导致无法识别负数,而得到正数65533,而分配得到大的堆块,从而溢出导致覆盖到后面的堆管理结构。

分析

打开漏洞驱动程序源码,找到漏洞函数TriggerIntegerOverflow,如下:
__declspec(safebuffers)
NTSTATUS TriggerIntegerOverflow( _In_ PVOID UserBuffer, _In_ SIZE_T Size)
{
ULONG Count = ;
NTSTATUS Status = STATUS_SUCCESS;
ULONG BufferTerminator = 0xBAD0B0B0;
ULONG KernelBuffer[BUFFER_SIZE] = { };//512*4=2048
SIZE_T TerminatorSize = sizeof(BufferTerminator);// PAGED_CODE(); __try
{
//
// UserBuffer 为Ring3地址 其中前面均用A填充,倒数8字节开始的4字节为Payload地址 最后四字节为0xBAD0B0B0
ProbeForRead(UserBuffer, sizeof(KernelBuffer), (ULONG)__alignof(UCHAR)); DbgPrint("[+] UserBuffer: 0x%p\n", UserBuffer);
DbgPrint("[+] UserBuffer Size: 0x%X\n", Size);
DbgPrint("[+] KernelBuffer: 0x%p\n", &KernelBuffer);
DbgPrint("[+] KernelBuffer Size: 0x%X\n", sizeof(KernelBuffer)); #ifdef SECURE
//
// 安全注意:这是安全的,因为开发人员没有对用户提供的值进行任何算术运算。
//相反,开发人员从KernelBuffer的大小减去ULONG的大小,即x86上的4。 因此,不会发生整数溢出,并且此检查不会失败 if (Size > (sizeof(KernelBuffer) - TerminatorSize))
{
DbgPrint("[-] Invalid UserBuffer Size: 0x%X\n", Size); Status = STATUS_INVALID_BUFFER_SIZE;
return Status;
}
#else
DbgPrint("[+] Triggering Integer Overflow (Arithmetic Overflow)\n"); // 注意这里是有漏洞的版本
if ((Size + TerminatorSize) > sizeof(KernelBuffer))//FFFFFFFF+4 = 00000003
{
DbgPrint("[-] Invalid UserBuffer Size: 0x%X\n", Size); Status = STATUS_INVALID_BUFFER_SIZE;
return Status;
}
#endif //实现拷贝操作
while (Count < (Size / sizeof(ULONG)))
{
if (*(PULONG)UserBuffer != BufferTerminator)
{
KernelBuffer[Count] = *(PULONG)UserBuffer;
UserBuffer = (PULONG)UserBuffer + ;
Count++;
}
else
{
break;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
DbgPrint("[-] Exception Code: 0x%X\n", Status);
}
return Status;
}

函数中比较了用户提交缓冲区长度和内核缓冲区长度,在有漏洞的版本中,这一比较采用了:

if ((Size + TerminatorSize) > sizeof(KernelBuffer))
TerminatorSize为4字节,当用户传过来的缓冲区大小为0xfffffffc~0xffffffff时,假发之后结果溢出,并且巧妙地通过了长度检查!
在Powershell中,我们可以清晰地看到这一问题。

我们在Windbg中同样可以看到这一问题:

97c4ba9f 8b450c          mov     eax,dword ptr [ebp+0Ch]
97c4baa2 0345d4 add eax,dword ptr [ebp-2Ch]
97c4baa5 3d00080000 cmp eax,800h kd> r eax
eax=
检查完之后,则进入循环,将用户缓冲区的数据拷贝到内核缓冲区。当内核地址不等于缓冲区结束标志0xBAD0B0B0时,拷贝数据。
在拷贝数据前,查看寄存器,当前ebp为0x9398fab0,查看内存,得知当前返回地址为0x9398fab0。
kd> r
eax= ebx= ecx=ffffffff edx=0000004d esi=86e61528 edi=860fff80
eip=97c80adb esp=9398f268 ebp=9398fab0 iopl= nv up ei ng nz na pe cy
cs= ss= ds= es= fs= gs= efl=
HEVD!TriggerIntegerOverflow+0x16b:
97c80adb 8b450c mov eax,dword ptr [ebp+0Ch] ss::9398fabc=ffffffff
kd> dd 9398fab0
9398fab0 9398fad4 97c80956 ffffffff
9398fac0 c0000001 ffffffff
9398fad0 9398fafc 97c800ae 86e6a870
9398fae0 86e6a8e0
9398faf0 c00000bb 86e6a8e0 9398fb14
9398fb00 83e7f593 86e61528 86e6a870 86e6a870
9398fb10 86e61528 9398fb34 8407399f 860fff80
9398fb20 86e6a870 86e6a8e0 0498fbac

0x02 漏洞利用

利用防方法与之前无二,主要是覆盖函数返回地址。
但是亲自测试过后,感觉函数内存结构与我们所构想的有所区别:

上面为覆盖前内核内存,红色为ebp地址,后面的0x97c5a956为返回地址,可以看到,覆盖后的内存并没有修改到返回地址,那么是怎么利用的呢?这让我很费解。
仔细想了一下,应该是VS编译器的原因,导致堆栈数据之间有保护间隙,所以实际的内存情况与我们所构造的并不一致。整个的利用思路和栈溢出是类似的。
使用HackSys Team发布的Release第二版,测试一哈,可以看到,此时提权利用是可以成功的。

0x03 漏洞反思

尽管利用的过程不太顺利,但是就原理来讲,参照安全版本,我们可以预估数据大小的情况下,如果传入数据较大,有可能向上溢出时,我们采用减法判断,类似的如果可能向下溢出,则我们采用加法判断。
当然了,如果无法判断大小那应该进行更为周密的考虑。

0x04 链接

[04] HEVD 内核漏洞之IntegerOverflow的更多相关文章

  1. [02] HEVD 内核漏洞之栈溢出

    作者:huity出处:http://www.cnblogs.com/huity35/版权:本文版权归作者所有.文章在看雪.博客园.个人博客同时发布.转载:欢迎转载,但未经作者同意,必须保留此段声明:必 ...

  2. [03] HEVD 内核漏洞之UAF

    作者:huity出处:https://www.cnblogs.com/huity35/p/11240997.html版权:本文版权归作者所有.文章在博客园.个人博客同时发布.转载:欢迎转载,但未经作者 ...

  3. 内核漏洞学习—熟悉HEVD

    一直以来内核漏洞安全给很多人的印象就是:难,枯燥.但是内核安全是否掌握是衡量一个系统安全工程师水平的标准之一,也是安全从业人员都应该掌握的基本功.本文通过详细的实例带领读者走进内核安全的大门.难度系数 ...

  4. 【翻译】 Windows 内核漏洞学习—空指针解引用

    Windows Kernel Exploitation – NullPointer Dereference 原文地址:https://osandamalith.com/2017/06/22/windo ...

  5. Windows 内核漏洞学习—空指针解引用

    原标题:Windows Kernel Exploitation – NullPointer Dereference 原文地址:https://osandamalith.com/2017/06/22/w ...

  6. CVE-2014-0038内核漏洞原理与本地提权利用代码实现分析 作者:seteuid0

    关键字:CVE-2014-0038,内核漏洞,POC,利用代码,本地提权,提权,exploit,cve analysis, privilege escalation, cve, kernel vuln ...

  7. Android内核漏洞利用技术实战:环境搭建&栈溢出实战

    前言 Android的内核采用的是 Linux 内核,所以在Android内核中进行漏洞利用其实和在 一般的 x86平台下的 linux 内核中进行利用差不多.主要区别在于 Android 下使用的是 ...

  8. Linux kernel pwn notes(内核漏洞利用学习)

    前言 对这段时间学习的 linux 内核中的一些简单的利用技术做一个记录,如有差错,请见谅. 相关的文件 https://gitee.com/hac425/kernel_ctf 相关引用已在文中进行了 ...

  9. 初识linux内核漏洞利用

    0x00 简介 之前只接触过应用层的漏洞利用, 这次第一次接触到内核层次的,小结一下. 0x01 概况 这次接触到的,是吾爱破解挑战赛里的一个题,给了一个有问题的驱动程序,要求在ubuntu 14.0 ...

随机推荐

  1. /etc/vsftpd/vsftpd.conf

    # Example config file /etc/vsftpd/vsftpd.conf## The default compiled in settings are fairly paranoid ...

  2. Java开发桌面程序学习(九)——JavaFxTemplate JavaFx模版 更简单进行JavaFx程序开发

    JavaFxTemplate 使用说明 项目基于maven,请确保maven配置成功,否则,可能会出现问题 项目内置了commons-io的jar包,Jfoenix的jar包以及常用的工具类JFxUt ...

  3. abp(net core)+easyui+efcore仓储系统——展现层实现增删改查之控制器(六)

    abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...

  4. 如何使用Vue.js来搭建一个后台管理系统

    目录 使用的技术 基础但不好版 1.初始化项目 2.实现初始页内容自定义 3.使用路由 原始代码 自建页面 修改路由 4.测试路由跳转 补充 子路由版 嵌套router-view 定义子路由 修改菜单 ...

  5. uint16,uint32是什么?

    记得之前在刷笔试题的时候就看见过这个问题,发现当时上网百度后又忘了. 最近在看CryEngine3引擎代码的时候又晕了,趁现在赶紧记下来~ 在查看CE3的代码时我发现了这个变量,TFlowNodeId ...

  6. Mybatis_three

    延迟加载 实现多对一的延迟加载(association) 例如下面的:有很多个账户信息(招商\工商\农商)是属于一个用户人的 [需求] 查询账户(Account)信息并且关联查询用户(User)信息. ...

  7. 【入门】WebRTC知识点概览 | 内有技术干货免费下载

    什么是WebRTC WebRTC 即Web Real-Time Communication(网页实时通信)的缩写,是一个支持网页浏览器之间进行实时数据传输(包括音频.视频.数据流)的技术.经过多年的发 ...

  8. spark 源码分析之二 -- SparkContext 的初始化过程

    创建或使用现有Session 从Spark 2.0 开始,引入了 SparkSession的概念,创建或使用已有的session 代码如下: val spark = SparkSession .bui ...

  9. git的基本指令

    更多详情请看廖雪峰官方网站 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 1.删 ...

  10. PATB 1004 成绩排名 (20)

    1004. 成绩排名 (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 读入n名学生的姓名.学号.成绩,分 ...