Application: Microsoft HTML Help
http://www.microsoft.com
Versions: <= 6.1
Platforms: Windows (any version included the latest Windows 7)
Bug: stack overflow
Date: 12 Apr 2011 (found 20 Feb 2011)
Author: Luigi Auriemma
e-mail: aluigi@autistici.org
web: aluigi.org
From http://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help:
"A CHM Help file name has a ".chm" extension. It has a set of web pages
written in a subset of HTML and a hyperlinked table of contents. CHM
format is optimized for reading, as files are heavily indexed. All
files are compressed together with LZX compression. Most CHM browsers
have the capability to display a table of contents outside of the body
text of the Help file."
itss.dll is affected by a stack overflow caused by the copying of an
arbitrary amount of data into a stack buffer during the decompression
of the content.
The following dump comes from the Windows XP 5.2.3790.2847 version:
The data that will be copied in this stack buffer is just one of the
decompressed LZX chunks (0x7ffe bytes) of the files embedded in the
input chm.
For reaching the vulnerable code I have modified the two dynamic
numbers after the "/#WINDOWS" tag setting the first to 0 (a value
smaller than the original) and the second to the amount of bytes to
copy, anyway note that the function is used also in other places.
Creating the malformed file from scratch is really a joke:
- get HTML Help Workshop
http://download.microsoft.com/download/0/a/9/0a939ef6-e31c-430f-a3df-dfae7960d564/htmlhelp.exe
- start HTML Help Workshop, create a new project and choose a name
- enable "HTML Help table of contents (.hhc)" and "HTML files (.htm)"
- select the provided test.hhc and then test.htm
- select the third button "Add/Modify window definitions", give a name
and then OK
- select File->Compile
- open the generated chm file with a hex editor
- search the text /#WINDOWS
- go after the 0x01 byte that follows it and place the bytes 00 ff 7f
I have noticed that it's a bit chaotic to debug this vulnerability
through an user-mode debugger, anyway without it attached the code
execution is correctly reported at the specified address of the
proof-of-concept (0x41414141) and our code is referenced in various
places ([ebp-c], [ebp-4], [ebp+c] and so on).
With the debugger attached is possible to see the new EIP only if it's
higher than 0x7fffffff otherwise it's necessary to guess the correct
16bit canary (destination+0x1c8) and specifying an amount of bytes that
will not be written over the available stack (like 00 83 7f) to see it.
The provided chm_1.chm proof-of-concept contains the address where will
continue the code execution at offset 0x17 of test.gif (set to
0x41414141, you can use any value because it's binary data) and I have
placed a bindshell (w32-bind-ngs-shellcode by SkyLined) at offset 0x200
of the same image file only as reference during my tests.
The folder build_chm_1 instead contains the original files from which
has been created chm_1.chm using the steps listed above.
本人就一大菜鸟,希望各位大牛看了愚见不要大笑-_-
pop pop pop ret的返回方法是利用SEH攻击跳入shellcode的常规办法。考察shellcode在堆栈上由于DEP的原因无法执行。而由于safeSEH,只能在nosafeSEH模块寻找指令序列。不知道我理解的对不对。
那么可以考察N pop ret指令序列,因为原来被利用来指向shellcode的地址无法使用,而shellcode就位于栈中该地址之后,可以选择更多的pop指令序列之后的ret,这样可以用我们选择的地址提供给ret指令。这个时候,由于指令序列在nosafeSEH中,所以绕过了safeSEH,而我们此时就可以通过ROP的方法来想办法绕过DEP。另外,这时LoadLibraryA的方法,也值得一试了。