
수동으로 Minidump 파일을 작성하여 NTAPI 함수만으로 lsass를 덤프합니다 (MiniDumpWriteDump 사용 없이!!!)
NativeDump는 NTAPI만을 사용하여 lsass 프로세스를 덤프하고, Minidump 파일을 생성합니다. 이 파일은 Mimikatz나 Pypykatz 같은 도구가 파싱하는 데 필요한 스트림(SystemInfo, ModuleList, Memory64List Stream)만 포함합니다.

이 프로그램은 출력 파일에 대한 선택적 인수를 하나 가지며, 기본 파일 이름은 "proc_<PID>.dmp"입니다:
NativeDump.exe [DUMP_FILE]

이 도구는 최신 Windows 버전과 가장 일반적인 보안 솔루션(Microsoft Defender for Endpoints, CrowdStrike 등)에서 테스트되었으며 잘 작동하지만, 은밀성은 선택한 "변형(flavour)"에 따라 달라집니다. 최상의 결과를 위해 비일반적인 언어를 사용하고 바이너리를 커스터마이징하세요! 그러나 PPL이 활성화되어 있거나 PEB 구조를 읽을 수 없는 경우 작동하지 않습니다. 업데이트: 이제 PEB를 읽지 않고도 프로그램을 실행할 수 있습니다. peb-unreadable 브랜치를 확인하세요 :)
이 기술의 장점은 다음과 같습니다:
다양한 "변형(flavour)"(또는 언어)으로 프로젝트를 확인할 수 있습니다:
main - .NET 기본 구현 (이 브랜치)
python-flavour - Python 구현, 3가지 ntdll.dll 덮어쓰기 방법 + 원격 머신으로 유출
golang-flavour - Golang 구현, 3가지 ntdll.dll 덮어쓰기 방법 + 원격 머신으로 유출
c-flavour - C/C++ 구현, 3가지 ntdll.dll 덮어쓰기 방법
bof-flavour - BOF 파일, 3가지 ntdll.dll 덮어쓰기 방법
rust-flavour - @safedv의 Rust 구현
crystal-flavour - Crystal 구현, ntdll.dll 덮어쓰기 기능
nim-flavour - Nim 구현, ntdll.dll 덮어쓰기 기능
.NET을 사용하는 기타 흥미로운 브랜치:
remote - 원격 머신으로 유출 + 3가지 ntdll.dll 덮어쓰기 방법 + 동적 함수 해결 + 문자열 AES 암호화 + XOR-인코딩 Minidump 내용
all-modules - 모든 모듈(lsasrv.dll뿐만 아니라)에 대한 정보 획득
peb-unreadable - lsass의 PEB 구조를 읽지 않는 구현 + 3가지 ntdll.dll 덮어쓰기 방법
Minidump의 문서화되지 않은 구조를 읽은 후, 그 구조는 다음과 같이 요약됩니다:

도움이 될 수 있는 파싱 도구를 만들었습니다: MinidumpParser. Mimikatz/Pypykatz가 Minidump 파일을 파싱하는 데 필요한 헤더, 스트림 디렉터리 및 SystemInfo, ModuleList, Memory64List Stream의 세 가지 스트림만으로 유효한 파일을 생성하는 데 초점을 맞출 것입니다.
헤더는 C#에서 다음과 같이 정의할 수 있는 32바이트 구조체입니다:
public struct MinidumpHeader
{
public uint Signature;
public ushort Version;
public ushort ImplementationVersion;
public ushort NumberOfStreams;
public uint StreamDirectoryRva;
public uint CheckSum;
public IntPtr TimeDateStamp;
}
필요한 값은:
스트림 디렉터리의 각 항목은 12바이트 구조체이므로, 3개의 항목이 있으면 크기는 36바이트입니다. 항목에 대한 C# 구조체 정의는 다음과 같습니다:
public struct MinidumpStreamDirectoryEntry
{
public uint StreamType;
public uint Size;
public uint Location;
}
"StreamType" 필드는 정수 또는 ID로 스트림 유형을 나타냅니다. 가장 관련 있는 것들은 다음과 같습니다:
첫 번째 스트림은 ID 7의 SystemInformation Stream입니다. 크기는 56바이트이며, 스트림 디렉터리 다음인 오프셋 68(0x44)에 위치합니다. C# 정의는 다음과 같습니다:
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;
}
필요한 값은:
두 번째 스트림은 ID 4의 ModuleList Stream입니다. SystemInformation Stream 다음인 오프셋 124(0x7C)에 위치하며, 파싱이 올바르게 되도록 필요한 유일한 모듈인 "lsasrv.dll" 항목 하나만 포함하므로 크기도 112바이트로 고정됩니다.
이 스트림의 일반적인 구조는 항목 수를 포함하는 4바이트 값과 각 모듈에 대한 108바이트 항목으로 구성됩니다:
public struct ModuleListStream
{
public uint NumberOfModules;
public ModuleInfo[] Modules;
}
하나만 있으므로 다음과 같이 단순화됩니다:
public struct ModuleListStream
{
public uint NumberOfModules;
public IntPtr BaseAddress;
public uint Size;
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;
}
필요한 값은:
세 번째 스트림은 ID 9의 Memory64List Stream입니다. ModuleList Stream과 유니코드 문자열 다음인 오프셋 298(0x12A)에 위치하며, 크기는 모듈 수에 따라 달라집니다.
public struct Memory64ListStream
{
public ulong NumberOfEntries;
public uint MemoryRegionsBaseAddress;
public Memory64Info[] MemoryInfoEntries;
}
각 모듈 항목은 16바이트 구조체입니다:
public struct Memory64Info
{
public IntPtr Address;
public IntPtr Size;
}
필요한 값은:
lsass.exe 프로세스의 메모리 영역을 반복하기 위한 전제 조건이 있으며, 이는 NTAPI만 사용하여 해결할 수 있습니다:
이를 통해 다음 호출로 프로세스 메모리를 순회할 수 있습니다:
이전 단계 후 Minidump 파일을 만드는 데 필요한 모든 것을 갖추게 됩니다. 파일을 로컬에 생성하거나 바이트를 원격 머신으로 보낼 수 있으며, 그 전에 바이트를 인코딩하거나 암호화할 수도 있습니다. 이러한 가능성 중 일부는 delegates 브랜치(로컬로 생성된 파일을 XOR로 인코딩 가능)와 remote 브랜치(원격 머신으로 보내기 전에 파일을 XOR로 인코딩 가능)에서 코딩되었습니다.
Minidump 파일 생성을 피하는 대안적인 접근 방식은 TrickDump를 확인하세요: 세 개의 JSON 파일과 ZIP 아카이브를 생성하며, Minidump는 공격자의 머신에서 재구성됩니다. 이는 Minidump 생성 또는 유출을 모니터링하는 보안 솔루션을 회피하는 데 도움이 될 수 있습니다.
| ID | 스트림 유형 |
|---|
| 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 |