As I mentioned in a previous post, to expand my knowledge, I am working through the labs in the book Practical Malware Analysis by Michael Sikorski. In this post, I will demonstrate my findings in Lab 11-03, which illustrate entry-point redirection. Why would malware even want to use entry point redirection in the first place? It allows malware to take a perfectly legitimate file, inject malicious code into it, and then run that code by changing the entry point address in the legitimate file’s header such that when the file is executed, the computer runs the malicious code immediately before the original program. It’s important to note that the malicious code may or may not transfer execution back to the original legitimate code inside the file. If execution is transferred back to the legitimate code, then this type of attack is even harder to detect since everything appears to function as normal.
Note: I will be documenting the full analysis in this post. If you are only interested in the actual execution redirection process, click here.
The specific section (data structure) inside the Portable Executable file header (IMAGE_NT_HEADERS4, literally) which stores the entry point address is called IMAGE_OPTIONAL_HEADER5, which has a DWORD member entitled AddressOfEntryPoint . AddressOfEntryPoint simply stores the memory address which corresponds to the program’s very first instruction. Ironically, the IMAGE_OPTIONAL_HEADER is not optional at all and in fact stores critical information for the PE file to load properly when it’s executed. This is a lot of jargon but, put in plain terms, when a user executes a .exe file, the Windows Loader consults the PE Header to find out how much memory to allocate for the initial program’s data, instructions, resources, and also where the program should begin, hence the AddressOfEntryPoint. It is easy to see how program execution is impossible without the “optional” header.
The malware sample came in the form of two initial files: Lab11-03.exe and Lab11-03.dll. Of course in a production setting with the malware in the wild, they wouldn’t be so named.
Basic Static Analysis
My first attack was to run the .exe and the .dll through PE Studio6 which is an effective Portable Executable file analyzer for malware analysis. It pulls strings, imports, directories, hashes, certificates, overlays, etc… and organizes them, placing suspicious strings and imports at the top of the list which are known red flags in malware. It also automatically creates hashes for content in the file and submits it to virustotal, returning how many antivirus and antimalware products flag the file. I open up a notepad file and jot down anything that I find suspicious from the PE Studio readout. I also run sysinternals strings on the file manually because for some reason, the prioritized list that PE Studio provides has sometimes caused me to miss important strings and imports. These were my findings:
.EXE suspicious strings:
net start cisvc
The biggest ones that stood out here were inet_epar32.dll, cmd.exe, net start cisvc, and “zzz69806582”. Lots of clues that this malware is doing some funny business with DLLs, probably hooking and injecting them into a process; perhaps cisvc.exe which it is launching as a service, as noted by the “net start” command.7 Net start goes hand-in-hand with cmd.exe, which is likely being used to run it.
.DLL Suspicious Strings:
I flagged the TlsAlloc, TlsFree, and TlsGetValue in case this file was trying to employ some TLS callback anti-debug techniques, which it was not in the end. The two dlls were suspicious for reasons mentioned above about the previous DLLs. GetForegroundWindow and GetAsyncKeyState can be used to log keystrokes, so we may be dealing with a keylogger. There was also the suspicious “zzz69806582” which made another appearance in the DLL. But there is no apparent log file here… Hmm… Maybe it’s not a keylogger.
At this point, I also had no idea what cisvc.exe was other than that it was some type of service. I honestly didn’t know if it was a legitimate service at all or if it was a new file created by the malware. A simple Google search yielded this explanation:
A background process in Windows, the Content Index Service catalogs and tracks files on the hard drive and indexes them for faster search results. Initially introduced in 1996, the Content Index service was crucial for finding files in versions of Windows until Windows 7, when Microsoft introduced Windows Search.
At this point, I took a little sidetrack to get familiar with cisvc.exe and cidaemon.exe and actually opened them up in PE Studio as well. I will not be posting the strings and symbols found in them though as they do not directly relate to the malware and are in fact legitimate Windows programs, but I wanted to learn more about these files so that I could detect anything suspicious that may happen after I ran the malware. I did note that cidaemon used COM functions such as CoInitializeEx and CoCreateInstance as well as NtSetInformationProcess and NtQueryInformationProcess though.
The lab questions prompted me to go ahead and start dynamic analysis.
Basic Dynamic Analysis
I opened up Process Explorer, Process Monitor, created a registry snapshop with RegShot, opened up FakeNet to make the malware think I was connected to the Internet, and then ran Lab11-03.exe which opened up a cmd prompt, which said that it successfully started up a service. I wonder which one…
Looking at process Explorer, I saw that two new executables were in memory:
Just as suspected, the malware fired up cisvc.exe and cidaemon. But why? We aren’t doing any intensive searching, are we?
I set Process Monitor (procmon) to filter out all results for Lab11-03.exe and where the operation “contains” the word “Write.” Sure enough, found that the exe had written the “C:\WINDOWS\System32\inet_epar32.dll” file:
After this, I used Process Explorer to grad the two PIDs associated with cisvc.exe and cidaemon.exe that the malware launched. I then searched for Writes by these and found:
Followed by lots more writes to the same file:
The number of writes that kept happening to kernel64x.dll made me suspicious that this file may be a logfile used for a keylogger. I also had inet_epar32.dll to work with so I went ahead and analyzed it with PE Studio and long story short, compared the hash of the file with Lab11-03.dll and discovered that it was Lab11-03.dll installed into System32 for persistence, so no further basic static analysis was needed for that file. I then looked at the file size of Kernel64x.dll and let me tell you, it was a lot smaller than a real kernel file would be, so I opened it up with Notepad in anticipation that this was actually not a binary file. I was right and found:
susp_strings.txt – Notepad:
susp_strings.txt – Notepad: 0x1
susp_strings.txt – Notepad: 0x1
susp_strings.txt – Notepad: 0x1
susp_strings.txt – Notepad: 0x11 0xa2
susp_strings.txt – Notepad: 0x11 0x43 0xa2
Process Monitor – Sysinternals: www.sysinternals.com:
Process Monitor – Sysinternals: www.sysinternals.com: 0x11 0xa2
Process Monitor Filter: 0x11 0x4c 0xa2
Yup, it’s a keylogger, or at least has that functionality… We don’t yet know, maybe it does more. This is always entertaining but a little creepy to find, especially when it’s logging everything in real-time as I am analyzing it. I noticed no network activity associated with this and didn’t see any network indicators in basic static analysis either so I decided it was time to open this up in IDA for advanced static analysis and find out how this malware worked its magic. This is where the real fun begins – figuring out the how.
Advanced Static Analysis With IDA Pro8
I decided to start with the inet_epar32.dll file first, rather than the main .exe file. First thing I did was check DllMain, which is the “main” equivalent for DLL files which gets run when the DLL is loaded. Frankly, I didn’t get any clues here:
What I typically do in DLLs is open the function exports which usually leads to a more information, and it does:
We see there’s a function with that long string we spotted earlier as its name. Upon opening that function, it doesn’t look very resourceful at first, it just calls CreateThread. However, even though there is no asm “call” code, this function is essentially synonymous, by passing the start address of the malicious payload into the CreateThread function as an argument, it effectively calls that function as well:
Once we enter the “payload” function (which I so-named it during my analysis), JACKPOT! As we can see, this DLL is the keylogger, which makes a lot of sense as to why this component of the malware is loaded into the cisrvc.exe service… It needs to be active in the background in order to capture all the keystrokes. See below:
This first shot shows the malware first attempts to open a mutex, then if it cannot locate it, it creates a new one. This is a way for the malware to ensure that the keylogger is not already running in the background on the machine. If it is, it exits this instance.
The calls to GetAsyncKeyState are a dead giveaway of the keylogging functionality. The surrounding function that these calls appear in has a lot of complicated assembly code, but a cursory view of these calls explain what’s going on.
This is the code that writes to the kernel64x.dll logfile the recorded keystrokes.
The Entry-Point Redirection
The last part of this analysis is to look at the code that injects the malicious inet_epar32.dll file into the cisvc.exe process to begin with. This is the entry-point redirection part, and the main subject of this post. Upon opening Lab11-03.exe in IDA Pro, we see that the main function copies Lab11-03.dll into C:\WINDOWS\System32\inet_epar32.dll as we noted earlier:
It then specifies the location of cisvc.exe on disk and passes it into a very complex function that I’ve called “infect_cisvc” which loads up the DLL into the memory of the current process (Lab11-03.exe) by using these functions called in order: CreateFileA, GetFileSize, CreateFileMappingA, and finally MapViewOfFile. CreateFileA opens the cisvc.exe file up, GetFileSize figures out how many bytes to allocate in memory, CreateFileMappingA starts the process of loading the file by creating a mapping object9, and finally MapViewOfFile actually loads the dll into the current process (Lab11-03.exe) memory… It’s quite a process, no pun intended:
MapViewOfFile returns the memory address of the beginning of the file mapped into the current process’ memory. So effectively, the above functions all reserved and populated memory space inside of Lab11-03.exe with cisvc.exe such that Lab11-03.exe as a program can now access cisvc’s code and data. This start address is now stored inside a variable we’ve called lpBaseAddress. The below routine is a good example of why higher level languages were created because it overly complicates some pretty simple tasks being done:
What’s gone on here is some shifting of registers and variables to pass the start address plus some offset of cisvc.exe in memory into another function that I’ve called modify_header which is the function that opens cisvc.exe’s Portable Executable file header and changes the IMAGE_OPTIONAL_HEADER’s AddressOfEntryPoint to redirect execution to the shellcode that is about to be inserted and explained below. IDA Pro didn’t help much here but the “.text” section name and the fact that the above code is passing an offset value, which has actually transcended through several structs (IMAGE_NT_HEADERS -> IMAGE_OPTIONAL_HEADER) from the base address of the executable (herein called lpBaseAddress), is a dead giveaway that this program is modifying the header. Put together with the final segment, it’s clear what is going on. It also makes it clear how important knowing the PE file format is for effective malware analysis. See the “.text” section name inside of modify_header, as well as unknown function calls:
Going back to infect_cisvc, after quite a while of searching through seemingly monotonous assembly code with no API calls whatsoever, I stumbled upon a strange “offset” out of no where. In my experience, it’s typical to see offsets prior to an API or function call, but this offset was in the midst of what appeared to be a bunch of moves and arithmetic. At this point, I examined the data at the offset but nothing stuck out to me, yet. Not coming up with much, I went ahead and did an MSDN search on UnmapViewOfFile, which although I had an idea of what it did, I wasn’t 100% sure. From MSDN10:
Modified pages in the unmapped view are not written to disk until their share count reaches zero, or in other words, until they are unmapped or trimmed from the working sets of all processes that share the pages. Even then, the modified pages are written “lazily” to disk; that is, modifications may be cached in memory and written to disk at a later time. To minimize the risk of data loss in the event of a power failure or a system crash, applications should explicitly flush modified pages using the FlushViewOfFile function.
There’s a strangely subtle message in there about UnmapViewOfFile saving the file back to disk. At this point, I had no idea that UnmapViewOfFile did this, and assumed that it would be a separate API call. Knowing that rep movsd takes ecx number of bytes from the source index (esi) and places them into the destination index (edi), I further examined what was in the source index… The suspicious offset! After glancing over this memory which was in the .data section one more time, and came up with nothing… EXCEPT, I noticed an E9h in an adjacent memory address. I knew that E9 was an x86 opcode from prior experience, so I decided to just click on it and press hotkey “c” and JACKPOT!!! IDA displayed a whole heap of assembly code which was embedded right here in the .data section of the file starting at the aforementioned offset… Shellcode.
Most of the shellcode was extremely obscure and did not lead to any more clues. However, upon reaching the end of the shellcode, the last section had just a couple small clues:
NewFileName and ExistingFileName prompted a double-click which lead to:
There it is! That’s all we need to know that this code which is placed inside of the .data section of Lab11-03.exe is being transferred (written to) cisvc.exe while loaded in memory, then finally closed out and saved by UnMapViewOfFile.
Summary of Behavior
We now know that the malware does the following:
- Copies a malicious DLL into the system32 directory
- Opens an existing legitimate system file and modifies it, adding launcher code into it which when executed, loads the malicious DLL which was placed into the system32 directory in the previous step
- Saves the changes made to the system file in the previous step to disk and closes out the file
- Launches the modified system file, loading it into memory and activating the malicious DLL installed in step 1
- The malicious DLL is a keylogger which creates a file called kernel64x.dll inside of system32 as well
- The keylogger is therefore masked by a seemingly legitimate system process, even if he/she presses Ctrl+Shift+Escape and checks the process list. If the user searches Google for cisvc.exe in suspicion, Google will return results specifying that the file is indeed a legitimate Microsoft file.
- The logfile which is logging the keystrokes itself is also masked by being improperly labeled as a .dll file when in fact it’s a text file.
Lessons learned in this lab include:
- Be suspicious that files associated with malware are not labeled with proper file extensions. Just because it says .JPG doesn’t mean that it’s an image file. It could actually be an MP3 or a .exe
- Be suspicious of offsets to data in uncommon locations, and don’t forget the possbility of shellcode, which are just opcodes hidden away in plain old memory bytes.
- Malware often has to take obscure, ridiculous paths of execution in order to try to avoid detection, therefore it is important to be open-minded and know that typical programming practices probably won’t be followed. For example, instead of loading the malicious DLL into Lab11-03.exe, the program modified a system file to load the DLL, whereas with a legitimate program, there would be no need or desire to do this.
Entry-Point redirection is just one of many methods malware can use to try to hide itself. Learning it not only helps detect this specific type of attack, but also helps in learning the thought processes behind it, which are common to many other types of attacks as well. Lastly, we used all static analysis here but we could have opened up the files in a debugger like OllyDbg and figured much of this out that way as well. Stay tuned for articles on other methods malware uses to hide itself soon.