Deploying Detections at Scale — Part 0x01 use-case format and automated validation
FalconFriday — Detecting LSASS dumping with debug privileges — 0xFF1F
September 16, 2022

Olaf Hartong

Credential dumping from Local Security Authority Subsystem Service

As you know, there are various ways of dumping credentials. On the endpoint, in most cases, credentials are gathered from the Local Security Authority Subsystem Service (LSASS).

Dumping credentials from the LSASS process can be done in various ways. The most straightforward way is using the Win32 API MiniDumpWriteDump. However, since this method is detected by almost every AV/EDR, we’re going to look at something a bit more advanced.

The MiniDumpWriteDump function is essentially a wrapper around reading memory from another process and writing it in the minidump format. Since the format is public, we can also get the same output by implementing this dumping functionality ourselves. One of the tools that has an implementation of MiniDumpWriteDump (along with many other features) is Nanodump, which is created by HelpSystems. Since this tool has an implementation of many different credential dumping methods, I strongly encourage you to start experimenting with it against your EDR and detection rules. In our experience, quite a lot of these credential dumping variations were not alerted on by EDRs. However, in most cases they can be detected by writing custom detections.

Most of the variations rely on a handle on the process, so that would be an interesting starting point.

Getting a handle

When a user logs in to a machine, the system collects a set of data that uniquely identifies the user during the authentication process, and stores it in an access token. This access token holds the security context of all processes which the user has initiated. The security context of a process is the set of credentials given to the process or the user account that created the process.

The access request rights on the handles are fortunately well documented by Microsoft.

The handle requests are also relatively easy to get telemetry on. Sysmon has the option to configure EventID 10 and Defender for Endpoint logs it to the DeviceEvents table via the OpenProcessApi ActionType.

Please note the emphasis on requests, since a process can ask for more process-specific access rights than it will actually use.

The minimum access rights a process needs to read the memory of another process are PROCESS_QUERY_LIMITED_INFORMATION (0x1000) and PROCESS_VM_READ (0x10).

This access request can be padded with all kinds of non-required rights to make the detection a little bit more complicated, depending on the tool you use. Sysmon for instance, when set to log all handle requests, will be way to noisy. So usually, these logs are filtered on the commonly observed access rights combinations to certain processes; to get the volume to a more manageable size. By padding an access request with additional rights, it allows an attacker to stay hidden with that action. Depending on your EDR solution, it may filter on only the handles requested to certain processes, for instance, lsass.exe and itself, and possibly even limiting the number of repetitive requests being logged.

One way some implementations of the dumping techniques get the memory, is just to request full access rights to the lsass.exe process. You might think, “this should immediately stand out and is easy to spot”. Well, it turns out it is not…Sadly this is super common.

A count for distinct processes requesting full access to the LSASS process across an enterprise.

As is visible from the screenshot above, over 140 distinct processes do this almost 2 million times over the span of a week. This is partially required, partially lazy programming and often totally benign and unused. However, in isolation, also a pretty rubbish detection and at best a possible hunting starting point.

Token privileges

However, reading the documentation properly helps us again here. To open a handle to another process and obtain full access rights, you must enable the SeDebugPrivilege privilege. This requires the process to run with high integrity which might prompt UAC, depending on the configuration of the system. This can obviously be bypassed as well, but this is outside of the scope of this blog. The enabling of the SeDebugPrivilege privilege also requires changing your current access token.

Token privileges for a generic high-integrity process.

By default, most high-integrity processes do not have the SeDebugPrivilege privilege enabled as can be seen above.

Token privileges for task manager, which has debug privileges and runs with high integrity.

If you want to learn more about tokens and what they can be (ab)used for, I highly recommend reading Jonny Jonson’s blog using this in other detections. For the purpose of this blog, let’s focus on the behavior of enabling the SeDebugPrivilege privilege, which results in an access token modification.

Detecting the addition of the SeDebugPrivilege privilege

