skip to content

Which LSASS dumping variants does a sweep of Sysmon Event ID 10 process access miss?

level: middleimportance: should knowfreq 42%

answer

  1. the record is a handle grant
  2. the mask bit, not the tool name
  3. kernel callback below user-mode hooks
  4. kernel-mode reads request no handle
  5. clone target is not lsass.exe

basics

~20 s

Sysmon Event ID 10 records one process opening a handle to another, with the access mask granted. It catches user-mode dumpers, including direct-syscall ones, but not a signed driver reading memory from kernel mode, nor a read aimed at a forked clone.

solid answer

~50 s

Event ID 10 is Sysmon's ProcessAccess record: `SourceImage`, `TargetImage`, `GrantedAccess` and a `CallTrace`. A sweep filtering on `TargetImage` ending in `lsass.exe` with a mask including `PROCESS_VM_READ` (`0x0010`) covers the `comsvcs.dll` MiniDump route, any renamed dumping utility, and an implant issuing direct syscalls — direct syscalls bypass user-mode API hooks, but Sysmon's ProcessAccess comes from a kernel object-access callback, so the record is still written, usually with an odd unbacked `CallTrace`. Two variants slip through: a vulnerable signed driver reading the memory from kernel mode never requests a user-mode handle, and a variant that snapshots or forks the process reads a clone whose image is not `lsass.exe`. Those need other records — driver-load and service-creation events, and the dump file appearing on disk. And note what the record proves: read rights were granted, not that memory was read.

code

text · 7 lines
text
EventID:      10                (Sysmon ProcessAccess)
SourceImage:  C:\Windows\System32\rundll32.exe
TargetImage:  C:\Windows\System32\lsass.exe
GrantedAccess: 0x1410          (QUERY_LIMITED_INFORMATION | QUERY_INFORMATION | VM_READ)
CallTrace:    C:\Windows\SYSTEM32\ntdll.dll+... | C:\Windows\System32\comsvcs.dll+...
SourceUser:   CORP\svc-backup
...

go deeper

for a junior

Know that this record means one process opened a handle to another, and that the granted-access mask is the field that says whether the handle could read memory at all.

for a middle

Be ready to name the read bit, explain why a renamed binary changes nothing about the record, and say which variants the sweep does and does not see.

for a senior

Demonstrate that you choose an observable knowing its blind spots, pair it with driver-load and file-create records, and can defend precisely what a hit proves and what it does not.

for a principal

Own the coverage statement: when a variant has no observable at all in this estate, that is a telemetry investment decision, not a hunt finding, and it belongs in front of whoever funds endpoint sensors.

