MS06-040
MS06-040
跟着https://bbs.pediy.com/thread-73878-1.htm上的深入浅出ms60-040学习
分析环境
- Windows2K sp4补丁前 NETAPI32.DLL
- IDA7.0
分析过程
把NETAPI32.DLL丢进IDA,在Exports中找到NetpwPathCanonicalize,双进后进入IDA-View A,按空格以流程图形式显示
IDA流程图中有线的部分代表有比较,以不同颜色区分
- 红-No
- 绿-Yes
- 蓝-顺序执行
代码执行顺序NetpwPathCanonicalize->NetpwPathType->CanonicalizePathName
在NetpwPathType中
会有cmp eax,103h,而ja跳转的条件为zf=0&cf=0,即若eax>103h则发生跳转,即字符串不超过103h才能正常运行。
后面分析CanonicalizePathName()函数,地址在.text:7517F856 call sub_7517FC68处,接下来在7517FC68处
.text:7517FC68
.text:7517FC68 ; =============== S U B R O U T I N E =======================================
.text:7517FC68
.text:7517FC68 ; Attributes: bp-based frame
.text:7517FC68
.text:7517FC68 ; int __stdcall sub_7517FC68(wchar_t *Str, wchar_t *Source, wchar_t *, int, int)
.text:7517FC68 sub_7517FC68 proc near ; CODE XREF: NetpwPathCanonicalize+74↑p
.text:7517FC68
.text:7517FC68 var_416 = word ptr -416h
.text:7517FC68 Dest = word ptr -414h
.text:7517FC68 Str = dword ptr 8
.text:7517FC68 Source = 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
.text:7517FC68 push ebp
.text:7517FC69 mov ebp, esp
.text:7517FC6B sub esp, 414h ; 开辟栈内空间,用于暂存生存的字符串
.text:7517FC71 push ebx
.text:7517FC72 push esi
.text:7517FC73 xor esi, esi
.text:7517FC75 push edi
.text:7517FC76 cmp [ebp+Str], esi //比较4号串地址是否为空
.text:7517FC79 mov edi, ds:__imp_wcslen
.text:7517FC7F mov ebx, 411h
.text:7517FC84 jz short loc_7517FCED
.text:7517FC86 push [ebp+Str] ; Str // 压入4号串
.text:7517FC89 call edi ; __imp_wcslen //, 计算4号串的Unicode长度,注意为字节长度
; 的一半这是导致边界检查被突破的主要原因
;即用Unicode检查边界,而栈空间是按字节开的
;wcslen()求宽字符集长度
.text:7517FC8B mov esi, eax
.text:7517FC8D pop ecx
.text:7517FC8E test esi, esi
.text:7517FC90 jz short loc_7517FCF4
.text:7517FC92 cmp esi, ebx
.text:7517FC94 ja loc_7517FD3E ;若程序越界则退出程序
.text:7517FC9A push [ebp+Str] ; Source
.text:7517FC9D lea eax, [ebp+Dest]
.text:7517FCA3 push eax ; Dest
.text:7517FCA4 call ds:__imp_wcscpy ;将4号串拷入栈中暂存串。虽然前面的边界检查有
;缺陷乎传入的4号串可以到0x822字节,但是4 ;号串在传入本函数被NetpwPathType()提前检查过,按
;照前面的分析知道4号串长度不超过0x206字节,所以
;光靠这里的检查缺陷不足以通过4号串制造栈溢出
.text:7517FCAA mov ax, [ebp+esi*2+var_416] ; 取出4号串的最后两个字节,检查是否 ;是斜杠
.text:7517FCB2 pop ecx
.text:7517FCB3 cmp ax, 5Ch ; '\'
.text:7517FCB7 pop ecx
.text:7517FCB8 jz short loc_7517FCD5
.text:7517FCBA cmp ax, 2Fh ; '/'
.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
.text:7517FCD4 pop ecx
.text:7517FCD5
.text:7517FCD5 loc_7517FCD5: ; CODE XREF: sub_7517FC68+50↑j
.text:7517FCD5 ; sub_7517FC68+56↑j
.text:7517FCD5 mov eax, [ebp+Source]
.text:7517FCD8 mov ax, [eax]
.text:7517FCDB cmp ax, 5Ch ; '\'
.text:7517FCDF jz short loc_7517FCE7
.text:7517FCE1 cmp ax, 2Fh ; '/'
.text:7517FCE5 jnz short loc_7517FCF4
.text:7517FCE7
.text:7517FCE7 loc_7517FCE7: ; CODE XREF: sub_7517FC68+77↑j
.text:7517FCE7 add [ebp+Source], 2
.text:7517FCEB jmp short loc_7517FCF4
.text:7517FCED ; ---------------------------------------------------------------------------
.text:7517FCED
.text:7517FCED loc_7517FCED: ; CODE XREF: sub_7517FC68+1C↑j
.text:7517FCED mov [ebp+Dest], si
.text:7517FCF4
.text:7517FCF4 loc_7517FCF4: ; CODE XREF: sub_7517FC68+28↑j
.text:7517FCF4 ; sub_7517FC68+7D↑j ...
.text:7517FCF4 push [ebp+Source] ; Str1号串地址
.text:7517FCF7 call edi ; __imp_wcslen
.text:7517FCF9 add eax, esi
.text:7517FCFB pop ecx
.text:7517FCFC cmp eax, ebx
.text:7517FCFE ja short loc_7517FD3E ;一号串没有做边界检查,可以做栈溢出
.text:7517FD00 push [ebp+Source] ; Source
.text:7517FD03 lea eax, [ebp+Dest]
.text:7517FD09 push eax ; Dest
.text:7517FD0A call ds:__imp_wcscat
.text:7517FD10 pop ecx
总结原因
漏洞产生原因在于1号串没有做边界检查,造成的栈溢出,前面各种检查都是针对的四号串
整个函数作用在于将1号串与4号串,用'\'等字符串连接
----vincebye---