So, obviously we would like to be able to monitor for this behavior on changing these token permissions. Fortunately, there are options, even native ones if you have those available. Windows offers events for this natively with event ID 4703, when you have the right audit policy enabled. You can validate this with the following command:AuditPol.exe /get /subcategory:”Authorization Policy Change”.

However, when you are an MDE user you’re in luck: these token modification events are also available under the DeviceEvents as the ProcessPrimaryTokenModified actiontype.

Additional fields example from a ProcessPrimaryTokenModified event

Additional fields example from a ProcessPrimaryTokenModified event.

Now, there is a small catch here: the MDE telemetry provides you with the original token and the current one, as a decimal value. Fortunately, the Kusto Query Language (KQL) can help us out here.

Bitwise calculations

After some digging around online to find the hex representation of the SeDebugPrivilege, we came across this presentation by Cem Gurkok to show us which bits can be set for which privilege.

Token privilege permissions with their corresponding index positions.

This allows us to create a variable which we can use in our query to do some bitwise calculations. In KQL there is a binary_shift_left function to make this easier for us. This function does exactly what you would expect from the name. It creates a binary field, and allows you to set a bit sequence and move it to the left, to the position you require. In our case, this would be a single bit on index position 20 (the 21st bit); resulting in a binary value of 10000000000000000000. In KQL, this looks as follows:

let SeDebugPrivilege = binary_shift_left(1, 20);

We can still convert it to other representations if we like. For example, to a hex or decimal value as well. We don’t require that now, but it can come in handy sometimes.

Converting a binary value example to decimal or hex.

Now that we know the value we are looking for in the changed token, we can use another function in KQL to find out whether our SeDebugPrivilege bit has been set in the new token value. One approach for this is to use the binary_and function. Without going too deep into this, the binary and allows you to check whether a certain bit is present in another value.

Binary and example.

The way this works is: we take a value (in the left example above of 0x33 or the binary equivalent 00110011), and then we do a binary and of 0x02 or 00000010. The outcome of this operation results in the bits that match; so in this example 0x02 or 00000010. In the right example, we take the same value of 0x33 or the binary equivalent 00110011, and then we do a binary and of 0x04 or 00000100. Since none of the bits match, the result is 00000000.

This allows us to check tokens with the binary_and function with the binary representation of the SeDebugPrivilege flag to see whether is has been enabled in the modified token.

A count for distinct processes changing their access token to add at least the SeDebugPrivilege privilege across an enterprise.

Again, you might expect that this should be quite rare. Sadly, as before it is not… There are probably all kinds of reasons for this. However, it also is highly unlikely we can change this.

Now, when we merge these two somewhat noisy events together, we get to a result that is very manageable. The example below shows the results of a week’s worth of events across a sizable enterprise environment. This is something to investigate and filter where these actions are benign.

Results of the complete query over a week across 100k devices.

As usual, the full query can be found here in our repository.

Wrapping up

As mentioned at the start of this post, there are several other methods of dumping credentials from the LSASS process, or carving it out live. A lot of them are (partially) detected out of the box, but still a substantial number are not. This detection only covers a specific implementation of the credential dumping technique.

The primary goal of this blog post is to inspire you to make the most use of your telemetry, investigate how these dumping variations can be detected.

Knowledge center

Other articles

FalconHound, attack path management for blue teams

FalconHound, attack path management for blue teams

[dsm_breadcrumbs show_home_icon="off" separator_icon="K||divi||400" admin_label="Supreme Breadcrumbs" _builder_version="4.18.0" _module_preset="default" items_font="||||||||" items_text_color="rgba(255,255,255,0.6)" custom_css_main_element="color:...

Together. Secure. Today.

Stay in the loop and sign up to our newsletter

FalconForce realizes ambitions by working closely with its customers in a methodical manner, improving their security in the digital domain.

Energieweg 3
3542 DZ Utrecht
The Netherlands

FalconForce B.V.
[email protected]
(+31) 85 044 93 34

KVK 76682307
BTW NL860745314B01