0% found this document useful (0 votes)
76 views7 pages

Analysis of ANI "Anih" Header Stack Overflow Vulnerability, Microsoft Security Advisory 935423

The document analyzes a stack overflow vulnerability in Microsoft's handling of ANI files that can be exploited by malicious files. It finds that user32.dll loads ANI files using a function that has a static buffer on the stack to hold ANI header data, but takes the header size from the file itself without validation. A specially crafted ANI file can set the header size larger than the buffer, overwriting the return address to redirect execution to embedded shellcode and allowing remote code execution. The vulnerability was located by debugging the loading of a malicious ANI file and tracing back the execution.

Uploaded by

manishkulhari
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
76 views7 pages

Analysis of ANI "Anih" Header Stack Overflow Vulnerability, Microsoft Security Advisory 935423

The document analyzes a stack overflow vulnerability in Microsoft's handling of ANI files that can be exploited by malicious files. It finds that user32.dll loads ANI files using a function that has a static buffer on the stack to hold ANI header data, but takes the header size from the file itself without validation. A specially crafted ANI file can set the header size larger than the buffer, overwriting the return address to redirect execution to embedded shellcode and allowing remote code execution. The vulnerability was located by debugging the loading of a malicious ANI file and tracing back the execution.

Uploaded by

manishkulhari
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Analysis of ANI “anih” Header

Stack Overflow Vulnerability,


Microsoft Security Advisory 935423

With help from Andre (Dre) and


various other members of mal-aware
This is a really, really rough explanation of the exploit and the actions performed to
research the vulnerability.

There are several malicious ANI files in circulation. The one to discuss is mm.jpg from
newasp, but others are likely very similar. Shellcode in mm.jpg basically resolves
kernel32 functions, downloads, and executes xx.exe (from behavioral analysis). It doesn’t
do much but delete the system’s HOSTS file, write bdscheca001.dll to %SYSTEM%, and
registers the DLL as ShellExecuteHooks entry.

This means whenever a process calls ShellExecute() or ShellExecuteEx(), the new DLL
will be loaded into that process’ address space and its startup routine will be executed. So
practically everything is going to call one of these two functions eventually. It will result
in all processes being trojanized. Here is a view of the xx.exe sections (who is MrOwen?)
and the hooked process list.
Anyway, the point is to find the vulnerability, not analyze the payload, so I have no idea
what bdscheca001.dll does. While waiting on a few things, we looked in the mm.jpg at
the shellcode. It’s pretty obvious where it starts in the file – it starts around 0xA8.

So do a little translation with IDA and now we know that it just resolves Kernel32
exports. Most important, it finds GlobalAlloc() before any others, and allocates 0x300
bytes of memory.

So, now we have a good start. Opening IE in a debugger, a breakpoint is set on


GlobalAlloc(). Now we can access the HTML file that loads the malicious cursor. There
are easier ways, like maybe setting 0xCC as the first byte at 0xA8 offset and catching a
break there, but as we will learn soon, this will really break things bad. There are about
30 calls to GlobalAlloc() that we just have to play past until eventually we encounter one
where the memory size argument is 0x300, just like in the shellcode. This isn’t foolproof
(maybe other calls allocate 0x300 bytes, but in our case, the first encounter is the correct
one.

If we “execute until return” once inside GlobalAlloc(), our EIP ends up on the heap. The
question is – how did we get here…why is EIP on the heap. If we look down on the
stack, some return addresses are inside user32.dll.
So let’s see what is at this address inside user32.dll:

Basically, there is a call [ebx+4] right before the return address we know. So this
indicates that EIP was at this call sometime close before it got redirected to the heap. My
first assumption is that the vulnerability is inside _MLLine or inside the parent function.
But, putting breakpoints on either function fails, and the whole exploit still works. So
strangely, this means that somehow EIP ends up at the call [ebx+4], in the middle of the
function, without ever starting at the beginning of the parent function.

From here, we back-traced a little to return addresses further down on the stack and found
the point where user32.dll opens our mm.jpg and reads it using MapViewOfFile(). It
happens inside the RtlLoadObjectFromDIBFile() function. We can confirm, because after
mapping the file, it checks the headers of the alleged ANI file. If the header is valid, it
goes on to call LoadCursorIconFromFileMap().
Its important to note that jumping over the LoadCursorIconFromFileMap() function from
within RtlLoadObjectFromDIBFile() will execute the exploit. This is good verification
though that the vulnerability is getting closer – now we know it exists inside
LoadCursorIconFromFileMap() and not some other function that
RtlLoadObjectFromDIBFile() calls.

With a little more back-trace, we can narrow it down even further. It turns out that
LoadCursorIconFromFileMap() calls a sub function too (several, actually) called
LoadAniIcon(). Check out the state of things right before the call to this sub function.
Notice how the next instruction after the call is 0x77D842C5. This *should* be the return
address when LoadAniIcon() finishes.

Just for a sanity check, step inside the function and see what is pushed on the stack:

Yep, we should return to 0x77D842C5. Let’s fast forward a bit by using “execute until
return” and take another look at the stack.
So, the bottom 2 bytes of the return address is overwritten by something inside
LoadAniIcon(). We no longer will return to code in LoadCursorIconFromFileMap().
Instead, we go to 0x77D825BA, which is – guess what – the address of that call [ebx+4]
instruction. This is proof that sometimes when you can’t overwrite an arbitrary 4 bytes of
address to gain control, even an arbitrary 2 bytes will work. Now where did those bytes
come from, eh? We’re looking for a strict 0x25BA, or some value that is later added,
subtracted, multiplied, etc to turn into 0x25BA.

It’s easy this time, as the 0x25BA is right inside the malformed ANI file. Someone did
their homework and studied the addresses pretty well. I’m going to re-use the same
screen shot as the one above…can you spot the bytes?

Yep, they are the first two bytes of what we labeled as the shellcode before. At some
point in LoadAniIcon(), there is a copy or move function that allows these bytes to
overwrite some of the return address. Now look up in the screen shot where the image is
almost cut off (around 0x54 offset) and you will see “52 00 00 00” – which is right after
the “anih” header signature. This “52 00 00 00” is the size of the “anih” header chunk.
This value is 0x52 really or decimal 82 bytes. If you count, this 82 bytes starts right after
the size itself, which is at “30 31 32 33” and goes all the way to include the first two
bytes of the highlighted area (0xBA25).

So the vulnerability occurs because there is a statically-sized buffer on the stack to hold
an “anih” chunk, but it takes the size of the “anih” chunk from the malformed ANI file
itself, and doesn’t check to see if the specified size will fit. The malformed ANI we know
about says that the chunk size is 0x52 bytes and this is too big. The extra bytes overwrite
part of the LoadAniIcon() return address and force execution to a location with user32.dll
that calls [ebx+4]. Conveniently, [ebx+4] points to the start of shellcode contained within
mm.jpg (everything after the 0xBA25, start is highlighted below):
The fix for this is pretty easy, but not easy to detect. We’re basically looking for some
DWORD-sized value after an “anih” header that is larger than the buffer on the stack. All
for now.

You might also like