Rather than inject code into a host program, some malware uses a method known as process replacement to overwrite the memory space of a running process with a malicious executable. Process replacement is used when a malware author wants to disguise malware as a legitimate process, without the risk of crashing a process through the use of process injection.
This technique provides the malware with the same privileges as the process it is replacing. For example, if a piece of malware were to perform a process-replacement attack on svchost.exe, the user would see a process name svchost.exe running from C:WindowsSystem32 and probably think nothing of it. (This is a common malware attack, by the way.)
Key to process replacement is creating a process in a suspended state.
This means that the process will be loaded into memory, but the primary thread of the process is
suspended. The program will not do anything until an external program resumes the primary thread,
causing the program to start running. Example 12-2
shows how a malware author achieves this suspended state by passing CREATE_SUSPENDED
(0x4
) as the dwCreationFlags
parameter when performing the call to CreateProcess
.
Example 12-2. Assembly code showing process replacement
00401535 push edi ; lpProcessInformation 00401536 push ecx ; lpStartupInfo 00401537 push ebx ; lpCurrentDirectory 00401538 push ebx ; lpEnvironment 00401539 pushCREATE_SUSPENDED
;dwCreationFlags
0040153B push ebx ; bInheritHandles 0040153C push ebx ; lpThreadAttributes 0040153D lea edx, [esp+94h+CommandLine] 00401541 push ebx ; lpProcessAttributes 00401542 push edx ; lpCommandLine 00401543 push ebx ; lpApplicationName 00401544 mov [esp+0A0h+StartupInfo.dwFlags], 101h 0040154F mov [esp+0A0h+StartupInfo.wShowWindow], bx 00401557 call ds:CreateProcessA
Although poorly documented by Microsoft, this method of process creation can be used to load a process into memory and suspend it at the entry point.
Example 12-3 shows C pseudocode for performing process replacement.
Example 12-3. C pseudocode for process replacement
CreateProcess(...,"svchost.exe",...,CREATE_SUSPENDED,...);ZwUnmapViewOfSection(...);
VirtualAllocEx
(...,ImageBase,SizeOfImage,...);WriteProcessMemory
(...,headers,...); for (i=0; i < NumberOfSections; i++) { ❶WriteProcessMemory
(...,section,...); }SetThreadContext
(); ...ResumeThread
();
Once the process is created, the next step is to replace the victim process’s memory
with the malicious executable, typically using ZwUnmapViewOfSection
to release all memory pointed to by a section passed as a parameter.
After the memory is unmapped, the loader performs VirtualAllocEx
to allocate new memory for the malware, and uses WriteProcessMemory
to write each of the malware sections to the victim process space,
typically in a loop, as shown at ❶.
In the final step, the malware restores the victim process environment so that the malicious
code can run by calling SetThreadContext
to set the entry point
to point to the malicious code. Finally, ResumeThread
is called
to initiate the malware, which has now replaced the victim process.
Process replacement is an effective way for malware to appear non-malicious. By masquerading as the victim process, the malware is able to bypass firewalls or intrusion prevention systems (IPSs) and avoid detection by appearing to be a normal Windows process. Also, by using the original binary’s path, the malware deceives the savvy user who, when viewing a process listing, sees only the known and valid binary executing, with no idea that it was unmapped.