Studying Sysmon's Ability to Detect Process Injections Using Different Configuration Schemas
Redcanary has ranked Process Injection as the number one threat observed in their customers’ environments; More than 34% of organizations are affected by this threat, with more than 2,700 confirmed threats. Process Injection is a technique adversaries use to carry out malicious activities to be performed by legitimate processes. Adversaries also employ the technique so that their malicious code inherits the privileges of the injected legitimate process.
There are different methodologies to achieve process injection. The methods that will be discussed in this post are implemented using Blackbone library, which is a Windows memory hacking library. The methods are the followings; DLL injection via CreateRemoteThread(), DLL injection via a stealth CreateRemoteThread(), DLL injection via QueueUserAPC(), DLL injection via Shellcode DLL injection, DLL injection via Suspend Injection Resume, and DLL injection via Image Mapping. In this post, I show a comparison of different ways of Sysmon usage. From experience, I saw a high usage of SwiftOnSecurity’s configuration schema, so I wanted to put it under test. I wanted to test Sysmon without using an external schema, with SwiftOnSecurity/sysmon-modular, and Sysmon without any Create Remote Thread exclusions against the mentioned injection methods above.
Sysmon is a very helpful tool that should be able to detect DLL injections, right? What I found is that by default, it doesn’t. Analysts need to configure them correctly; otherwise, Sysmon won’t be able to detect the kinds of injections mentioned in this post. Using a premade Sysmon configuration file from SwiftOnSecurity, SwiftOnSecurity/sysmon-config doesn’t detect an injection via CreateRemoteThread(). Sysmon wasn’t able to detect that there was a DLL injection that happened to notepad.exe. The next screenshot shows no alerts with the number 8 as an identifier for a CreateRemoteThread event.
The reason SwiftOnSecurity config file didn’t work is that it has this line to exclude kernel32.dll:
And the injection code uses LoadLibraryW function from KERNEL32.DLL which is the StartModule.
So I had to edit the configuration file and let it monitor all the binaries in the system, which can be done by removing the conditions for the CreateRemoteThread rule.
<RuleGroup name="" groupRelation="or"> <CreateRemoteThread onmatch="exclude"> </CreateRemoteThread> </RuleGroup>
I launched the infection again, and Sysmon was able to detect the new remote thread.
Here is the trade-off, if there is no exception for kernel32.dll. Sysmon would send many events from csrss.exe and other processes showing several false positives. I am guessing that’s why kernel32 wasn’t included in SwiftOnSecurity’s schema file.
In the next grid, I compared different Sysmon XML schemas. I used the most common schema, SwiftOnSecurity’s schema. I also know that sysmon-modular is very common. Sysmon-modular’s schema is almost the same as SwiftOnSecurity’s so I didn’t compare it. I also added a schema without any
create remote thread exclusions. Finally, as a control, I used Sysmon without a custom schema.
|Injection method||SwiftOnSecurity/sysmon-modular||Default||No exclusions|
|CreateRemoteThread()||Not detected||Not detected||Detected|
|stealth CreateRemoteThread()||Detected||Not detected||Detected|
|QueueUserAPC()||Not detected||Not detected||Not detected|
|Shellcode DLL injection||Detected||Not detected||Detected|
|Suspend Injection Resume||Detected||Not detected||Detected|
|Image Mapping||Detected||Not detected||Detected|
The lack of an immeasurable Sysmon configuration schema defeats the purpose of using Sysmon. SwiftOnSecurity’s configuration schema is a good configuration schema. However, with a little work, malware can hide itself. Unless we configure Sysmon to log every remote thread creation event without any exception, it would be hard to detect all mentioned injection types.