Monday, 18 April 2022

Auditing Protected Lsass (RunAsPPL) Access using Sysmon

 Auditing Lsass access using Sysmon is one of the key settings that blueteam are using to detect suspicious instances in an attempt to detect behaviour like Mimikatz. It's also known that a lot of legit programs (including MS native services) are requesting process access handle (including VM_READ) which get very noisy in large scale deployment. 

One exception that comes to mind is what if some of the machines in the prod have RunAsPPL enabled ? RunAsPPL normally is designed to prevent OpenProcess from a process with lower signature level to access Lsass.  Thus the volume of Sysmon 10 events with TargetImage set to lsass.exe shouldn't be a problem as its limited to what Lsa PPL allow:

If the SourceProcess is not a protected process then the only allowed access rights (from a high/system integrity level) are : 


Excluding QUERY_LIMITED_INFORMATION (suspend/terminate is a bit abnormal for lsass anyway) and should be good enough to limit noise to SourceImage set to a protected processes (with signature level >=  PsProtectedSignerLsa) or a usermode process leveraging a kernel mode driver such as ProcessExplorer via PROCEXP512.sys or ProcessHacker via kph.sys and those cases should be limited (no major impact on noise, can excluded with minimal efforts).

To confirm this behavior, created a generic sysmon config to audit all process access to PPL Lsass : 

ProcExp leveraging PROCEXP.SYS

As suspected, almost 90% of the volume is related to query_limited_info/set_limited_info, rest is malicious or related to a usermode process that leverage a kernel mode component :

As can be seen above, even protected process with signature level > LsaLight (services.exe) they usually don't request GA > query_limited_info (even if technically they can get full access). This lead us to the idea that if  we receive a sysmon event 10 with target image set to lsass and granted access allow to read memory and RunAsPPL is enabled from that machine then there are high chances it's A) PPL Bypass or B) legit usermode process (non protected) leveraging a kernel driver (risky too if not controlled and can be abused via stealing lsass handles), C) Protected Process with signature_protect level >= Lsa_LIGHT (should be limited).

The question that remain is how an analyst can differentiate between a Sysmon event 10 (Process Access) coming from an Lsa protected process or from a normal one ?  

An ideal scenario is if Sysmon added an enrichment to Sysmon 10 events (at least if targe image is lsass but can also be useful for auditing PP tampering in general), something like : 

A dirty way of  doing it, is to create a scheduled task (via GPO) that triggers on a sysmon 10 event with lsass access (custom XML filter), then run a command to query RunAsPPL registry value (I know it can be deleted as a bypass with no effect on PPL but unlikely scenario and can be audited via sysmon 12) and write the results to the event logs (everytime lsass is accessed), then ingest and correlate that event with any process access:

Correlating Lsa RunAsPPL status with Sysmon Process Access enabled us to differentiate between what can be considered as a regular false positive (e.g. svchost.exe accessing Lsass with full access rights) and what could be a serious alert like PPL bypass or potential bypass vectors such as a third party unprotected process leveraging a kernel driver to obtain access to protected processes.


Sunday, 20 March 2022

Structured Approach to Triage New Detection Ideas


Triaging new detection ideas is an important aspect of detection engineering, as it allow us to focus on the most important tasks and to optimize the utilization of the existing limited resources (both human and technology).

It doesn't have to be perfect, but it needs to minimize the effect of personal preferences and the tendency or desire to catch the most advanced or recent stuff. To do so, we need a way to assign qualitative scores for certain critical questions, the threshold can be adjusted per your need and context.

The following diagram try to summarize the most relevant questions to consider while deciding on whether or not to implement a new detection idea. Note that if a detection does not fit the agreed threshold, it can move as a hunt or a scheduled report (the goal here is to scope rules running in near real-time and that tend to consume more computing processing power).

