24.8 C
New York
Saturday, September 7, 2024

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




Dump Lsass Utilizing Solely Native APIs By Hand-Crafting Minidump Recordsdata (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 needed for the SystemInfo Stream
  • NtQueryInformationProcess and NtReadVirtualMemory to get the lsasrv.dll tackle. That is the one module needed for the ModuleList Stream
  • NtOpenProcess to get a deal with for the lsass course of
  • NtQueryVirtualMemory and NtReadVirtualMemory to loop by the reminiscence areas and dump all potential ones. On the identical time it populates the Memory64List Stream

Utilization:

NativeDump.exe [DUMP_FILE]

The default file identify is “proc_.dmp”:

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

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

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

The challenge has three branches in the intervening time (other than the primary 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 constructions, its construction will be summed as much as:

  • Header: Info 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 kind, complete measurement and placement within the file of every one
  • Streams: Each stream comprises totally different data associated to the method and has its personal format
  • Areas: The precise bytes from the method from every reminiscence area which will be learn

I created a parsing software which will 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 will 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 sector “StreamType” represents the kind of stream as an integer or ID, a few of the most related are:

ID Stream Sort
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 might be positioned 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 kernel32!GetVersionEx or ntdll!RtlGetVersion (we’ll use the latter)


D. ModuleList Stream

Second stream is a ModuleList stream, with ID 4. It’s positioned at offset 124 (0x7C) after the SystemInformation stream and it’ll even have a set measurement, of 112 bytes, since it can 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 mixture of ntdll!NtQueryInformationProcess and ntdll!NtReadVirtualMemory (we’ll use the latter) – Measurement: Obtained including all reminiscence area sizes since BaseAddress till one with a measurement of 4096 bytes (0x1000), the .textual content part of different library – PointerToName: Unicode string construction for the “C:WindowsSystem32lsasrv.dll” string, positioned after the stream itself at offset 236 (0xEC)


E. Memory64List Stream

Third stream is a Memory64List stream, with ID 9. It’s positioned at offset 298 (0x12A), after the ModuleList stream and the Unicode string, and its measurement 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 will be solved utilizing solely NTAPIs:

  1. Receive 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. Receive the method ID. For instance, loop all processes utilizing ntdll!NtGetNextProcess, acquire the PEB tackle with ntdll!NtQueryInformationProcess and use ntdll!NtReadVirtualMemory to learn the ImagePathName discipline 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 data and PROCESS_VM_READ (0x0010) to learn the reminiscence bytes

With this it’s potential to traverse course of reminiscence by calling: – ntdll!NtQueryVirtualMemory: Return a MEMORY_BASIC_INFORMATION construction with the safety sort, state, base tackle and measurement of every reminiscence area – If the reminiscence safety shouldn’t be PAGE_NOACCESS (0x01) and the reminiscence state is MEM_COMMIT (0x1000), that means it’s accessible and dedicated, the bottom tackle and measurement populates one entry of the Memory64List stream and bytes will be added to the file – If the bottom tackle equals lsasrv.dll base tackle, 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’ve all that’s essential to create the Minidump file. We will create a file regionally or ship the bytes to a distant machine, with the potential for encoding or encrypting the bytes earlier than. A few of these potentialities are coded within the delegates department, the place the file created regionally will be encoded with XOR, and within the distant department, the place the file will 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