In detection engineering we often encounter attack techniques that result into a system process spawning an unusual child process, which can be used as a good detection or hunting logic. The only problem that remains is to exclude legitimate/expected benign child processes, and for this often we need some endpoint production telemetry (the more the better), unfortunately not everyone has this privilege. In this post we will share with you some quick steps you can follow to tune your rule with no telemetry access.
For this let's take the example of a malware masquerading as WerFault.exe via hollowing or any equivalent form of injection, and our goal is to detect suspicious instances via looking at any abnormal child process (e.g. cmd.exe):
1) Imported Modules: Step 1 consist of identifying all imported DLL that are specific to the functioning of the subject process (not generic ones such as kernel32.dll, ntdll.dll etc.), in our example we can see 2 modules wer.dll and faultrep.dll:
2) Strings: Step 2 consist of identifying all executables in the process (werfault.exe) strings and also the previously identified function specific DLLs (wer.dll, faultrep.dll):
3) Process Creation APIs: goal here is to identify all references to process creation related APIs (CreateProcessA/W, CreateProcessAsUserA/W, CreateProcessInternal, WinExec, ShellExecute , ShellExecuteEx, NtCreateProcess, ZwCreateProcess etc.). we will need to start first with those extracted directly from WerFault.exe, and then repeat same steps for the function specific DLLs.
For brevity we will show the steps for WerFault.exe example only, open your subject process in your favorite disassembler (you don't need to be a reverser!) and go to the the imports view, then search for the process creation related APIs:
Next double-click on the matched API name, then right-click or X to display the functions that use this API:
As you can see below, we have only 6 functions to check, you can also start from the process names identified in Step 2 (Strings View), but for better flow and understanding start first with the APIs XREFs:
The CreateProcess API arguments that we care about (point the potential benign child process we are looking for) are lpCommandLine or lpApplicationName:
4) Going back to Step 1 if needed: before repeating the same steps 1, 2 and 3 on wer.dll and faultrep.dll, first check via strings or checking the Import Table the presence of any process creation related APIs:
In case of no references to process names or process creation APIs, it's safe to move directly to step 5.
5) Detection Logic: Last step is straightforward, look for process with parent process name equal to WerFault.exe and process name is different than the identified potential benign child processes:
process where process.parent.name == "werfault.exe" and not process.name in ("cofire.exe", "psr.exe, ", "VsJITDebugger.exe", "TTTracer.exe", "rundll32.exe")