Detecting all known common LOLBINS connecting to the internet, at first glance seems to be a good idea, but if we take it through the above process : 

  • Coverage width is high since a variety of malware droppers tend to involve some kind of lolbins -> DS = 5 (having access to a malware sandbox helps with this point)
  • Performance impact is medium : although the number of lolbin binaries is considerably high, at least 25 processes, we are still using only one type of event (network), no correlation, logic is simple (if network event detected and process is in lolbins_list alert) -> DS = 10
  • It is a critical technique (matches Initial Access & Execution and partially defense evasion too) -> DS=15
  • Triage experience and noise ratio: a considerable number of LOLBINS tend to connect to the internet for legit activities, this makes quick assessment a little bit harder, the same impact FP rate (False Positives) -> DS=15 (no changes to the score)
  • resilience to bypass:  low effort via renaming a LOLBIN process name to something else -> DS=12 (15-3)
So our idea total score is 12, as it seems to be very close to our defined threshold, we can target the weakest points of our initial idea and adjust it, either by working on the evasion aspect, triage experience or both, to do so we can slightly change our initial idea to a correlation of a lolbins process execution followed by network connection, this will allow us to improve resilience by using process original file name (instead of process name) and also make triage and FPs tunning processes more flexible by having access to both the process arguments and the destination address.

Note that sometimes adjusting the initial logic may require to redo the whole assessment, for instance in our example the correlation may increase performance impact on the rules processing engine, but this is an acceptable impact (medium) since we are limiting the correlation to a subset of known processes (lolbins).

Friday, 10 December 2021

Detecting Token Stealing using Sysmon v13.30 and EQL


Access token manipulation is a well known technique often used to elevate privileges or to execute in the context of a different identity.  There are different implementations of this technique but the most observed one seen in malwares as well as in common offensive frameworks (i.e. metasploit incognito, cobalt srike steal_token) is often referred to as Token Stealing and aims to elevate privileges from high integrity to System integrity.

If you are interested to know more about the implementation part of this technique I would recommend the following reading :

The classic implementation invole those steps / APIs: 
  1. Enable SeDebugPrivilege (needed for Step 2 and require high integrity)
  2. Obtain a handle to a process running as System via OpenProcess (victim)
  3. Obtain Token handle of the System process via OpenProcessToken 
  4. Duplicate stolen token via ImpersonateLoggedOnUser and DuplicateTokenEx
  5. Create a SYSTEM child process with the token duplicate via CreateProcessWithTokenW

For step 2 (critical step) usually the source process (Malware) will be running as High integrity and won't be able to obtain Full access rights to all System processes (i.e. PPL). 

The minimum needed Access rights are enough to obtain a valid access handle that allow to proceed to step 3:

0x1400 - PROCESS_QUERY_INFORMATION : High to System, fails on PPL protected processes such as the following: 

0x1000 - PROCESS_QUERY_LIMITED_INFORMATION (High to system, works on PPL protected processes)

Also something worth noting is that winlogon.exe is one of the most targeted processes (not PPL and runs as system).


For detection there are some opportunities such as the one described in this blog using custom SACLs to audit a list of selected processes object access via event 4656 (very noisy, often not logged in prod and captures step 2 only) or baselining processes enabling the SeDebugPrivlege using event 4703 (captures step 1 only). 

In this post we will be using Sysmon v.13.30 that added recently some cool enrichment (SourceUser,  TargetUser for process Access events and ParentUser for process creation events) and that we can play with to create a more resilient detection. Before going to the detection logic let's breakdown the key steps/artifacts:

Step 1 - Windows security 4703

Step 2 - Sysmon  Process Access - 10 (Target is a System process and source is not)

Step 3 and 4 - No Events

Step 5 - System Process Creation  

From the above events we can create a correlation (using Elastic EQL) to link artifact from Step2 and Step 5 :

  1. Process Access event from Process A running as normal user to Process B running as SYSTEM (Sysmon 13.30 - Source User and Target User) 
  2. Process A running as normal user (Sysmon 13.30 ParentUser) spawns a child process running as SYSTEM.

