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.
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.
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.
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.