The Local Security Authority Subsystem Service (LSASS) is a critical process in Windows responsible for enforcing the security policy on the system. It handles authentication, password changes, and the generation of access tokens. Due to its vital role in managing credentials, LSASS has become a prime target for attackers who seek to extract sensitive information, such as password hashes and Kerberos tickets.
This article presents a guide on how to dump the memory of the LSASS process using direct syscalls, which can help evade detection by security tools that monitor traditional API calls. We will provide a detailed explanation of the code used to perform this operation and discuss the associated risks and ethical considerations.
What is LSASS?
LSASS (Local Security Authority Subsystem Service) is a process that manages various aspects of local security authority policies in Windows operating systems. It is responsible for handling user logins, password changes, and creating access tokens that are used by other processes to authenticate the users. The LSASS process also stores password hashes, which can be extracted if the process's memory is dumped. This makes LSASS a critical target for attackers aiming to collect credentials.
Why Dump LSASS?
Dumping the LSASS process's memory allows attackers to retrieve sensitive information such as password hashes, Kerberos tickets, and plaintext passwords (if stored in memory). This information can then be used to escalate privileges, perform lateral movement within the network, or conduct further attacks against other systems.
Security tools like antivirus (AV) and endpoint detection and response (EDR) solutions monitor LSASS closely. They typically detect and block attempts to access or dump its memory using known techniques. Direct syscalls offer a way to bypass such monitoring by directly interacting with the kernel without triggering these security mechanisms.
Implementing LSASS Dump with Direct Syscalls
The following code example demonstrates how to dump the memory of the LSASS process using direct syscalls. The code is split into three files:
LsassDumpSyscall.cpp: The main C++ file that initializes the syscalls and creates the LSASS memory dump.
syscall.asm: The assembly file defining the direct syscall routines.
syscall.h: The header file containing the syscall prototypes and function pointer definitions.
LsassDumpSyscall.cpp
This C++ file contains the logic to find the LSASS process, enable the necessary privileges, and create a memory dump using direct syscalls.
This header file contains the prototypes for the syscalls and function pointer definitions.
#pragmaonce#include<Windows.h>#include<winternl.h>// For original definitions of structures and types like CLIENT_ID// Prototypes for the functions with the correct signaturesEXTERN_C NTSTATUS ZwOpenProcess10(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, CLIENT_ID* ClientId);
EXTERN_C NTSTATUS ZwClose10(HANDLE Handle);EXTERN_C NTSTATUS ZwWriteVirtualMemory10(HANDLE ProcessHandle, PVOID BaseAddress, LPCVOID Buffer, SIZE_T BufferSize, PSIZE_T NumberOfBytesWritten);
EXTERN_C NTSTATUS ZwProtectVirtualMemory10(HANDLE ProcessHandle, PVOID* BaseAddress, SIZE_T* NumberOfBytesToProtect, ULONG NewAccessProtection, PULONG OldAccessProtection);
EXTERN_C NTSTATUS ZwQuerySystemInformation10(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
EXTERN_C NTSTATUS NtCreateFile10(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO
_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
// Global function pointers for dynamic resolution, if neededPFN_ZwOpenProcess g_ZwOpenProcess =nullptr;PFN_ZwClose g_ZwClose =nullptr;PFN_ZwWriteVirtualMemory g_ZwWriteVirtualMemory =nullptr;PFN_ZwProtectVirtualMemory g_ZwProtectVirtualMemory =nullptr;PFN_ZwQuerySystemInformation g_ZwQuerySystemInformation =nullptr;PFN_NtCreateFile g_NtCreateFile =nullptr;
How It Works
Initialize Syscalls: The InitializeSystemCalls function maps the syscall numbers to their corresponding routines defined in the assembly file. This ensures that the correct syscall is invoked based on the system's architecture.
Privilege Elevation: The tool first checks if it is running with elevated privileges using the IsElevated function. If not, it prompts the user to run the tool with the necessary permissions. It then attempts to enable the SeDebugPrivilege, which is required to interact with system processes like LSASS.
Find the LSASS Process ID: The GetLsassPID function uses a snapshot of all running processes to locate the process ID of lsass.exe.
Open LSASS Process: The tool then opens the LSASS process using the direct syscall ZwOpenProcess. This allows it to interact with the process's memory.
Create a Memory Dump: The CreateMiniDump function uses the MiniDumpWriteDump function to create a dump of the LSASS process's memory and save it to a file. This dump can later be analyzed to extract sensitive information.
Close Handles: Finally, the tool closes the handle to the LSASS process using the ZwClose syscall.
Conclusion
Direct syscalls offer a method to interact with the Windows kernel in a way that can bypass many security mechanisms. By implementing the code provided in this guide, you can create a tool that dumps the LSASS process's memory while potentially evading detection by modern security tools.