Zombie Processes as a HIPS Bypass
A long long time ago (about 10 years in non-internet time) malware developers only had to worry about signature based detection, which could be easily bypasses with polymorphic droppers or executable encryption. To deal with rapidly evolving malware, capable of evading signature detection, HIPS was created.
HIPS (Host-based Intrusion Prevention System), sometimes referred to as Proactive Protection or Proactive Defense, is an anti-malware technique designed to detect malware by behavior, and not its file signature. Using kernel mode callback and hooking, HIPS systems can monitor which functions an executable calls, with which parameters, and in what order. By monitoring executable calls the HIPS can get a decent idea of what the executable is trying to do, Ex: Allocating executable memory in a foreign process, followed by creating a thread that resides in the allocated memory; The process is likely trying to inject code. Once the executable tries to perform an action that is deemed malicious, the system can decide what to do based on how common the application is, if it’s signed and by whom. For a malicious executable to escape a HIPS, it would have to trick the system into believing it’s a legitimate signed application.
Due to non-static data within a process, such as absolute addresses, imports, and statically allocated variables; it is not possible to verify the digital signature of a running process. To check a process’ signature, the HIPS would have to get the executable file path from the PEB (Process Environment Block) or the section handle, then verify the signature of the file on disk. ## Zombie Processes
The concept of zombie processes is pretty simple: we can create a standard Windows process in a suspended state, then write our malicious code to the processes’ memory; the PEB and the EPROCESS structures will still be that of the original process, causing the HIPS to see the now malicious process as a legitimate signed executable (this is not RunPE or dynamic forking, because we don’t unmap the original executable and replacing it with our malicious one, as thos can be detected in multiple ways). It’s basically PE injection, but with less exposure to functions that would allow the HIPS to detect code injection.
- CreateProcess returns a handle to the created process and its main thread with full access, so we don’t have to call OpenProcess or OpenThread.
- The main thread is in a suspended state and we know the entry point, so no need to call CreateRemoteThread.
- Modification to a child process is far less suspicious that a foreign one.
Injecting the Code A common practice is to call VirtualAllocEx to allocate memory, then use the returned address to relocate the code ready to run at that address. Once the code has been prepared, it can be written to the process with WriteProcessMemory. This is a terrible idea, every HIPS ever expects malware to do that. A better practice used by newer malware (such as Andromeda and BetaBot) is to create as section, then use NtMapViewOfSection to map the section into both the current process and the target process. It’s not really possible to know what address the section will be mapped at before mapping it, so this would cause a problem with code that requires relocation.
NtMapViewOfSection actually maps the same physical section into both processes (writing the map of the section in the current process will also write the map in the target process), we can simply map the section into both processes then relocate and write the code to the section in the current process, resulting in it also being written to the target process, no WriteProcessMemory needed!
Executing the Code There’s a few ways to do this, but I’ll go over the 2 most common.
- Use SetThreadContext to change the EAX register (which points to the process entry point) to the entry point of your code.
- Use WriteProcessMemory to write a jump from the process entry point to your code.
Once the code is running inside the trusted process, it is likely to have far more freedom as to what it can do without triggering antivirus warnings, the PEB, EPROCESS and Section Handle, all still point to the original process. As always I’ve included some example code: https://github.com/MalwareTech/ZombifyProcess