Although sometimes it obvious when a computer’s integrity has been compromised by malware (addware, fakeAV, etc), other times it’s much less obvious. Some malware samples, like those designed to exfiltrate creditcard information/ user logins, can have their largest impact when the user doesn’t know they’ve been infected.
To avoid detection malware will often rename itself to something harmless. One of the most recent malware sample I’ve analyzed, a sample from the Alina family of viruses, tried to rename its self winfax12.exe to try and avoid detection on point of sale machines.
A more sophisticated method of persistence that doesn’t rely on social engineering is to have the malware sample inject itself into the memory of another actively running process. The most common way to do this on WindowsXP is through a process called DLL injection. Although there are variations on the process, malware will often take the following route to inject itself into a running process on WindowsXP
- Obtain a handle to the running process
- Allocate enough memory for the name of the dll to inject in the running process.
- Write the name of the dll to inject into the running process.
- Use Kernel32.dll to get hold of LoadLibraryA in the running process
- Create a new thread in the running process using CreateRemoteThread. The starting address of this thread is at LoadLibraryA and the name of the dll that was written into this process is passed as a parameter to LoadLibraryA.
By reverse engineering a malware sample in IDA I’ve reconstructed similar program in C seen running in the video below. In the video, the game solitaire named sol.exe is injected with mydll.dll which triggers a windows message box.
For those new to translating programs in IDA from assembly to C, one of the hardest parts can be getting used to the fact the arguments are pushed onto the stack in reverse order.
In the picture above the function VirtualAllocEx is used to allocate enough memory into the running process so later the name of the dll to inject has a place to be written to. According to Microsoft’s documentation the prototype for VirtualAllocEX looks like the following:
1 2 3 4 5 6 7
Before actually reading the documentation this almost looks more cryptic than the assembly. It also doesn’t help that by default instead of displaying symbolic constants like PAGE_READWRITE and MEM_COMMIT as string values in the previous picture IDA will just list these as integers. By right clicking the integer values you can select what symbolic constant to replace them with in IDA.
Actually reading Microsoft’s documentation, the rough equivalent of the excellent linux man pages, it becomes clear that hProcess is a handle to the process to inject, lpAddress is a preferred starting location for the allocation, dwSize is the number of bytes to allocate, and flAllocationType/flProtect are one of the symbolic constants shown earlier.
It would be tedious to explain every function but the rest of the program that actually does the injecting can be found on git here: https://github.com/quantumvm/InjectDll/blob/master/Source.c The second half of this puzzle is how what to actually put into the dll that will be injected into the running process. Since Visual studio seems to like c++ a lot, it’s not fantastic for just c development, I wrote the actual dll in c++ instead of c.
When a dll is compiled its entry point is defined by the function DllMain. Visual studio provides most of the code you need for the dll already (The empty switch isn’t even necessary!) its very easy to append the functionally you want at the end of the DllMain function. The full dll I wrote for this project can be found here: https://github.com/quantumvm/InjectDll/blob/master/sample_dll/dllmain.cpp
Before wrapping things up here are a few caveats: Although using the CreateRemoteThread method works fantastic in windows XP the method will fail in windows vista onward. The alternative is to use undocumented functions like NTCreateRemoteThread but this disadvantage is that the malware can only inject the dll into windowed programs using this function.
When compiling the c program for Windows XP on VisualStudio 2012 onward you encounter a few small problems with backward compatibility specifically for the function OpenProcess. Between XP and vista the size of the flag PROCESS_ALL_ACCESS is actually changed so it’s necessary to tell the preprocessor that we want to support windows XP by including the following flag at the top of the program: