Saturday, May 3, 2025

Dump Lsass Utilizing Solely Native APIs By Hand-Crafting Minidump Information (With out MinidumpWriteDump!)




NativeDump permits to dump the lsass course of utilizing solely NTAPIs producing a Minidump file with solely the streams wanted to be parsed by instruments like Mimikatz or Pypykatz (SystemInfo, ModuleList and Memory64List Streams).

  • NTOpenProcessToken and NtAdjustPrivilegeToken to get the “SeDebugPrivilege” privilege
  • RtlGetVersion to get the Working System model particulars (Main model, minor model and construct quantity). That is crucial for the SystemInfo Stream
  • NtQueryInformationProcess and NtReadVirtualMemory to get the lsasrv.dll handle. That is the one module crucial for the ModuleList Stream
  • NtOpenProcess to get a deal with for the lsass course of
  • NtQueryVirtualMemory and NtReadVirtualMemory to loop by way of the reminiscence areas and dump all attainable ones. On the identical time it populates the Memory64List Stream

Utilization:

NativeDump.exe [DUMP_FILE]

The default file title is “proc_.dmp”:

Dump Lsass Utilizing Solely Native APIs By Hand-Crafting Minidump Information (With out MinidumpWriteDump!)

The device has been examined towards Home windows 10 and 11 units with the commonest safety options (Microsoft Defender for Endpoints, Crowdstrike…) and is for now undetected. Nevertheless, it doesn’t work if PPL is enabled within the system.

Some advantages of this method are: – It doesn’t use the well-known dbghelp!MinidumpWriteDump operate – It solely makes use of capabilities from Ntdll.dll, so it’s attainable to bypass API hooking by remapping the library – The Minidump file doesn’t should be written to disk, you may switch its bytes (encoded or encrypted) to a distant machine

The mission has three branches in the intervening time (aside from the principle department with the fundamental method):

  • ntdlloverwrite – Overwrite ntdll.dll’s “.textual content” part utilizing a clear model from the DLL file already on disk

  • delegates – Overwrite ntdll.dll + Dynamic operate decision + String encryption with AES + XOR-encoding

  • distant – Overwrite ntdll.dll + Dynamic operate decision + String encryption with AES + Ship file to distant machine + XOR-encoding

Method intimately: Making a minimal Minidump file

After studying Minidump undocumented buildings, its construction might be summed as much as:

  • Header: Data just like the Signature (“MDMP”), the placement of the Stream Listing and the variety of streams
  • Stream Listing: One entry for every stream, containing the sort, complete dimension and placement within the file of every one
  • Streams: Each stream accommodates completely different info associated to the method and has its personal format
  • Areas: The precise bytes from the method from every reminiscence area which might be learn

I created a parsing device which might be useful: MinidumpParser.

We are going to concentrate on creating a sound file with solely the required values for the header, stream listing and the one 3 streams wanted for a Minidump file to be parsed by Mimikatz/Pypykatz: SystemInfo, ModuleList and Memory64List Streams.


A. Header

The header is a 32-bytes construction which might be outlined in C# as:

public struct MinidumpHeader
{
public uint Signature;
public ushort Model;
public ushort ImplementationVersion;
public ushort NumberOfStreams;
public uint StreamDirectoryRva;
public uint CheckSum;
public IntPtr TimeDateStamp;
}

The required values are: – Signature: Fastened worth 0x504d44d (“MDMP” string) – Model: Fastened worth 0xa793 (Microsoft fixed MINIDUMP_VERSION) – NumberOfStreams: Fastened worth 3, the three Streams required for the file – StreamDirectoryRVA: Fastened worth 0x20 or 32 bytes, the dimensions of the header


B. Stream Listing

Every entry within the Stream Listing is a 12-bytes construction so having 3 entries the dimensions is 36 bytes. The C# struct definition for an entry is:

public struct MinidumpStreamDirectoryEntry
{
public uint StreamType;
public uint Measurement;
public uint Location;
}

The sphere “StreamType” represents the kind of stream as an integer or ID, among the most related are:

ID Stream Kind
0x00 UnusedStream
0x01 ReservedStream0
0x02 ReservedStream1
0x03 ThreadListStream
0x04 ModuleListStream
0x05 MemoryListStream
0x06 ExceptionStream
0x07 SystemInfoStream
0x08 ThreadExListStream
0x09 Memory64ListStream
0x0A CommentStreamA
0x0B CommentStreamW
0x0C HandleDataStream
0x0D FunctionTableStream
0x0E UnloadedModuleListStream
0x0F MiscInfoStream
0x10 MemoryInfoListStream
0x11 ThreadInfoListStream
0x12 HandleOperationListStream
0x13 TokenStream
0x16 HandleOperationListStream

C. SystemInformation Stream

First stream is a SystemInformation Stream, with ID 7. The scale is 56 bytes and shall be situated at offset 68 (0x44), after the Stream Listing. Its C# definition is:

public struct SystemInformationStream
{
public ushort ProcessorArchitecture;
public ushort ProcessorLevel;
public ushort ProcessorRevision;
public byte NumberOfProcessors;
public byte ProductType;
public uint MajorVersion;
public uint MinorVersion;
public uint BuildNumber;
public uint PlatformId;
public uint UnknownField1;
public uint UnknownField2;
public IntPtr ProcessorFeatures;
public IntPtr ProcessorFeatures2;
public uint UnknownField3;
public ushort UnknownField14;
public byte UnknownField15;
}

