Remote Interactive Task Manager LSASS Dump
Contents
Remote Interactive Task Manager LSASS Dump#
Hypothesis#
Adversaries might be RDPing to computers in my environment and interactively dumping the memory contents of LSASS with task manager.
Technical Context#
Offensive Tradecraft#
The Windows Task Manager may be used to dump the memory space of lsass.exe to disk for processing with a credential access tool such as Mimikatz. This is performed by launching Task Manager as a privileged user, selecting lsass.exe, and clicking “Create dump file”. This saves a dump file to disk with a deterministic name that includes the name of the process being dumped.
Pre-Recorded Security Datasets#
| Metadata | Value | 
|---|---|
| docs | https://securitydatasets.com/notebooks/atomic/windows/credential_access/SDWIN-191027055035.html | 
| link | 
Download Dataset#
import requests
from zipfile import ZipFile
from io import BytesIO
url = 'https://raw.githubusercontent.com/OTRF/Security-Datasets/master/datasets/atomic/windows/credential_access/host/rdp_interactive_taskmanager_lsass_dump.zip'
zipFileRequest = requests.get(url)
zipFile = ZipFile(BytesIO(zipFileRequest.content))
datasetJSONPath = zipFile.extract(zipFile.namelist()[0])
Read Dataset#
import pandas as pd
from pandas.io import json
df = json.read_json(path_or_buf=datasetJSONPath, lines=True)
Analytics#
A few initial ideas to explore your data and validate your detection logic:
Analytic I#
Look for taskmgr creating files which name contains the string lsass and with extension .dmp.
| Data source | Event Provider | Relationship | Event | 
|---|---|---|---|
| File | Microsoft-Windows-Sysmon/Operational | Process created File | 11 | 
Logic#
SELECT `@timestamp`, Hostname, Image, TargetFilename, ProcessGuid
FROM dataTable
WHERE Channel = "Microsoft-Windows-Sysmon/Operational"
    AND EventID = 11
    AND Image LIKE "%taskmgr.exe"
    AND lower(TargetFilename) RLIKE ".*lsass.*\.dmp"
Pandas Query#
(
df[['@timestamp','Hostname','Image','TargetFilename','ProcessGuid']]
[(df['Channel'] == 'Microsoft-Windows-Sysmon/Operational')
    & (df['EventID'] == 11)
    & (df['Image'].str.lower().str.endswith('taskmgr.exe', na=False))
    & (df['TargetFilename'].str.lower().str.contains('.*lsass.*dmp', regex=True))
]
)
Analytic II#
Look for task manager access lsass and with functions from dbgcore.dll or dbghelp.dll libraries.
| Data source | Event Provider | Relationship | Event | 
|---|---|---|---|
| Process | Microsoft-Windows-Sysmon/Operational | Process accessed Process | 10 | 
Logic#
SELECT `@timestamp`, Hostname, SourceImage, TargetImage, GrantedAccess
FROM dataTable
WHERE Channel = "Microsoft-Windows-Sysmon/Operational"
    AND EventID = 10
    AND lower(SourceImage) LIKE "%taskmgr.exe"
    AND lower(TargetImage) LIKE "%lsass.exe"
    AND (lower(CallTrace) RLIKE ".*dbgcore\.dll.*" OR lower(CallTrace) RLIKE ".*dbghelp\.dll.*")
Pandas Query#
(
df[['@timestamp','Hostname','SourceImage','TargetImage','GrantedAccess','CallTrace']]
[(df['Channel'] == 'Microsoft-Windows-Sysmon/Operational')
    & (df['EventID'] == 10)
    & (df['SourceImage'].str.lower().str.endswith('taskmgr.exe', na=False))
    & (df['TargetImage'].str.lower().str.endswith('lsass.exe', na=False))
    & (
        (df['CallTrace'].str.lower().str.contains('.*dbgcore.*', regex=True))
        | (df['CallTrace'].str.lower().str.contains('.*dbghelp.*', regex=True))
    )
]
.head()
)
Analytic III#
Look for any process accessing lsass and with functions from dbgcore.dll or dbghelp.dll libraries.
| Data source | Event Provider | Relationship | Event | 
|---|---|---|---|
| Process | Microsoft-Windows-Sysmon/Operational | Process accessed Process | 10 | 
Logic#
SELECT `@timestamp`, Hostname, SourceImage, TargetImage, GrantedAccess
FROM dataTable
WHERE Channel = "Microsoft-Windows-Sysmon/Operational"
    AND EventID = 10
    AND lower(TargetImage) LIKE "%lsass.exe"
    AND (lower(CallTrace) RLIKE ".*dbgcore\.dll.*" OR lower(CallTrace) RLIKE ".*dbghelp\.dll.*")