sequence with maxspan=1m
  [process where event.code : "10" and
  GrantedAccess values in scope
  winlog.event_data.GrantedAccess :

("0x1000", "0x1400", "0x1F3FFF") and
    winlog.event_data.TargetUser : "NT AUTHORITY\\SYSTEM" and not
    winlog.event_data.SourceUser : "NT AUTHORITY\\*" and
    winlog.event_data.TargetImage : "?:\\Windows\\*.exe"] by process.entity_id
[process where event.code : "1" and
    winlog.event_data.LogonId : "0x3e7" and
    winlog.event_data.TerminalSessionId : "1" and
    not winlog.event_data.ParentUser : "NT AUTHORITY\\*"] by process.parent.entity_id

Testing our detection logic

Same logic triggers on malwares such as Glupteba and Zenpack implementation:

For Sysmon config I would recommend to limit it to commonly targeted System processes like winlogon.exe, lsass.exe and TrustedInstaller.exe if you want to limit sysmon 10 eventing volume. 

Monday, 24 May 2021

Hunting for Suspicious Usage of Background Intelligent Transfer Service (BITS)

BITS Overview

Background Intelligent Transfer Service (BITS) is used by programmers and system administrators to download files from or upload files to HTTP web servers and SMB file shares. 

BITS will take the cost of the transfer into consideration, as well as the network usage so that the user's foreground work has as little impact as possible. BITS also handles network interruptions, pausing and automatically resuming transfers, even after a reboot, which makes it a very good candidate for implant Command and Control standard tasks (download, upload and ex-filtration). 

BITS includes PowerShell cmdlets for creating and managing transfers as well as the BitsAdmin command-line utility.

BITS is composed of a Client (i.e. bitsadmin, powershell) loading Bitsproxy.dll, qmgrprxy.dll or  Microsoft.BackgroundIntelligentTransfer.Management.Interop.dll and a Server (svchost.exe with the process's command-line value contains the keyword "BITS" and hosting the service DLL qmgr.dll):

Figure 1 - BITS Client

Figure 2 - BITS Server

Communication between the BITS client and server is performed via RPC, and the IBackgroundCopyManager  is the main BITS interface used to enumerate or create new BITS Jobs:

Figure 3 - OleView  of the BITS service exposed interfaces

  Figure 4 - BITS IBackgroundCopyManager Interface exposed Methods

Figure 5 - BITS JOB TYPE

From a behavior perspective all the download and upload activities are performed by the BITS server (svchost.exe) impersonating the BITS client which breaks the link between the client and the server if using standard monitoring telemetry such as Sysmon network and file creation events.

BITS can be also abused for persistence by setting a command to run every time a transfer job enters the BG_JOB_STATE_ERROR or BG_JOB_STATE_TRANSFERRED state using the IBackgroundCopyJob2::SetNotifyCmdLine method (i.e. bitsadmin.exe /SetNotifyCmdLine) which will result in a malicious program or command to be run persistently on a target system.

 Figure 6 - BITS SetNotifyCmdLine Parameters

Detection and Hunting

From a detection and forensics perspective Windows provides good logging events for the BITS client activities via the Microsoft-Windows-Bits-Client provider (enabled by default), key events are:
  • EventID 3 - BITS service created a new Job
  • EventID 59 - BITS started the <jobname> transfer job that is associated with URL.
  • EventID 60 - BITS stopped transferring the <jobname> transfer job that is associated with the URL. The status code is 0xxxx.
  • EventID 4 - The transfer job is complete
  • EventID 5 - Job cancelled.
  • Other events that are related to performance and transfer errors
Events such as 59, 60 and 61 contains the download/upload URL (very useful for forensics and detection) and event 3 contains the details of the BITS client process path and the Job name (very useful for detecting abnormal BITS clients).

Below example of BITS events resulting from this malware sample (Remcos or Netwire RAT loader):

  Figure 7 - BITS Client Event Logs 3 and 60        

A)  Unusual BITS Client:

