缓冲区溢出分析第07课:MS06-040漏洞研究——静态分析
前言
我在之前的课程中讨论过W32Dasm这款软件中的漏洞分析与利用的方法,由于使用该软件的人群毕竟是小众群体,因此该漏洞的危害相对来说还是比较小的。但是如果漏洞出现在Windows系统中,那么情况就会很不一样了。毕竟Windows统治了全球九成以上的计算机操作系统,因此如果该系统中出现了漏洞,而这个漏洞又被别有用心者所利用,那么就必然会出现数以亿计的受害者。
MS06-040漏洞基本信息
这次我们讨论的漏洞是在2006年8月8日,由微软公布的MS06-040这个漏洞(https://technet.microsoft.com/en-us/library/security/ms06-040.aspx)。在微软的安全技术中心,可以看到关于这个漏洞的报告,它被定义为“严重”的级别:
图1
其实,微软的安全技术中心所公布的漏洞是所有安全工作者和黑客们最为感兴趣的地方。每当微软发布一个补丁,修复了一个漏洞,总会有许多的攻击者通宵达旦地去研究这些补丁都修补了哪些漏洞,并写出漏洞利用程序。因为在补丁刚刚发布的一段时间内并非所有用户都能及时修复,所以这种新公布的漏洞会很有利用价值。对于这些攻击者而言,虽说他们的行为很不光彩,但是他们这种去挖掘漏洞的毅力,还是值得钦佩的。毕竟微软的漏洞公告,仅仅给出了一个大概的方向,而漏洞的具体细节,比如漏洞出现在哪个函数,该如何利用这个漏洞等等细节,是根本就没有透露的。这就和之前我们讨论的W32Dasm的漏洞报告很不一样,后者已经具体到了一个特定的函数,因此我们只要找到究竟是哪个位置的函数出现了问题即可。而通过微软的漏洞报告,我们一般至多只能够知道漏洞出现在哪一个动态链接库中,具体到究竟是该动态链接库中的哪一个函数,就需要我们自己去寻找了。由于动态链接库中可能包含有众多的导出函数,所以很多时候定位漏洞出现的位置就如同大海捞针,是需要极大的耐心甚至还包含有运气成分的。
依据微软的漏洞报告,我们知道出现问题的是Netapi32.dll这个动态链接库:
图2
在该动态链接库中有一个名为NetpwPathCanonicalize()的导出函数:
图3
这个函数存在着缓冲区溢出的缺陷,也正是我们重点关注的对象。
静态分析漏洞出现的原因
既然已经知道了出现漏洞的函数,那么下一步可以使用IDA Pro来分析一下漏洞出现的原因。事实上,在NetpwPathCanonicalize()函数中有一个名为sub_7517FC68的函数,出现溢出隐患的正是在这个函数内部:
图4
下面就是对这个函数反汇编代码的分析:
- .text:7517FC68 ; Attributes: bp-based frame
- .text:7517FC68 ; int __stdcall sub_7517FC68(wchar_t *Source, wchar_t *Str, int, int, int)
- .text:7517FC68 sub_7517FC68 proc near ; CODE XREF: NetpwPathCanonicalize+74p
- .text:7517FC68 var_416 = word ptr -416h
- .text:7517FC68 Dest = word ptr -414h
- .text:7517FC68 Source = dword ptr 8
- .text:7517FC68 Str = dword ptr 0Ch
- .text:7517FC68 arg_8 = dword ptr 10h
- .text:7517FC68 arg_C = dword ptr 14h
- .text:7517FC68 arg_10 = dword ptr 18h
- ; 本函数中一共有五个参数和两个局部变量
- .text:7517FC68 push ebp
- .text:7517FC69 mov ebp, esp
- .text:7517FC6B sub esp, 414h
- ; 开辟0x414字节大小的空间,用于存放生成的字符串
- .text:7517FC71 push ebx
- .text:7517FC72 push esi
- .text:7517FC73 xor esi, esi
- .text:7517FC75 push edi
- .text:7517FC76 cmp [ebp+Source], esi
- ; 验证参数Source是否为0
- .text:7517FC79 mov edi, ds:__imp_wcslen
- .text:7517FC7F mov ebx, 411h
- ; 在本函数中,ebx的值不变,恒为0x411,用于检查是否越界
- .text:7517FC84 jz short loc_7517FCED
- ; 依据上面的Source与0的比较结果来判定是否跳转
- .text:7517FC86 push [ebp+Source] ; Str
- .text:7517FC89 call edi ; __imp_wcslen
- ; 计算参数Source的长度,注意这里是Unicode形式的长度
- .text:7517FC8B mov esi, eax
- ; esi保存的是参数Source的Unicode形式的长度
- .text:7517FC8D pop ecx
- .text:7517FC8E test esi, esi
- .text:7517FC90 jz short loc_7517FCF4
- ; 验证参数Source的长度是否为0
- .text:7517FC92 cmp esi, ebx
- ; 验证参数Source的长度是否大于0x411
- .text:7517FC94 ja loc_7517FD3E
- ; 如果大于,则退出程序
- .text:7517FC9A push [ebp+Source] ; Source
- .text:7517FC9D lea eax, [ebp+Dest]
- .text:7517FCA3 push eax ; Dest
- .text:7517FCA4 call ds:__imp_wcscpy
- ; 将参数Source字符串拷贝到新分配的空间中。需要注意的是,这里开辟的是0x414字节的空间,
- ; 但是上述代码检测的却是宽字符,宽字符的0x411相当于0x822字节的空间。看似这是可以
- ; 利用的漏洞,但是在本函数调用之前,程序已经使用了NetpwPathType()函数用于检测参
- ; 数Source的长度,使其不能超过0x206个字节,因此这里是不能被当做漏洞利用的。
- .text:7517FCAA mov ax, [ebp+esi*2+var_416]
- ; 取出字符,检查是否为斜杠
- .text:7517FCB2 pop ecx
- .text:7517FCB3 cmp ax, 5Ch ; 0x5C表示的是“\”
- .text:7517FCB7 pop ecx
- .text:7517FCB8 jz short loc_7517FCD5
- .text:7517FCBA cmp ax, 2Fh ; 0x2F表示的是“/”
- .text:7517FCBE jz short loc_7517FCD5
- .text:7517FCC0 lea eax, [ebp+Dest]
- .text:7517FCC6 push offset asc_751717B8 ; "\\"
- .text:7517FCCB push eax ; Dest
- .text:7517FCCC call ds:__imp_wcscat
- ; 将斜杠与字符串进行连接
- .text:7517FCD2 pop ecx
- .text:7517FCD3 inc esi
- ; 由于加入了斜杠,所以字符串的长度增加1
- .text:7517FCD4 pop ecx
- .text:7517FCD5
- .text:7517FCD5 loc_7517FCD5: ; CODE XREF: sub_7517FC68+50j
- .text:7517FCD5 ; sub_7517FC68+56j
- .text:7517FCD5 mov eax, [ebp+Str]
- .text:7517FCD8 mov ax, [eax]
- .text:7517FCDB cmp ax, 5Ch ; 0x5C表示的是“\”
- .text:7517FCDF jz short loc_7517FCE7
- .text:7517FCE1 cmp ax, 2Fh ; 0x2F表示的是“/”
- .text:7517FCE5 jnz short loc_7517FCF4
- .text:7517FCE7
- .text:7517FCE7 loc_7517FCE7: ; CODE XREF: sub_7517FC68+77j
- .text:7517FCE7 add [ebp+Str], 2
- .text:7517FCEB jmp short loc_7517FCF4
- .text:7517FCED ; ------------------------------------------------------------
- .text:7517FCED loc_7517FCED: ; CODE XREF: sub_7517FC68+1Cj
- .text:7517FCED mov [ebp+Dest], si
- .text:7517FCF4
- .text:7517FCF4 loc_7517FCF4: ; CODE XREF: sub_7517FC68+28j
- .text:7517FCF4 ; sub_7517FC68+7Dj ...
- .text:7517FCF4 push [ebp+Str] ; Str
- .text:7517FCF7 call edi ; __imp_wcslen
- ; 计算参数Str的长度,注意这里是Unicode形式的长度
- .text:7517FCF9 add eax, esi
- ; 这里计算的是加上了斜杠的参数Source与Str长度的总和,该长度保存在eax中
- .text:7517FCFB pop ecx
- .text:7517FCFC cmp eax, ebx
- .text:7517FCFE ja short loc_7517FD3E
- ; 对连接后的字符串长度进行检查,经过之前的分析可以知道,仅仅依靠参数Source是不能够
- ; 实现漏洞的利用的,因为它的长度被限定在了0x206个字节,但是程序并没有对参数Str的
- ; 长度进行足够的限定,利用这一点就可以实现漏洞的利用。
- .text:7517FD00 push [ebp+Str] ; Source
- .text:7517FD03 lea eax, [ebp+Dest]
- .text:7517FD09 push eax ; Dest
- .text:7517FD0A call ds:__imp_wcscat
- ; 字符串连接,将参数Str连接到缓冲区中,也正是这个函数,导致了缓冲区的溢出
- .text:7517FD10 pop ecx
- .text:7517FD11 lea eax, [ebp+Dest]
- .text:7517FD17 pop ecx
- .text:7517FD18 push eax
- .text:7517FD19 call sub_7518AE95
- .text:7517FD1E lea eax, [ebp+Dest]
- .text:7517FD24 push eax ; Str
- .text:7517FD25 call sub_7518AEB3
- .text:7517FD2A test eax, eax
- .text:7517FD2C jnz short loc_7517FD43
- .text:7517FD2E lea eax, [ebp+Dest]
- .text:7517FD34 push eax
- .text:7517FD35 call sub_7518AFE2
- .text:7517FD3A test eax, eax
- .text:7517FD3C jnz short loc_7517FD43
- .text:7517FD3E
- .text:7517FD3E loc_7517FD3E: ; CODE XREF: sub_7517FC68+2Cj
- .text:7517FD3E ; sub_7517FC68+96j
- .text:7517FD3E push 7Bh
- .text:7517FD40 pop eax
- .text:7517FD41 jmp short loc_7517FD7A
- .text:7517FD43 ; ------------------------------------------------------------
- .text:7517FD43 loc_7517FD43: ; CODE XREF: sub_7517FC68+C4j
- .text:7517FD43 ; sub_7517FC68+D4j
- .text:7517FD43 lea eax, [ebp+Dest]
- .text:7517FD49 push eax ; Str
- .text:7517FD4A call edi ; __imp_wcslen
- .text:7517FD4C lea eax, [eax+eax+2]
- .text:7517FD50 pop ecx
- .text:7517FD51 cmp eax, [ebp+arg_C]
- .text:7517FD54 jbe short loc_7517FD66
- .text:7517FD56 mov ecx, [ebp+arg_10]
- .text:7517FD59 test ecx, ecx
- .text:7517FD5B jz short loc_7517FD5F
- .text:7517FD5D mov [ecx], eax
- .text:7517FD5F
- .text:7517FD5F loc_7517FD5F: ; CODE XREF: sub_7517FC68+F3j
- .text:7517FD5F mov eax, 84Bh
- .text:7517FD64 jmp short loc_7517FD7A
- .text:7517FD66 ; ------------------------------------------------------------
- .text:7517FD66 loc_7517FD66: ; CODE XREF: sub_7517FC68+ECj
- .text:7517FD66 lea eax, [ebp+Dest]
- .text:7517FD6C push eax ; Source
- .text:7517FD6D push [ebp+arg_8] ; Dest
- .text:7517FD70 call ds:__imp_wcscpy
- .text:7517FD76 pop ecx
- .text:7517FD77 xor eax, eax
- .text:7517FD79 pop ecx
- .text:7517FD7A
- .text:7517FD7A loc_7517FD7A: ; CODE XREF: sub_7517FC68+D9j
- .text:7517FD7A ; sub_7517FC68+FCj
- .text:7517FD7A pop edi
- .text:7517FD7B pop esi
- .text:7517FD7C pop ebx
- .text:7517FD7D leave
- .text:7517FD7E retn 14h
- .text:7517FD7E sub_7517FC68 endp
- .text:7517FD7E
如上所述,程序对字符串的长度限定是unicode的0x411个字符,也就是0x822个字节,而程序仅仅分配了0x414个字节的空间,于是就出现了缓冲区溢出的隐患。
对于函数sub_7517FC68而言,它有两个参数是需要我们特别留意的,一个是Source,另一个是Str。由于前者已经被限定了长度,最多只能0x206个字节,所以我们只能拿后者做文章。那么这两个参数在NetpwPathCanonicalize()函数中是什么形态呢?经过分析可知,Str这个参数正是NetpwPathCanonicalize()函数的第一个参数,而Source则是第四个参数:
也就是说,我们可以构造一个程序,让它加载Netapi32.dll这个动态链接库,并调用其中的NetpwPathCanonicalize()函数,精心构造这个函数的第一和第四个参数的内容,那么就可以实现漏洞的利用了。
函数NetpwPathCanonicalize()说明
其实经过上述分析,我们就可以知道NetpwPathCanonicalize()函数的大概功能了。其实关于这个函数,微软是没有给我们任何介绍的,现在对于这个函数功能的讲解,都是前辈们通过类似于我们上述的逆向分析而总结出来的。由此可见,逆向工程确实是计算机领域中最富挑战性的工作之一。
函数NetpwPathCanonicalize()用于格式化网络路径字符串,其定义如下:
- void NetpwPathCanonicalize(
- _in_ dword Str, // +8h
- _out_ dword lpWideCharStr, // +0Ch
- _in_ dword arg_8, // +10h
- _in_ dword Source, // +14h
- _in_out_ dword arg_10, // +18h
- _in_ dword arg_14 // +1Ch
- );
参数说明:
Str:指向Unicode字串的指针,用于生成路径字串的第二部分。
lpWideCharStr:指向buffer的指针,用于接收格式化后的字符串。
arg_8:表明lpWideCharStr的大小
Source:指向Unicode字串的指针,用于生成路径字串的第一部分。
arg_10:指向long的指针。
arg_14:标志位,一般为0。
函数的功能是把Source指的字符串,加上‘\’,再加上Str指的字符串,放在lpWideCharStr的buffer里。即
Source+ ‘\’ + Str => lpWideCharStr[arg_8]
小结
经过上述一系列的分析,我们已经弄清楚了漏洞出现的原因以及利用方法。那么对于这个漏洞的实际利用,我会在下一次的讲解中,结合动态调试,编程实现。
缓冲区溢出分析第07课:MS06-040漏洞研究——静态分析的更多相关文章
- 缓冲区溢出分析第09课:MS06-040漏洞研究——深入挖掘
前言 经过前两次的分析,我们已经对Netapi32.dll文件中所包含的漏洞成功地实现了利用.在系统未打补丁之前,这确实是一个非常严重的漏洞,那么打了补丁之后,这个动态链接库是不是就安全了呢?答案是否 ...
- 缓冲区溢出分析第08课:MS06-040漏洞研究——动态调试
前言 经过上次的分析,我们已经知道了MS06-040漏洞的本质,那么这次我们就通过编程实现漏洞的利用. 编写漏洞利用程序的框架 这里我使用的是VC++6.0进行编写,需要将包含有漏洞的netapi32 ...
- 缓冲区溢出分析第06课:W32Dasm缓冲区溢出分析
漏洞报告分析 学习过破解的朋友一定听说过W32Dasm这款逆向分析工具.它是一个静态反汇编工具,在IDA Pro流行之前,是破解界人士必然要学会使用的工具之一,它也被比作破解界的"屠龙刀&q ...
- 缓冲区溢出分析第10课:Winamp缓冲区溢出研究
前言 Winamp是一款非常经典的音乐播放软件,它于上世纪九十年代后期问世.与现在音乐播放软件行业百家争鸣的情况不同,当时可以说Winamp就是听音乐的唯一选择了,相信那个时代的电脑玩家是深有体会的. ...
- 缓冲区溢出分析第05课:编写通用的ShellCode
前言 我们这次的实验所要研究的是如何编写通用的ShellCode.可能大家会有疑惑,我们上次所编写的ShellCode已经能够很好地完成任务,哪里不通用了呢?其实这就是因为我们上次所编写的ShellC ...
- 缓冲区溢出分析第04课:ShellCode的编写
前言 ShellCode究竟是什么呢,其实它就是一些编译好的机器码,将这些机器码作为数据输入,然后通过我们之前所讲的方式来执行ShellCode,这就是缓冲区溢出利用的基本原理.那么下面我们就来编写S ...
- W32Dasm缓冲区溢出分析【转载】
课程简介 在上次课程中与大家一起学习了编写通用的Shellcode,也提到会用一个实例来展示Shellcode的溢出. 那么本次课程中为大家准备了W32Dasm这款软件,并且是存在漏洞的版本.利用它的 ...
- CVE2016-8863libupnp缓冲区溢出漏洞原理分析及Poc
1.libupnp问题分析: (1)问题简述: 根据客户给出的报告,通过设备安装的libupnp软件版本来判断,存在缓冲区溢出漏洞:CVE-2016-8863. (2)漏洞原理分析: 该漏洞发生在up ...
- CVE-2011-0104 Microsoft Office Excel缓冲区溢出漏洞 分析
漏洞简述 Microsoft Excel是Microsoft Office组件之一,是流行的电子表格处理软件. Microsoft Excel中存在缓冲区溢出漏洞,远程攻击者可利用此 ...
随机推荐
- 剑指 Offer 12. 矩阵中的路径 + 递归 + 深搜 + 字符串问题
剑指 Offer 12. 矩阵中的路径 题目链接 题目类似于迷宫的搜索. 需要注意的是,需要首先判断起始搜索的位置,可能有多个起点,都需要一一尝试. 每轮迭代的时候记得将是否遍历标记数组还原为未遍历的 ...
- HDOJ-2087(KMP算法)
剪花布条 HDOJ-2087 本题和hdoj-1686相似,唯一不同的是这里的子串一定要是单独的.所以在确定有多少个子串时不能用前面的方法.而是在循环时,只要找到一个子串,i就不是++,而是+=子串的 ...
- 面试准备——计算机网络(https)
一.为什么要提出HTTPS? HTTP的缺点: 明文通信.不加密,可能被窃听. 无身份验证,可能遭遇伪装. 无法证明报文的完整性,可能被篡改. 二.HTTPS = HTTP+加密(防窃听)+认证(防伪 ...
- 如何快速的插入 100W数据到数据库,使用PreparedStatement 最快实现!
有时候,我们使用数据库的时候,如何快速的添加测试数据到数据库中,做测试呢,添加100W 数据,如果使用工具的话可能很慢,这里我推荐大家使用 PreparedStatement 预编译 去进行操作:单线 ...
- golang 并发运算时主线程先运行完,子线程运行没结束的问题记录
代码如下: blocks,err:= mgo.FindBlocks(batch) //获得当前批次下的矿体信息 cubes:= BlockCutting(blocks[0],x,y,z,nest) f ...
- TextRank算法及生产文本摘要方法介绍
TextRank 算法是一种用于文本的基于图的排序算法,其基本思想来源于谷歌的 PageRank算法,通过把文本分割成若干组成单元(句子),构建节点连接图,用句子之间的相似度作为边的权重,通过循环迭代 ...
- N皇后求解。万万没想到,只用一个一维数组就搞定了。还体现了回溯。
一.啥是N皇后?先从四皇后入手 给定一个4x4的棋盘,要在棋盘上放置4个皇后.他们的位置有这样的要求,每一列,每一行,每一对角线都能有一个皇后. 你可能会对这个对角线有疑惑,其实就是每一个小正方形的对 ...
- UML第二部分和创建型模式
状态机视图通过对每个类的对象的生命期进行建模 描述了对象时间上的动态行为 .状态指就某个特定类而言 对于发生的事件具有相同性质响应的一系列对象值.状态机不但可以描述类的行为 而且可以描述用例 协作和方 ...
- 热更新基础--AssetBundle学习笔记
一.简介 AssetBundle简称AB包,特定平台的资产压缩包(包括模型.贴图.预设体.音效.材质球等资产). 作用:Resources下的资源只读且打包后不可修改,而AB包存储位置自定,后期可以动 ...
- PhpStorm/WebStorm实用技巧
我常用的IDE设置和功能 1) 使用IDE管理远程主机 Tools -> Deployment -> Browse Remote Host 其中功能十分强大 自己去探索 关键提示: 手动/ ...