The required values are: – ProcessorArchitecture: 9 for 64-bit and 0 for 32-bit Home windows programs – Main model, Minor model and the BuildNumber: Hardcoded or obtained by way of kernel32!GetVersionEx or ntdll!RtlGetVersion (we’ll use the latter)


D. ModuleList Stream

Second stream is a ModuleList stream, with ID 4. It’s situated at offset 124 (0x7C) after the SystemInformation stream and it’ll even have a hard and fast dimension, of 112 bytes, since it should have the entry of a single module, the one one wanted for the parse to be appropriate: “lsasrv.dll”.

The standard construction for this stream is a 4-byte worth containing the variety of entries adopted by 108-byte entries for every module:

public struct ModuleListStream
{
public uint NumberOfModules;
public ModuleInfo[] Modules;
}

As there is just one, it will get simplified to:

public struct ModuleListStream
{
public uint NumberOfModules;
public IntPtr BaseAddress;
public uint Measurement;
public uint UnknownField1;
public uint Timestamp;
public uint PointerName;
public IntPtr UnknownField2;
public IntPtr UnknownField3;
public IntPtr UnknownField4;
public IntPtr UnknownField5;
public IntPtr UnknownField6;
public IntPtr UnknownField7;
public IntPtr UnknownField8;
public IntPtr UnknownField9;
public IntPtr UnknownField10;
public IntPtr UnknownField11;
}

The required values are: – NumberOfStreams: Fastened worth 1 – BaseAddress: Utilizing psapi!GetModuleBaseName or a mix of ntdll!NtQueryInformationProcess and ntdll!NtReadVirtualMemory (we’ll use the latter) – Measurement: Obtained including all reminiscence area sizes since BaseAddress till one with a dimension of 4096 bytes (0x1000), the .textual content part of different library – PointerToName: Unicode string construction for the “C:WindowsSystem32lsasrv.dll” string, situated after the stream itself at offset 236 (0xEC)


E. Memory64List Stream

Third stream is a Memory64List stream, with ID 9. It’s situated at offset 298 (0x12A), after the ModuleList stream and the Unicode string, and its dimension is dependent upon the variety of modules.

public struct Memory64ListStream
{
public ulong NumberOfEntries;
public uint MemoryRegionsBaseAddress;
public Memory64Info[] MemoryInfoEntries;
}

Every module entry is a 16-bytes construction:

public struct Memory64Info
{
public IntPtr Handle;
public IntPtr Measurement;
}

The required values are: – NumberOfEntries: Variety of reminiscence areas, obtained after looping reminiscence areas – MemoryRegionsBaseAddress: Location of the beginning of reminiscence areas bytes, calculated after including the dimensions of all 16-bytes reminiscence entries – Handle and Measurement: Obtained for every legitimate area whereas looping them


F. Looping reminiscence areas

There are pre-requisites to loop the reminiscence areas of the lsass.exe course of which might be solved utilizing solely NTAPIs:

  1. Get hold of the “SeDebugPrivilege” permission. As an alternative of the standard Advapi!OpenProcessToken, Advapi!LookupPrivilegeValue and Advapi!AdjustTokenPrivilege, we’ll use ntdll!NtOpenProcessToken, ntdll!NtAdjustPrivilegesToken and the hardcoded worth of 20 for the Luid (which is fixed in all newest Home windows variations)
  2. Get hold of the method ID. For instance, loop all processes utilizing ntdll!NtGetNextProcess, acquire the PEB handle with ntdll!NtQueryInformationProcess and use ntdll!NtReadVirtualMemory to learn the ImagePathName area inside ProcessParameters. To keep away from overcomplicating the PoC, we’ll use .NET’s Course of.GetProcessesByName()
  3. Open a course of deal with. Use ntdll!OpenProcess with permissions PROCESS_QUERY_INFORMATION (0x0400) to retrieve course of info and PROCESS_VM_READ (0x0010) to learn the reminiscence bytes

With this it’s attainable to traverse course of reminiscence by calling: – ntdll!NtQueryVirtualMemory: Return a MEMORY_BASIC_INFORMATION construction with the safety sort, state, base handle and dimension of every reminiscence area – If the reminiscence safety shouldn’t be PAGE_NOACCESS (0x01) and the reminiscence state is MEM_COMMIT (0x1000), which means it’s accessible and dedicated, the bottom handle and dimension populates one entry of the Memory64List stream and bytes might be added to the file – If the bottom handle equals lsasrv.dll base handle, it’s used to calculate the dimensions of lsasrv.dll in reminiscence – ntdll!NtReadVirtualMemory: Add bytes of that area to the Minidump file after the Memory64List Stream


G. Creating Minidump file

After earlier steps we have now all that’s essential to create the Minidump file. We will create a file domestically or ship the bytes to a distant machine, with the opportunity of encoding or encrypting the bytes earlier than. A few of these potentialities are coded within the delegates department, the place the file created domestically might be encoded with XOR, and within the distant department, the place the file might be encoded with XOR earlier than being despatched to a distant machine.



Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles

PHP Code Snippets Powered By : XYZScripts.com