## What the record actually is Sysmon **Event ID 10** is `ProcessAccess`: it is written when one process opens a handle to another. The fields that carry the meaning are `SourceImage` (who asked), `TargetImage` (what they asked for), `GrantedAccess` (the rights the kernel actually granted, as a bitmask) and `CallTrace` (the stack of modules the request came through). It is not a record that memory was read. It is a record that a handle with certain rights was granted. The mask is the discriminating field. The bits that matter for reading another process's memory are `PROCESS_VM_READ` (`0x0010`), usually alongside `PROCESS_QUERY_INFORMATION` (`0x0400`) or `PROCESS_QUERY_LIMITED_INFORMATION` (`0x1000`), which is why masks such as `0x1010` and `0x1410` recur in this hunt. A handle granted only `PROCESS_QUERY_LIMITED_INFORMATION` cannot read memory at all, so filtering on the read bit rather than on any access to the target is what keeps the result set finite. ## What the sweep does cover Run across the estate, a `TargetImage` / read-bit filter covers most of the procedure list at once: - **`rundll32` invoking the `MiniDump` export of `comsvcs.dll`.** Nothing is dropped on the host and the calling binary is a Microsoft one, so nothing about the *tool* is suspicious — but the handle is still opened, and `CallTrace` shows `comsvcs.dll` in the stack. - **A renamed dumping utility.** The name in `SourceImage` is whatever the operator chose. It does not matter: the handle open is the same. - **An implant issuing direct syscalls.** This is the variant people expect to evade the record, and it usually does not. Direct syscalls exist to bypass **user-mode API hooks** that some products place in `ntdll.dll`. Sysmon's ProcessAccess telemetry comes from a kernel-registered object-access callback, which sits below that. The record still appears, and the `CallTrace` is itself informative: a stack returning into unbacked memory rather than into a known module is unusual on its own. ## What it misses, and this is the point of the leaf **The kernel-driver variant.** If an operator loads a signed but vulnerable driver and has it read the target's memory from kernel mode, there is no user-mode handle request, so no ProcessAccess record is ever written. This is not a tuning problem or a coverage gap you can filter your way out of; the observable simply does not exist. It needs different records — driver load (Sysmon **Event ID 6**), the service creation that installed the driver, and the dump file's appearance on disk (Sysmon **Event ID 11**, FileCreate). **The clone variant.** Some implementations snapshot or fork the target and dump the copy. The read that matters then targets a child object whose image is not `lsass.exe`, so a filter pinned to `TargetImage` never matches it. The handle open that *created* the clone may still be visible, which is why the smarter sweep also looks for unusual access masks against the credential process rather than only read masks — but you should treat this variant as partially covered and say so. ## Pair the observable, do not trust it alone A mature version of this hunt runs the handle-access sweep and, alongside it, looks for the artefacts the dump has to leave elsewhere: a large file written by an unexpected process, a driver loaded on a workstation that loads no drivers, a service created and immediately deleted. Each of those is individually noisier; together with the handle record they discriminate far better than any one of them. ## Getting the direction of the claim right The most common wrong answer in this area is to read a ProcessAccess hit as evidence that credentials were stolen. It is not. It is evidence that a handle with read rights was granted. Whether memory was read, whether a dump was produced, whether it left the host — each of those is a separate question needing separate evidence. Conversely, a benign hit is extremely common: endpoint protection agents, backup and inventory software, performance tooling and the built-in task manager all legitimately open read handles to that process, and several do it on a timer. Those are **benign true positives** — the behaviour genuinely occurred and is genuinely not malicious — not false positives, and calling them the wrong thing leads people to try to fix the sweep instead of filtering it. ## The takeaway shape of the answer Name the record and its fields, name the mask bit that carries the meaning, list which variants the sweep covers and *why* direct syscalls do not escape it, then name the two it cannot see and the records that would. An interviewer is checking whether you know that choosing one observable is choosing a specific set of blind spots, and whether you can enumerate yours rather than assuming full coverage.

  • What does a GrantedAccess value of 0x1410 tell you, and what does it not?
    It is `PROCESS_QUERY_LIMITED_INFORMATION` | `PROCESS_QUERY_INFORMATION` | `PROCESS_VM_READ`, so the handle carries enough rights to read the target's memory, which is what a dump requires. What it does not tell you is that memory was read, that a dump file was produced, or that anything left the host. Each of those needs its own evidence.
  • Why doesn't a direct-syscall implementation evade this record?
    Direct syscalls exist to skip user-mode API hooks placed in `ntdll.dll`. The ProcessAccess record comes from a kernel object-access callback, which sits below the layer being skipped, so the event is still written. The `CallTrace` often gets *more* suspicious, showing a return into unbacked memory rather than into a known module.
  • If this sweep is blind to the driver variant, what else could catch it?
    Driver-load telemetry (Sysmon Event ID 6) and the service creation that installs the driver, plus the dump file landing on disk. On a workstation fleet a newly loaded third-party driver is rare enough to hunt on directly. Record it as a variant covered by a different observable rather than as covered by this sweep.
  • Task Manager and your EDR agent both appear in the results. How do you classify them?
    As benign true positives: the behaviour really happened and is genuinely legitimate. That matters, because a false positive means the query was wrong and should be fixed, while a benign true positive means the query was right and the result needs filtering. Mislabelling them leads people to weaken the sweep instead of excluding known-good sources.

saying these in an interview costs you the question

  • Reads a handle-access record as proof memory was read
  • Assumes direct syscalls defeat kernel-callback telemetry
  • Filters on any access to the process instead of the read bit
  • Calls the technique fully covered by one observable
  • Labels the endpoint agent's own access a false positive

context