Pages

Monday, 4 January 2021

How to Design Abnormal Child Processes Rules without Telemetry

    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):


Of course not all programs names are valid child processes of WerFault.exe, to confirm which one are potential benign/expected child processes we need to move to the next step. 

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:


In the example of the CInpagePlugIn::StartCoFireProcess function we can see that the cofire.exe t is a potential child process.


In this case it was easy (adjacent to the API call), in other cases you will need to drill-down a couple of functions to find the ApplicationName or CommandLine being populated, you can always go back to the Program names extracted at phase 2 and cross reference the function that uses them for correlation. 

Psr.exe is another potential child process referenced in CAppRecorderPlugin::StopRecordingSession 


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")


  Of course this approach will miss in some instances potential false positives such as processes created with arguments passed via standard input, config files, registry values, COM, RPC and equivalent :





above you can see an example where a potential child process name is extracted from the registry values ReflectDebugger. or Debugger:




This method is time consuming but still if applied to a limited number of target processes it can provide you with an initial working detection rule with minimum noise and with no access to production endpoint process execution telemetry.

References:

https://twitter.com/SBousseaden/status/1235533224337641473

https://www.hexacorn.com/blog/2018/08/31/beyond-good-ol-run-key-part-85/

https://github.com/elastic/detection-rules/blob/main/rules/windows/defense_evasion_masquerading_suspicious_werfault_childproc.toml