Title : W32dsm v8.93漏洞可利用性分析
Author : XCyber
e-mail : XCyber@sohu.com
Date : 2005-01-28
最近的W32dsm v8.93漏洞:
"The program uses the wsprintf() function to copy the name of the
imported/exported functions of the analyzed file into a buffer of only
256 bytes, with the possibility for an attacker to execute malicious
code."
http://marc.theaimsgroup.com/?l=bugtraq&m=110661194108205&w=2
验证了一下,W32dsm处理导入函数时确实存在栈溢出漏洞,但是很长的导入函数名会造成PE文件无效,所以用作Anti-W32dsm可能性不大。仔细
看看漏洞说明"imported/exported functions...",如果导出函数也有同样漏洞那就...嘻嘻...因为很长的导出函数名不会导致PE文件无效,
而且一般人也不会注意一个.exe文件的导出表,所以有利用价值。
废话少说,先分析一下W32dsm对导入/导出函数的处理。
W32dsm对导入函数处理的分析:
0045D805 |> \6A 00 ||push 0 ; /Origin = FILE_BEGIN
0045D807 |. 6A 00 ||push 0 ; |pOffsetHi = NULL
0045D809 |. 8B45 E0 ||mov eax,dword ptr ss:[ebp-20] ; |
0045D80C |. 8B55 EC ||mov edx,dword ptr ss:[ebp-14] ; |
0045D80F |. 03C2 ||add eax,edx ; |
0045D811 |. 8B4D FC ||mov ecx,dword ptr ss:[ebp-4] ; |
0045D814 |. 2BC1 ||sub eax,ecx ; |
0045D816 |. 50 ||push eax ; |OffsetLo
0045D817 |. FFB3 12596000 ||push dword ptr ds:[ebx+605912] ; |hFile
0045D81D |. E8 1E130500 ||call W32dsm8_.004AEB40 ; \SetFilePointer
0045D822 |. 6A 00 ||push 0 ; /pOverlapped = NULL
0045D824 |. 8D45 F4 ||lea eax,dword ptr ss:[ebp-C] ; |
0045D827 |. 50 ||push eax ; |pBytesRead
0045D828 |. 6A 02 ||push 2 ; |BytesToRead = 2
0045D82A |. 69D6 CEEA0200 ||imul edx,esi,2EACE ; |
0045D830 |. 03D3 ||add edx,ebx ; |
0045D832 |. 6BCF 5B ||imul ecx,edi,5B ; |
0045D835 |. 03D1 ||add edx,ecx ; |
0045D837 |. 81C2 F26A1700 ||add edx,176AF2 ; |
0045D83D |. 52 ||push edx ; |Buffer
0045D83E |. FFB3 12596000 ||push dword ptr ds:[ebx+605912] ; |hFile
0045D844 |. E8 CD120500 ||call W32dsm8_.004AEB16 ; \ReadFile 【1】:读入导入函数字符串的偏移
0045D849 |. 6A 00 ||push 0 ; /Origin = FILE_BEGIN
0045D84B |. 6A 00 ||push 0 ; |pOffsetHi = NULL
0045D84D |. 8B45 E0 ||mov eax,dword ptr ss:[ebp-20] ; |
0045D850 |. 8B55 EC ||mov edx,dword ptr ss:[ebp-14] ; |
0045D853 |. 03C2 ||add eax,edx ; |
0045D855 |. 8B4D FC ||mov ecx,dword ptr ss:[ebp-4] ; |
0045D858 |. 2BC1 ||sub eax,ecx ; |
0045D85A |. 83C0 02 ||add eax,2 ; |
0045D85D |. 50 ||push eax ; |OffsetLo
0045D85E |. FFB3 12596000 ||push dword ptr ds:[ebx+605912] ; |hFile
0045D864 |. E8 D7120500 ||call W32dsm8_.004AEB40 ; \SetFilePointer
0045D869 |. 6A 00 ||push 0 ; /pOverlapped = NULL
0045D86B |. 8D45 F4 ||lea eax,dword ptr ss:[ebp-C] ; |
0045D86E |. 50 ||push eax ; |pBytesRead
0045D86F |. 68 2C010000 ||push 12C ; |BytesToRead = 12C (300.)
0045D874 |. FFB3 A5726000 ||push dword ptr ds:[ebx+6072A5] ; |Buffer
0045D87A |. FFB3 12596000 ||push dword ptr ds:[ebx+605912] ; |hFile
0045D880 |. E8 91120500 ||call W32dsm8_.004AEB16 ; \ReadFile 【2】:从【1】得到的偏移开始,读入12C字节。注意是12c字节!
0045D885 |. FFB3 A5726000 ||push dword ptr ds:[ebx+6072A5] ; /String2
0045D88B |. 8D93 2B0A6400 ||lea edx,dword ptr ds:[ebx+640A2B] ; |
0045D891 |. 52 ||push edx ; |String1
0045D892 |. E8 C3130500 ||call W32dsm8_.004AEC5A ; \lstrcpyA
...
0045D8C8 |> 8D83 2B0A6400 ||lea eax,dword ptr ds:[ebx+640A2B]
0045D8CE |. 50 ||push eax ; /<%s>
0045D8CF |. 68 18384C00 ||push W32dsm8_.004C3818 ; |Format = "%s"
0045D8D4 |. 8D95 04FFFFFF ||lea edx,dword ptr ss:[ebp-FC] ; |
0045D8DA |. 52 ||push edx ; |s
0045D8DB |. E8 A0170500 ||call W32dsm8_.004AF080 ; \wsprintfA ★
注意wsprintfA函数的第一个参数,[ebp-F4],这是函数名字符串开始覆盖的地方,由于读入字符串最大是12C > FC,所以只要导入函数名
足够长就会产生栈溢出。
W32dsm对导出函数处理的分析:
0045DD72 |> /6A 00 /push 0 ; /Origin = FILE_BEGIN
0045DD74 |. |6A 00 |push 0 ; |pOffsetHi = NULL
0045DD76 |. |8B45 FC |mov eax,dword ptr ss:[ebp-4] ; |
0045DD79 |. |03C7 |add eax,edi ; |
0045DD7B |. |50 |push eax ; |OffsetLo
0045DD7C |. |FFB3 12596000 |push dword ptr ds:[ebx+605912] ; |hFile
0045DD82 |. |E8 B90D0500 |call W32dsm8_.004AEB40 ; \SetFilePointer
0045DD87 |. |6A 00 |push 0 ; /pOverlapped = NULL
0045DD89 |. |8D55 E4 |lea edx,dword ptr ss:[ebp-1C] ; |
0045DD8C |. |52 |push edx ; |pBytesRead
0045DD8D |. |6A 04 |push 4 ; |BytesToRead = 4
0045DD8F |. |8D4D F0 |lea ecx,dword ptr ss:[ebp-10] ; |
0045DD92 |. |51 |push ecx ; |Buffer = 006DBF1C
0045DD93 |. |FFB3 12596000 |push dword ptr ds:[ebx+605912] ; |hFile
0045DD99 |. |E8 780D0500 |call W32dsm8_.004AEB16 ; \ReadFile 【3】:读入导出函数字符串的偏移
0045DD9E |. |8B45 E4 |mov eax,dword ptr ss:[ebp-1C]
0045DDA1 |. |85C0 |test eax,eax
0045DDA3 |. |75 07 |jnz short W32dsm8_.0045DDAC
0045DDA5 |. |33C0 |xor eax,eax
0045DDA7 |. |E9 BB020000 |jmp W32dsm8_.0045E067
0045DDAC |> |83C7 04 |add edi,4
0045DDAF |. |8B93 DC376F00 |mov edx,dword ptr ds:[ebx+6F37DC]
0045DDB5 |. |2955 F0 |sub dword ptr ss:[ebp-10],edx
0045DDB8 |. |8B8B D8376F00 |mov ecx,dword ptr ds:[ebx+6F37D8]
0045DDBE |. |014D F0 |add dword ptr ss:[ebp-10],ecx
0045DDC1 |. |6A 00 |push 0 ; /Origin = FILE_BEGIN
0045DDC3 |. |6A 00 |push 0 ; |pOffsetHi = NULL
0045DDC5 |. |FF75 F0 |push dword ptr ss:[ebp-10] ; |OffsetLo
0045DDC8 |. |FFB3 12596000 |push dword ptr ds:[ebx+605912] ; |hFile
0045DDCE |. |E8 6D0D0500 |call W32dsm8_.004AEB40 ; \SetFilePointer
0045DDD3 |. |6A 00 |push 0 ; /pOverlapped = NULL
0045DDD5 |. |8D45 E4 |lea eax,dword ptr ss:[ebp-1C] ; |
0045DDD8 |. |50 |push eax ; |pBytesRead
0045DDD9 |. |6A 4F |push 4F ; |BytesToRead = 4F (79.)
0045DDDB |. |8D55 8C |lea edx,dword ptr ss:[ebp-74] ; |
0045DDDE |. |52 |push edx ; |Buffer
0045DDDF |. |FFB3 12596000 |push dword ptr ds:[ebx+605912] ; |hFile
0045DDE5 |. |E8 2C0D0500 |call W32dsm8_.004AEB16 ; \ReadFile 【4】:从【3】得到的偏移开始,读入4F字节
0045DDEA |. |8B4D E4 |mov ecx,dword ptr ss:[ebp-1C]
0045DDED |. |85C9 |test ecx,ecx
0045DDEF |. |75 07 |jnz short W32dsm8_.0045DDF8
0045DDF1 |. |33C0 |xor eax,eax
0045DDF3 |. |E9 6F020000 |jmp W32dsm8_.0045E067
0045DDF8 |> |C645 DB 00 |mov byte ptr ss:[ebp-25],0
0045DDFC |. |0FBE55 8C |movsx edx,byte ptr ss:[ebp-74]
0045DE00 |. |83FA 40 |cmp edx,40
0045DE03 |. |75 22 |jnz short W32dsm8_.0045DE27
0045DE05 |. |8B8B 74116F00 |mov ecx,dword ptr ds:[ebx+6F1174]
0045DE0B |. |85C9 |test ecx,ecx
0045DE0D |. |74 18 |je short W32dsm8_.0045DE27
0045DE0F |. |6A 01 |push 1
0045DE11 |. |8D85 3CFFFFFF |lea eax,dword ptr ss:[ebp-C4]
0045DE17 |. |50 |push eax
0045DE18 |. |8D55 8C |lea edx,dword ptr ss:[ebp-74]
0045DE1B |. |52 |push edx
0045DE1C |. |53 |push ebx
0045DE1D |. |E8 6F2C0000 |call W32dsm8_.00460A91
0045DE22 |. |83C4 10 |add esp,10
0045DE25 |. |EB 18 |jmp short W32dsm8_.0045DE3F
0045DE27 |> |8D4D 8C |lea ecx,dword ptr ss:[ebp-74]
0045DE2A |. |51 |push ecx ; /<%s>
0045DE2B |. |68 60384C00 |push W32dsm8_.004C3860 ; |Format = "%s"
0045DE30 |. |8D85 3CFFFFFF |lea eax,dword ptr ss:[ebp-C4] ; |
0045DE36 |. |50 |push eax ; |s
0045DE37 |. |E8 44120500 |call W32dsm8_.004AF080 ; \wsprintfA ★
注意wsprintfA函数的第一个参数,[ebp-C4],这是函数名字符串开始覆盖的地方,由于函数名最大只读入4F,无法覆盖到ebp-C4,
所以无法产生栈溢出。
结论:W32dsm只是在处理导入函数时有可能导致栈溢出,由于windows loader会对导入函数进行有效性判断,所以利用该漏洞设计
Anti-W32dsm可能不大。
水平有限,不对之处请指正。