By default on a Windows machine there are a limited number of BITS clients (native Windows binaries) and the majority are related to third party programs such as browsers. To baseline the clients we can use Bitsproxy.dll or qmgrprxy.dll ImageLoad events (such as Sysmon EventId 7) or BITS Client Event Logs EventId 3.

By default the following are the known normal BITS client with process path residing under c:\windows\ directory.

c:\Windows\System32\MRT.exe (x)
c:\Windows\System32\svchost.exe (BITS service)

Excluding the above we can hunt/detect for unusual client, below an example of a hunting EQL query:

Figure 8 - Unusual Bits Client Hunt

Figure 9 - Notepad.exe Unusual BITS Client

B) Program Execution via BITS SetNotifyCmdline Persistence: 

Programs set to execute via the SetNotifyCmdline method are a child of the BITS service, there are some legit instances especially signed stuff running from program files directories, but its quite rare:

Figure 10 - Hunt Example for Persistence via BITS SetNotifyCmdline Method

Figure 11 - Malware example persisting via BITS SetNotifyCmdline Method

C) Execution of a File Downloaded via BITS Service:

Last example is to hunt for executable content that is downloaded via BITS service and immediately executed, we can do that by correlating File rename event (old file name always follow this pattern BITXXXX.tmp and renamed to the target file name)  by the BITS service followed by process execution by file.path/process.executable:

Figure 12 - Download & Execution of a file via BITS using PowerShell

As you can see below we can link the file download activity to the process execution event:

Figure 13 - Hunt for Process Execution of a File Downloaded via BITS service

Figure 14 - Hunt Results for Process Execution of a File Downloaded via BITS service

There other scenarios but that should give you an idea of the building blocks and how to play with them to spot unusual combinations.

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 == "werfault.exe" and not 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.


Friday, 27 November 2020

How to Design Detection Logic - Part 1

   In this first part we are going to share with you some common logical and high level steps we tend to follow to design detection logic for a certain attack technique. To make it simple and straightforward we will start with some definitions (to align) and then analyze the following diagram that summarizes big chunks of the process.


  • attack technique: group of small blocks (primitives) chained to bypass a certain security control (e.g. steal secrets, elevate privileges, execute code remote or locally).
  • datasource: mainly logs (host and network) and OS telemetry such as processes execution, file modifications, network connection.
  • detection resilience: high level qualitative metric to measure how easy for an attacker to bypass a certain detection logic (e.g. to detect LSASS memory dump creation we monitor file creation with the name "lsass.dmp". this can be easily bypassed if the attacker has control over the file name).
  • unique changes: if a certain attack primitive  performs a change that happens a lot and in normal conditions (e.g. create a file with extension .tmp or .js in the user temporary directory)  then this change is not unique enough and hence can't be used as an indicator of suspicious activity.
  • context: if a certain change is unique enough to use it as an indicator of suspicious activity, we still have to assess if it provides enough context or it can be associated to 100 techniques.

Step A, consist of identifying all building blocks of certain attack technique, in our example we have 8 primitives for the attack technique X (often involves reading documentation and source code if available and needed).

Step B, consist of identifying what's necessary for the technique success and what's optional from an attacker perspective for the success of the technique, in our example out of 8 primitives only 5 are needed (still green) and the rest are optional and if omitted the technique still works. 

Step C, consist of identifying what's under the attacker control and what's not (e.g. in PM1 the technique needs drop a dll file in the system32 directory, the default name is abc.dll (still can be used as signature) but the attacker controls the name and can set it to more than 20 different unique names). In our example out of 5 necessary PMs, only 3 are non modifiable (still green) and 2 are modifiable (marked as dark green).

