A customer reported a problem with starting our application today. The error reported by our application was strange and was not one we’d encountered before:
Exception 'Exception' in module _________.exe at 004904CB
Unable to hook API functions for print preview [-1,-1,-1,0,0,0,0]
In effect the error told us that 4 out of 7 API hooks failed. I was called upon to try and diagnose the issue.
Initially I looked for a 3rd party application that could be hooking the calls in question (RegisterClassA
, RegisterClassW
, RegisterClassExA
, RegisterClassExW
). But there were no unusual applications running according to Process Explorer, and no unexpected DLLs in memory in the process. After disabling the antivirus in case that was causing the problem, and running both RootkitRevealer and Procmon with no clear outcomes, I decided I’d need to go deeper.
Time to break out windbg. I started our process and looked at the disassembly for one of the functions that failed to hook. Here’s what I saw:
0:000> u user32!registerclassexw
user32!RegisterClassExW:
7e41af7f 8bff mov edi,edi
7e41af81 55 push ebp
7e41af82 8bec mov ebp,esp
7e41af84 8b4508 mov eax,dword ptr [ebp+8]
7e41af87 833830 cmp dword ptr [eax],30h
7e41af8a 0f850be70200 jne user32!RegisterClassExW+0xd (7e44969b)
7e41af90 6800010000 push 100h
7e41af95 6a00 push 0
That’s pretty normal, the usual mov edi,edi that most Windows API calls start with, and what we were expecting. So I continued execution until the error occurred, and took another look at that point.
0:000> u user32!registerclassexw
user32!RegisterClassExW:
7e41af7f e9cc93d281 jmp 00144350
7e41af84 8b4508 mov eax,dword ptr [ebp+8]
7e41af87 833830 cmp dword ptr [eax],30h
7e41af8a 0f850be70200 jne user32!RegisterClassExW+0xd (7e44969b)
7e41af90 6800010000 push 100h
7e41af95 6a00 push 0
7e41af97 6a00 push 0
7e41af99 50 push eax
Huh, that’s kinda different. Now we were jumping off into a very unexpected part of memory. A quick check of that address revealed that it was not mapped into the normal address space of any modules. I had a look at the code in question.
0:000> u 144350 L...
00144350 55 push ebp
00144351 8bec mov ebp,esp
00144353 83ec30 sub esp,30h
00144356 f605e029150004 test byte ptr ds:[1529E0h],4 ; 001529e0
0014435d 56 push esi
0014435e 8b7508 mov esi,dword ptr [ebp+8]
00144361 7433 je 00144396
00144363 e8595bffff call 00139ec1
00144368 84c0 test al,al
0014436a 742a je 00144396
0014436c 85f6 test esi,esi
0014436e 7426 je 00144396
00144370 833e30 cmp dword ptr [esi],30h
00144373 7521 jne 00144396
00144375 8b4608 mov eax,dword ptr [esi+8]
00144378 e8fdfeffff call 0014427a
0014437d 85c0 test eax,eax
0014437f 7415 je 00144396
00144381 6a30 push 30h
00144383 56 push esi
00144384 8d4dd0 lea ecx,[ebp-30h]
00144387 51 push ecx
00144388 e818010000 call 001444a5
0014438d 8945d8 mov dword ptr [ebp-28h],eax
00144390 8d45d0 lea eax,[ebp-30h]
00144393 50 push eax
00144394 eb01 jmp 00144397
00144396 56 push esi
00144397 ff1568141300 call dword ptr ds:[131468h] ; -> 02200126
0014439d 5e pop esi
0014439e c9 leave
0014439f c20400 ret 4
A bit hard to know what it was doing but there was a call at the bottom there that was worth a quick look.
02200126 8bff mov edi,edi
02200128 55 push ebp
02200129 8bec mov ebp,esp
0220012b e954ae217c jmp user32!RegisterClassExW+0x5 (7e41af84)
Yep, as expected it was a jump back to the original API function, 5 bytes in. That looked like a hook library was being used because the callback to the original function was in a separate memory block. But no real info. But again, looking at the address space revealed it belonged to no known module.
0:000> !address 2200126
02200000 : 02200000 - 00001000
Type 00020000 MEM_PRIVATE
Protect 00000040 PAGE_EXECUTE_READWRITE
State 00001000 MEM_COMMIT
Usage RegionUsageIsVAD
At this stage, it was clear we were looking at malware, so I decided to look for some strings in the data area referenced earlier (in blue, above). Initially I found only strings pointing to Application Data and other uninteresting sources.
0:000> dd 1529e0
001529e0 00000000 02181ea0 0000001c 83f6f0a1
001529f0 00000000 00130000 7c800000 7c900000
00152a00 02200000 00000000 7c90d7fe 00000000
00152a10 0220000a 7c916a02 0000000c 00152a24
00152a20 00000000 00040001 00000000 00000000
00152a30 00000000 00000000 ffffffff 02181ee0
00152a40 003a0043 0044005c 0063006f 006d0075
00152a50 006e0065 00730074 00610020 0064006e
But eventually I struck gold:
0:000> dd
00152f5c 00000000 000006b0 00000000 004f0053
00152f6c 00540046 00410057 00450052 004d005c
00152f7c 00630069 006f0072 006f0073 00740066
00152f8c 0041005c 006b0067 00610065 00000064
00152f9c 00000000 00000000 00000000 00000000
00152fac 00000000 00000000 00000000 00000000
00152fbc 00000000 00000000 00000000 00000000
00152fcc 0019c110 ffffffff 00000000 00000000
This proved to be a suspicious registry key:
0:000> du 152f68
00152f68 "SOFTWARE\Microsoft\Agkead"
A quick glance at that registry key showed the following suspicious registry entries:
I picked up a few other interesting strings as well:
0:000> du 152fe8
00152fe8 "Global\{451EEC04-7C31-7A30-8C56-"
00153028 "BCE6C174342E}"
0:000> du 1527e0
001527e0 "Enfok"
The following string was also interesting:
0:000> du 1523d4
001523d4 "\Documents and Settings\Receptio"
00152414 "n_2.PGE\Application Data\Ewacg\o"
00152454 "xmo.hio"
While the folder existed, I was unable to see the file oxmo.hio. This, as well as the fact that I could not see any user mode activity doing the hooking of the functions in question, really suggested a rootkit which was doing some cloaking, rather than simple user-mode malware.
A reference to the string Agkead was on ThreatExpert.
But by now I was really only continuing out of interest, so I handed the machine in question back to the client, with the advice that they rebuild it — difficult to be sure that the machine is clean any other way. While it would have been fun to analyse the malware further, it’s not really my job 🙁