Intro
I’ve been working through Practical Malware Analysis and taking diversions into the some fantastic chapters Dr. Fu’s Malware Analysis Tutorial. Dr. Fu also links to some great resources, including: - A 2011 UCSB class (CS290G): Host-based Security and Malicious Code
-
Infosec Institute’s Step-by-Step Tutorial on Reverse Engineering Malware
-
Context’s 2013 two-part tutorial on malware analysis: Part One and Part Two
Another great reference is Malware Analyst’s Cookbook. It’s actually built cookbook-style with recipes for different types of processes you need to do.
The Lab
My setup is based on a few VMs. The host is a Win8.1 MSI GE70 running VirtualBox. The guests are:
OS | Purpose |
---|---|
Windows 7 x64 | Primarily used for acquiring malicious files. The files are then compressed and encrypted with 7-zip before being dropped into a shared folder with the host. |
Windows XP SP2 | The analysis VM. I pull the 7z archive from the shared folder and get to work with various tools. The network is VirtualBox’s “Internal Network” with the default gateway and DNS set to my Debian box. |
Debian (Wheezy) | Runs Inetsim. All DNS resolves back to Inetsim, fake files are served for any requests and redirection is turned on as well. |
The Malware
Name | Zender |
---|---|
File Name | zender1.exe |
File Size | 1,063,572 bytes (1.01MB) |
Family | Win32/Kelihos (?) |
Type | Trojan & Spambot |
Source | 89.144.xxx.xxx (UK-based server for a small tech services company) |
Hashes | MD5: F3BBC6C7E45D0503A6F9E397798EC09D1 SHA1: 1C81A258640142DA0740C8ADDAD8341138958DB7 SHA256: F83E964E7FCF5EABA7889F62630685DBD298F88519D0DF9B1385FB981B9043BC |
Callback IPs | 94.76.78.20, 37.229.235.67, 46.118.54.70, 176.8.157.75, 176.101.197.10, 190.254.65.114, 92.113.60.116, 86.124.225.116, 78.84.123.145, 46.118.80.240, 5.105.56.87 The IP ISPs are primarily in Ukraine but also Russia, Romania, Latvia & Colombia |
Ports & Protocols |
From: Sequential ephemeral ports To: TCP/80 |
Detection | Windows Defender recognizes it as part of the Win32/Kelihos trojan/botnet. The MD5 and SHA1 hashes didn’t return anything on VirusTotal. I hadn’t tried SHA-256. Once I uploaded it, only 8/57 antivirus programs recognized it as malicious. |
Prior Art
If this thing is actually part of Kelihos, I’m not seeing the similarities just yet. That classification was based solely on Windows Defender so I’m actually not sure just yet.
Kyle Yang of Fortinet gave a great presentation at BlackHat 2012:Google Docs PDF or Original PDF. Ditto for a group of researchers at BotConf 2012: Google Docs PDF or Original PDF
Static Analysis
Strings
Most strings are just garbage, plus a couple DLL names. Most of the ASCII characters it finds are actually part of the toolbar bitmap in the .rsrc section (Location: 0x00406180, Length: 1064 bytes). I found no IPs or domain names.
Imports
Library | Notes |
---|---|
advapi32 | For opening the registry and checking security permissions. |
gdi32 | Presumably for drawing an interface, or appearing to be a legitimate piece of software. |
kernel32 | All the good stuff. |
mfc42 | Wraps the Windows API in an easier-to-use API. Version 4.2 is from the days of Windows 98. |
msvcrt | The C runtime libraries (which were removed from MFC in v4.2). |
I’m guessing this file was originally a normal document editor that’s since been infected (and broken), or the authors just used a Visual Studio project template, considering an embedded bitmap toolbar that looks like it came out of Notepad and other imports like DoPreparePrinter, SaveAllModified, LoadToolbar, etc.
Functions
Half the functions are just stubs or appear to wrap some part of the Windows API. This may be the MFC stuff or intentional obfuscation; IDA failed to analyze some of them but there aren’t so few that it appears packed. In fact, multiple tools failed to recognize any packing.
Dynamic Analysis
First, Zender changes its own file attributes to Hidden and Archive. It does not hide itself from the Task Manager; even after a reboot, it remains in the process listing. With Process Monitor, I can see it iterates through hundreds of directories to see what’s on my box. It does the same with the registry but I’m not sure yet which are a “normal”.
For this variant at least, just renaming the EXE before rebooting appears to stop it in its tracks. I’d renamed the file and then noticed it wasn’t in Task Manager. Even if it was hiding itself from the listing, I saw none of the previous network activity through WireShark.
Without connection redirection turned on in Inetsim, the only outbound connections I captured were SYN requests to TCP/80. The IPs have to be hardcoded as no internet connection was available for it to get that data. However, they are not in the assembly as plaintext so it must be decrypting them on-the-fly. With connection redirection turned on, the handshake completes and Zender sends a TCP PSH with a bunch of, apparently encrypted, data.
I spent a bit of time searching for data cross-references. I found one long jumble of data at 0x405090 referencing 0x4021DD.
.data:00405090 byte_405090 db 0CDh ; DATA XREF: .t:crypto_4021DD
.data:00405091 db 37h ; 7
.data:00405092 db 0E4h ; S
.data:00405093 db 0Ah
.data:00405094 db 7Eh ; ~
.data:00405095 db 0D5h ; +
.data:00405096 db 0CAh ; -
.data:00405097 db 3
[ ... ]
.t:004021DD crypto_4021DD: ; CODE XREF: .t:00402233
.t:004021DD mov dl, ds:byte_405090
.t:004021E3 lea eax, [ecx+esi]
.t:004021E6 mov bl, [ebp+eax-0BA8h]
.t:004021ED mov eax, 7D8C42B3h
.t:004021F2 xor bl, dl
.t:004021F4 imul edi
.t:004021F6 sar edx, 8
.t:004021F9 mov eax, edx
.t:004021FB shr eax, 1Fh
.t:004021FE add edx, eax
.t:00402200 mov [ebp+edx-0BA8h], bl
.t:00402207 mov al, [ebp+esi-0BA8h]
.t:0040220E cmp al, 44h
.t:00402210 ja short loc_40221B
.t:00402212 dec al
.t:00402214 mov [ebp+esi-0BA8h], al
.t:0040221B
.t:0040221B loc_40221B: ; CODE XREF: .t:00402210
.t:0040221B inc esi
.t:0040221C add edi, 20Ah
.t:00402222 mov [ebp+8], esi
.t:00402225 fild dword ptr [ebp+8]
.t:00402228 fcomp ds:dbl_403AD0
.t:0040222E fnstsw ax
.t:00402230 test ah, 44h
.t:00402233 jnz short crypto_4021DD
.t:00402235 jmp loc_4021A0
This contains an xor with two different operands (so it’s not just zeroing out a register). I followed the code in OllyDbg and noticed a segment just above it that it jumped to, then it skipped a couple lines based on a floating-point register. I set a breakpoint on that (0x4021B0) and let it run. It stopped on the breakpoint and I followed it to the decrypted code at 0x12E874. That was a call to 0x12EA86.
mov eax, 4120
call 0012EE04
push ecx
Eventually, I find myself at 0x12EA93. It just moves text to memory: “kernel32.dll” is written to 0x12CCB0, “GetModuleFileNameW” to 0x12CC5C, “CreateFile” to 0x12CC80, “VirtualAlloc” to 0x12CC70, “GetFileSize[NULL]ReadFile” to 0x12CC98.
It messes with EAX to push a couple addresses in this range onto the stack and continues writing more function names to the area. Then it calls 0x12E8A4, pushes more addresses (0x2D680, 0x2D680, 0x00, 0x92A, 0x12AFA4, 0xD5786, 0xD4E88) on the stack and calls 0x12E8D5.
Pushes more stuff, gets the name of the file from ECX+30 (0x241F10), pushes more stuff and calls 0x12E956.
At 0x12E956, it iterated through the EXE’s name (and then several WinAPI DLLs) and appeared to encrypted the file names. If I watched it right, the key for the OR operation is ` $ $
$ $
$` $ (without the spaces… markdown syntax stuff).
Following a bit more, at 0x12E906, it pushes 0x7C800000 into EAX. That address contains a PE image. The PE signature is at 0x7C8000F0 so the size is at offset+0x50. The hex, 0x0060, is little endian so the image size is 0x6000. The memory doesn’t actually go that far; 0x42 is the last non-zero byte at 0x7C800287.
CPU Dump
Address Hex dump ASCII
7C800000 4D 5A 90 00|03 00 00 00|04 00 00 00|FF FF 00 00| MZ.......ÿÿ..
7C800010 B8 00 00 00|00 00 00 00|40 00 00 00|00 00 00 00| ¸.......@.......
7C800020 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
7C800030 00 00 00 00|00 00 00 00|00 00 00 00|F0 00 00 00| ............ð...
7C800040 0E 1F BA 0E|00 B4 09 CD|21 B8 01 4C|CD 21 54 68| º.´.Í!¸LÍ!Th
7C800050 69 73 20 70|72 6F 67 72|61 6D 20 63|61 6E 6E 6F| is program canno
7C800060 74 20 62 65|20 72 75 6E|20 69 6E 20|44 4F 53 20| t be run in DOS
7C800070 6D 6F 64 65|2E 0D 0D 0A|24 00 00 00|00 00 00 00| mode....$.......
7C800080 17 86 20 AA|53 E7 4E F9|53 E7 4E F9|53 E7 4E F9| † ªSçNùSçNùSçNù
7C800090 53 E7 4F F9|D9 E6 4E F9|90 E8 13 F9|50 E7 4E F9| SçOùÙæNùèùPçNù
7C8000A0 90 E8 12 F9|52 E7 4E F9|90 E8 10 F9|52 E7 4E F9| èùRçNùèùRçNù
7C8000B0 90 E8 41 F9|56 E7 4E F9|90 E8 11 F9|8E E7 4E F9| èAùVçNùèùŽçNù
7C8000C0 90 E8 2E F9|57 E7 4E F9|90 E8 14 F9|52 E7 4E F9| è.ùWçNùèùRçNù
7C8000D0 52 69 63 68|53 E7 4E F9|00 00 00 00|00 00 00 00| RichSçNù........
7C8000E0 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
7C8000F0 50 45 00 00|4C 01 04 00|92 3B 20 53|00 00 00 00| PE..L.’; S....
7C800100 00 00 00 00|E0 00 0E 21|0B 01 07 0A|00 40 08 00| ....à.!..@.
7C800110 00 04 07 00|00 00 00 00|4E B6 00 00|00 10 00 00| ......N¶.....
7C800120 00 10 08 00|00 00 80 7C|00 10 00 00|00 02 00 00| ....€|......
7C800130 05 00 01 00|05 00 01 00|04 00 00 00|00 00 00 00| ...........
7C800140 00 60 0F 00|00 04 00 00|D5 63 0F 00|03 00 00 00| .`....Õc....
7C800150 00 00 04 00|00 10 00 00|00 00 10 00|00 10 00 00| ............
7C800160 00 00 00 00|10 00 00 00|2C 26 00 00|19 6D 00 00| .......,&..m..
7C800170 00 26 08 00|28 00 00 00|00 A0 08 00|E8 5E 06 00| .&.(.... .è^.
7C800180 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
7C800190 00 00 0F 00|D8 5C 00 00|F0 4E 08 00|38 00 00 00| ...Ø\..ðN.8...
7C8001A0 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
7C8001B0 00 00 00 00|00 00 00 00|B8 EB 04 00|40 00 00 00| ........¸ë.@...
7C8001C0 00 00 00 00|00 00 00 00|00 10 00 00|24 06 00 00| ...........$..
7C8001D0 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
7C8001E0 00 00 00 00|00 00 00 00|2E 74 65 78|74 00 00 00| .........text...
7C8001F0 51 3F 08 00|00 10 00 00|00 40 08 00|00 04 00 00| Q?.....@....
7C800200 00 00 00 00|00 00 00 00|00 00 00 00|20 00 00 60| ............ ..`
7C800210 2E 64 61 74|61 00 00 00|40 44 00 00|00 50 08 00| .data...@D...P.
7C800220 00 26 00 00|00 44 08 00|00 00 00 00|00 00 00 00| .&...D.........
7C800230 00 00 00 00|40 00 00 C0|2E 72 73 72|63 00 00 00| ....@..À.rsrc...
7C800240 E8 5E 06 00|00 A0 08 00|00 60 06 00|00 6A 08 00| è^.. ..`..j.
7C800250 00 00 00 00|00 00 00 00|00 00 00 00|40 00 00 40| ............@..@
7C800260 2E 72 65 6C|6F 63 00 00|D8 5C 00 00|00 00 0F 00| .reloc..Ø\.....
7C800270 00 5E 00 00|00 CA 0E 00|00 00 00 00|00 00 00 00| .^...Ê.........
7C800280 00 00 00 00|40 00 00 42|00 00 00 00|00 00 00 00| ....@..B........
Update: I had the second post partially written for this but had a bit of a catastrophic failure after moving. I may get around to continuing but I’ve mostly moved on.