Pandas Query#
(
df[['@timestamp','Hostname','SourceImage','TargetImage','GrantedAccess','CallTrace']]
[(df['Channel'] == 'Microsoft-Windows-Sysmon/Operational')
    & (df['EventID'] == 10)
    & (df['TargetImage'].str.lower().str.endswith('lsass.exe', na=False))
    & (
        (df['CallTrace'].str.lower().str.contains('.*dbgcore.*', regex=True))
        | (df['CallTrace'].str.lower().str.contains('.*dbghelp.*', regex=True))
    )
]
.head()
)
Analytic IV#
Look for combinations of process access and process creation to get more context around potential lsass dump form task manager or other binaries.
| Data source | Event Provider | Relationship | Event | 
|---|---|---|---|
| Process | Microsoft-Windows-Sysmon/Operational | Process accessed Process | 10 | 
| Process | Microsoft-Windows-Sysmon/Operational | Process created Process | 1 | 
Logic#
SELECT o.`@timestamp`, o.Hostname, o.Image, o.LogonId, o.ProcessGuid, a.SourceProcessGUID, o.CommandLine
FROM dataTable o
INNER JOIN (
    SELECT Hostname,SourceProcessGUID
    FROM dataTable
    WHERE Channel = "Microsoft-Windows-Sysmon/Operational"
        AND EventID = 10
        AND lower(TargetImage) LIKE "%lsass.exe"
        AND (lower(CallTrace) RLIKE ".*dbgcore\.dll.*" OR lower(CallTrace) RLIKE ".*dbghelp\.dll.*")
    ) a
ON o.ProcessGuid = a.SourceProcessGUID
WHERE o.Channel = "Microsoft-Windows-Sysmon/Operational"
    AND o.EventID = 1
Pandas Query#
processCreateDf = (
df[['@timestamp','Hostname','Image','LogonId','ProcessGuid','CommandLine']]
[(df['Channel'] == 'Microsoft-Windows-Sysmon/Operational')
    & (df['EventID'] == 1)
]
)
processAccessDf = (
df[['@timestamp','Hostname','SourceImage','SourceProcessGUID','TargetImage','GrantedAccess','CallTrace']]
[(df['Channel'] == 'Microsoft-Windows-Sysmon/Operational')
    & (df['EventID'] == 10)
    & (df['TargetImage'].str.lower().str.endswith('lsass.exe', na=False))
    & (
        (df['CallTrace'].str.lower().str.contains('.*dbgcore.*', regex=True))
        | (df['CallTrace'].str.lower().str.contains('.*dbghelp.*', regex=True))
    )
]
)
(
pd.merge(processCreateDf, processAccessDf,
    left_on = 'ProcessGuid', right_on = 'SourceProcessGUID', how = 'inner')
)
Analytic V#
Look for binaries accessing lsass that are running under the same logon context of a user over an RDP session.
| Data source | Event Provider | Relationship | Event | 
|---|---|---|---|
| Process | Microsoft-Windows-Sysmon/Operational | Process accessed Process | 10 | 
| Process | Microsoft-Windows-Sysmon/Operational | Process created Process | 1 | 
| Authentication log | Microsoft-Windows-Security-Auditing | User authenticated Host | 4778 | 
Logic#
SELECT o.`@timestamp`, o.Hostname, o.SessionName, o.AccountName, o.ClientName, o.ClientAddress
FROM dataTable o
INNER JOIN (
    SELECT LogonId, Image, CommandLine
    FROM (
        SELECT o.Image, o.LogonId, o.CommandLine
        FROM dataTable o
        INNER JOIN (
            SELECT Hostname,SourceProcessGUID
            FROM dataTable
            WHERE Channel = "Microsoft-Windows-Sysmon/Operational"
                AND EventID = 10
                AND lower(TargetImage) LIKE "%lsass.exe"
                AND (lower(CallTrace) RLIKE ".*dbgcore\.dll.*" OR lower(CallTrace) RLIKE ".*dbghelp\.dll.*")
            ) a
        ON o.ProcessGuid = a.SourceProcessGUID
        WHERE o.Channel = "Microsoft-Windows-Sysmon/Operational"
            AND o.EventID = 1
        )
    ) a
ON o.LogonID = a.LogonId
WHERE lower(o.Channel) = "security"
    AND o.EventID = 4778
Pandas Query#
processCreateDf = (
df[['@timestamp','Hostname','Image','LogonId','ProcessGuid','CommandLine']]
[(df['Channel'] == 'Microsoft-Windows-Sysmon/Operational')
    & (df['EventID'] == 1)
]
)
processAccessDf = (
df[['@timestamp','Hostname','SourceImage','SourceProcessGUID','TargetImage','GrantedAccess','CallTrace']]
[(df['Channel'] == 'Microsoft-Windows-Sysmon/Operational')
    & (df['EventID'] == 10)
    & (df['TargetImage'].str.lower().str.endswith('lsass.exe', na=False))
    & (
        (df['CallTrace'].str.lower().str.contains('.*dbgcore.*', regex=True))
        | (df['CallTrace'].str.lower().str.contains('.*dbghelp.*', regex=True))
    )
]
)
firstJoinDf = (
pd.merge(processCreateDf, processAccessDf,
    left_on = 'ProcessGuid', right_on = 'SourceProcessGUID', how = 'inner')
)
sessionReconnectDf = (
df[['@timestamp','Hostname','LogonID','SessionName','AccountName','ClientName','ClientAddress']]
[(df['Channel'].str.lower() == 'security')
    & (df['EventID'] == 4778)
]
)
(
pd.merge(firstJoinDf, sessionReconnectDf,
    left_on = 'LogonId', right_on = 'LogonID', how = 'inner')
)
Known Bypasses#
False Positives#
Hunter Notes#
- Add context to your queries by joining RDP remote interactive authentication events by the logon ID. 
 
      
      
      