Step D, consist of mapping the 5 necessary PM to the relevant datasources we have at our disposition, (e.g. in PM8 Explorer.exe will perform a network connection but we don't collect processes network telemetry). In our example out of 5 PMs we have telemetry for only  3 PMs and the 2 others are opportunities for improvement (marked in purple) and if we encounter a medium to high number of techniques that requires the same type of telemetry then it's worth using it as a justification to enable visibility on those gaps.

Step E, mainly consist of identifying what's normal (happens a lot and if enabled as a detection will DoS your mailbox and SIEM), exclusion opportunities and what's unique enough to use it as an indicator of suspicious activity. This usually involves querying the history of existing datastores and if the number of hits is medium to low then its worth moving to the next step. In our example out of 3 remaining PMs we are left with 2 .

Step F,  In this step we are are left with 2/8 PMs, that can serve as our initial detection scope, we need to assess the detection opportunities we have in term of performance impact, alert context and enrichment options. for instance if PM4 alone is indeed indicative of something suspicious still it can be also associated to other unrelated malicious techniques (context), and for PM5 we need to create a rule that matches against 100 different file names (query time and high performance impact). 

 Following those steps in order is not necessary, and we may have missed (unintentionally) some other important steps. It usually comes to having a good understanding of the offensive technique, filtering out normal behavior while in the same time balancing detection resilience, alert context and performance impact. Also not always we have guarantees to come up with a detection for a TTP, but the ultimate goal is to capture gaps and potential opportunities of improvement. In the upcoming parts we will try to cover each step in details with some practical examples. 

Friday, 4 September 2020

Hunting Local Accounts and Groups Changes using Sysmon

   Visibility on local accounts and groups changes is as important as for Domain ones for both good systems hygiene and security. attackers may add or change existing local account to persist, escalate privileges or simply to bypass any existing known accounts monitoring. In this post we will try to highlight some of the standard options to enable monitoring local accounts and also share some less known tricks that you can leverage using your existing Sysmon or EDR for hunting local accounts activities.

A) Windows Native Event Logs:

Windows provides good auditing for this category of changes under Account Management Audit Policy:


below example of event-id 4720 recording a local account creation activity:

adding user support to the local Administrators group is also covered by event-id 4732:


As can be seen, both events provide good details such as when, who did the action and other relevant details and it's important to capture those events where feasible. This method provides a reasonable resilience level but often subject to common audit policy and central logs collection issues.

B) Process Activity:

This is the most common approach, monitoring system command-line value such as net.exe or net1.exe with args containing keywords such as "/add", "administrators" is good and must have but not that resilient if the same activity is done via  APIs or using an uncommon utility.

C) APIs Hooking:

This approach consists of hooking relevant System APIs such as NetUserAdd, NetLocalGroupAddMemberNetUserSetInfo and NetLocalGroupSetInfo which is indeed a more resilient approach than the Process Command-line one but still subject to evasions techniques such as hooking/unhooking, direct Syscalls or RPC via MS-SAMR (SamrCreateUserInDomain, SamrAddMemberToGroup ):


D) Sysmon:

Sysmon provides great set of events covering different type of actions but none of them is specific to local accounts changes. one easy approach is to monitor process creation with user name like "MachineNamePatterns\*" but this provides clues on the activities conducted by a local account and not related to account creation or modification.

we know also that most local accounts activity tend to be saved on the SAM registry hive, and we also known that Sysmon provides visibility on Registry changes via events 12 (key creation or deletion) and 13 (registry value modification) so let's try to do the same action we did before with ProcMon ON and see if there are any relevant changes we can use for hunting:

Main changes that are relevant to our immediate hunting needs are:

  • New Local Account Name means new registry key HKLM\SAM\SAM\DOMAINS\Account\Users\Names\<accountname> (Sysmon 12 👍):

  • Similar to account creation, local account deletion can be detected using Sysmon EventID 12 (EventType eq to DeleteKey):

  • Account added or deleted from local Administrators Group means changes to HKLM\SAM\SAM\Domains\Builtin\Aliases\00000220\ 
00000220 is the local Administrators group Alias on Windows

which we can also confirm by looking at the changed binary data value

 000003F8 is a unique key name (RID) associated to the account support which was appended to the Administrators Alias C value: