December 28, 2016
Following a webinar hosted by my colleague Justin Seitz two weeks ago, we discuss here of the detection of process hollowing, and how this capability may help in detecting ongoing cyber attacks.
Process hollowing is a trick for malware to hide its running computation. In a nutshell, it involves the replacement of the code of a process with that of the malware. Consider its implementation on the Windows OS, where Arc4dia’s hunters typically observe it. A bootstrap program will first start a process in the suspended state. The OS sets up the process structure and loads the program’s code. Then, the bootstrap uses debugging API functions in order to open the suspended process and replace the content of one of its code segments with its malware payload. It then tweaks the hollowed process’ entry point to start through the malware payload. The latter may then fork a thread to run the malware computation, leaving the main program’s thread to run its usual entry point, or replace that main function outright. When done against a little-used system process, this trick can very effectively hide a malware computation.
So, how does a hunter detect hollowed-out processes? On Windows, program code is loaded from files stored on disk; it is difficult to modify or destroy these files while the program runs. Hence, one can scan through the code segments of all processes, comparing the loaded code to that expected to have been loaded from file. Because of dynamic relocation, the code in memory never matches exactly its stored origin, but strong positive correlation is always expected — except when the code in memory has been replaced.
The astute reader will have noticed that the approach described above actually detects modified processes, not specifically hollowed-out processes. The latter is a subset of the former, and program self-modification is unfortunately a very common phenomenon. Many legitimate programs leverage so-called packer systems, such as BoxedApp. Some of these packers decrypt and/or uncompress the actual program code within the same code segment. Such approaches help reduce the programs’ storage footprint, or to conceal their functionality from reverse engineers (who are not fooled by the scheme, by the way). Many online update or self-updating programs exhibit similar code replacement behavior. And all of them trip the detection technique described above.
Therefore, any attempt at detecting process hollowing is bound to generate multiple false positives. As suggested, process code modification is infrequent enough to take interest when it happens, but also common enough not to be a surefire malware identifier. Process hollowing alerts must thus be analyzed **in context** of other events reported from and other alerts raised by the concerned host. Some context elements are of particular interest:
Let us first consider a process hollowing alert generated by looking at a process loaded from the
SC2_x64.exe program (namely, the main executable for the popular video game StarCraft II):
At first glance, this looks rather good. Video games often download updated code from the Internet: that it would replace the code within the same process is quite 1337 and surprising, but not worrisome. Furthermore, the tactical interest of hollowing a video game for malware purposes is low, unless the user plays with regularity and dedication — features that this games elicits, by the way, so it may become interesting to ask the user about his habits. We dig in SNOW’s object database to see how often we’ve see this module:
So we’ve seen this executable only on this host, which is perplexing. However, a quick check of its hash on VirusTotal shows that this is the real StarCraft II client, a well-known signed executable. Therefore, it is very unlikely to be a self-hollowing bootstrap; the hypothesis of a self-modifying game code is reinforced. We then look at the list of autoruns (programs made to run when the host boots up), which reveals nothing out of the ordinary. Finally, we look at other alerts raised for the host under investigation:
The process hollowing alert was raised on December 27th; the previous alert for this box goes back two days before (simply an object never seen before on other systems), and nothing more has happened since (at the time of writing). There is thus no context clue for worrying about an attack. Conclusion: false positive.
Let us now look in depth at how the malware examined in Justin Seitz’s webinar stacks up. The initial process hollowing alert shows up like this:
The target here is a VMware Tools daemon used by the VMware hypervisor for various data sharing features between the host and the virtual machine (e.g. clipboard, automatic resolution adjustment, etc.). As we are investigating a virtual machine, this makes sense. This daemon runs all the time and boots with the machine. Thus, from a tactical point of view, if would be a very good place for malware to hide. Like we did with the Starcraft II case, let us check that this
vmtoolsd.exe program is legit.
This time, we have seen many avatars of file
vmtoolsd.exe across all the networks we defend. The hash observed on the host under investigation is this one:
It checks out good on VirusTotal, so if there is a bootstrap, it is elsewhere.
At this stage, I start to look out for further context on this alert. Other alerts generated on this host:
The initial process hollowing alert corresponds to the next to bottom-most entry in this list. So we see that over the following few hours, the process hollowing alert repeated, side by side with thread injection and hidden module alerts targetting the same
vmtoolsd.exe process. This raises the alert to orange level — an execution thread has its entry point within the modified code segment.
The hidden module alert:
The base address (0x7ff693880000) indicated for this hidden module (e.g. identified MZ-headered code segment unaccounted for within the process’ list of modules) is exactly the same as that of the hollowed-out code segment. The alert level has now risen to scarlet. Hunters would team up to get a dump of this segment and start reverse engineering it, while somebody else looks for the persistent bootstrap. The first place to look is the autoruns list, for which we see here the beginning:
It takes close examination, but a good look at entry 3 shows something fishy: the
vmware_update.exe made to run is in
C:\ProgramData. This directory is normally hidden to the Explorer on most computers, so this is a pretty good place to put files better concealed… A look at this file’s hash shows it is unknown by VirusTotal, which is very uncommon for files related to VMware. This is a likely candidate for the bootstrap! Reverse engineering of this file (obtained through SNOW) and of the dumped module quickly show definitive malware features. Conclusion: very malware.
So, process hollowing detection is a nice feat of live memory forensics, but it has its caveats. The detection test actually identifies process code modification, which is a phenomenon too common to systematically label such events as malware. However, taken in proper context, process hollowing alerts do facilitate and accelerate the detection of an ongoing attack, enabling a quicker response and a more effective defense.
Obviously, sorting out all the false positives for process hollowing detection remains tedious. However, automation planned for implementation in SNOW can eliminate many common false positive cases. In particular, packed executables (e.g. executables set up using packer software, as described above) are easy to identify using tools such as PEiD. Automating this analysis, as well as other heuristics for flagging classes of legitimate process code modifications, should help the SNOW platform to scale better.
Thank you to Justin Seitz for his advice on contextual analysis and Marc Théberge for info on packers.