1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * PROJECT: ReactOS Application compatibility module 3*c2c66affSColin Finck * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4*c2c66affSColin Finck * PURPOSE: Shim engine core 5*c2c66affSColin Finck * COPYRIGHT: Copyright 2015-2017 Mark Jansen (mark.jansen@reactos.org) 6*c2c66affSColin Finck */ 7*c2c66affSColin Finck 8*c2c66affSColin Finck #define WIN32_NO_STATUS 9*c2c66affSColin Finck #include "ntndk.h" 10*c2c66affSColin Finck #define IN_APPHELP 11*c2c66affSColin Finck #include "shimlib.h" 12*c2c66affSColin Finck #include <strsafe.h> 13*c2c66affSColin Finck /* Make sure we don't include apphelp logging */ 14*c2c66affSColin Finck #define APPHELP_NOSDBPAPI 15*c2c66affSColin Finck #include "apphelp.h" 16*c2c66affSColin Finck #include "shimeng.h" 17*c2c66affSColin Finck 18*c2c66affSColin Finck 19*c2c66affSColin Finck 20*c2c66affSColin Finck FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName); 21*c2c66affSColin Finck BOOL WINAPI SE_IsShimDll(PVOID BaseAddress); 22*c2c66affSColin Finck 23*c2c66affSColin Finck 24*c2c66affSColin Finck extern HMODULE g_hInstance; 25*c2c66affSColin Finck static UNICODE_STRING g_WindowsDirectory; 26*c2c66affSColin Finck static UNICODE_STRING g_System32Directory; 27*c2c66affSColin Finck static UNICODE_STRING g_SxsDirectory; 28*c2c66affSColin Finck ULONG g_ShimEngDebugLevel = 0xffffffff; 29*c2c66affSColin Finck BOOL g_bComPlusImage = FALSE; 30*c2c66affSColin Finck BOOL g_bShimDuringInit = FALSE; 31*c2c66affSColin Finck BOOL g_bInternalHooksUsed = FALSE; 32*c2c66affSColin Finck static ARRAY g_pShimInfo; /* PSHIMMODULE */ 33*c2c66affSColin Finck static ARRAY g_pHookArray; /* HOOKMODULEINFO */ 34*c2c66affSColin Finck static ARRAY g_InExclude; /* INEXCLUDE */ 35*c2c66affSColin Finck 36*c2c66affSColin Finck /* If we have setup a hook for a function, we should also redirect GetProcAddress for this function */ 37*c2c66affSColin Finck HOOKAPIEX g_IntHookEx[] = 38*c2c66affSColin Finck { 39*c2c66affSColin Finck { 40*c2c66affSColin Finck "kernel32.dll", /* LibraryName */ 41*c2c66affSColin Finck "GetProcAddress", /* FunctionName */ 42*c2c66affSColin Finck StubGetProcAddress, /* ReplacementFunction*/ 43*c2c66affSColin Finck NULL, /* OriginalFunction */ 44*c2c66affSColin Finck NULL, /* pShimInfo */ 45*c2c66affSColin Finck NULL /* Unused */ 46*c2c66affSColin Finck }, 47*c2c66affSColin Finck }; 48*c2c66affSColin Finck 49*c2c66affSColin Finck static inline BOOL ARRAY_InitWorker(PARRAY Array, DWORD ItemSize) 50*c2c66affSColin Finck { 51*c2c66affSColin Finck Array->Data__ = NULL; 52*c2c66affSColin Finck Array->Size__ = Array->MaxSize__ = 0; 53*c2c66affSColin Finck Array->ItemSize__ = ItemSize; 54*c2c66affSColin Finck 55*c2c66affSColin Finck return TRUE; 56*c2c66affSColin Finck } 57*c2c66affSColin Finck 58*c2c66affSColin Finck static inline BOOL ARRAY_EnsureSize(PARRAY Array, DWORD ItemSize, DWORD GrowWith) 59*c2c66affSColin Finck { 60*c2c66affSColin Finck PVOID pNewData; 61*c2c66affSColin Finck DWORD Count; 62*c2c66affSColin Finck 63*c2c66affSColin Finck ASSERT(Array); 64*c2c66affSColin Finck ASSERT(ItemSize == Array->ItemSize__); 65*c2c66affSColin Finck 66*c2c66affSColin Finck if (Array->MaxSize__ > Array->Size__) 67*c2c66affSColin Finck return TRUE; 68*c2c66affSColin Finck 69*c2c66affSColin Finck Count = Array->Size__ + GrowWith; 70*c2c66affSColin Finck pNewData = SeiAlloc(Count * ItemSize); 71*c2c66affSColin Finck 72*c2c66affSColin Finck if (!pNewData) 73*c2c66affSColin Finck { 74*c2c66affSColin Finck SHIMENG_FAIL("Failed to allocate %d bytes\n", Count * ItemSize); 75*c2c66affSColin Finck return FALSE; 76*c2c66affSColin Finck } 77*c2c66affSColin Finck Array->MaxSize__ = Count; 78*c2c66affSColin Finck 79*c2c66affSColin Finck if (Array->Data__) 80*c2c66affSColin Finck { 81*c2c66affSColin Finck memcpy(pNewData, Array->Data__, Array->Size__ * ItemSize); 82*c2c66affSColin Finck SeiFree(Array->Data__); 83*c2c66affSColin Finck } 84*c2c66affSColin Finck Array->Data__ = pNewData; 85*c2c66affSColin Finck 86*c2c66affSColin Finck return TRUE; 87*c2c66affSColin Finck } 88*c2c66affSColin Finck 89*c2c66affSColin Finck static inline PVOID ARRAY_AppendWorker(PARRAY Array, DWORD ItemSize, DWORD GrowWith) 90*c2c66affSColin Finck { 91*c2c66affSColin Finck PBYTE pData; 92*c2c66affSColin Finck 93*c2c66affSColin Finck if (!ARRAY_EnsureSize(Array, ItemSize, GrowWith)) 94*c2c66affSColin Finck return NULL; 95*c2c66affSColin Finck 96*c2c66affSColin Finck pData = Array->Data__; 97*c2c66affSColin Finck pData += (Array->Size__ * ItemSize); 98*c2c66affSColin Finck Array->Size__++; 99*c2c66affSColin Finck 100*c2c66affSColin Finck return pData; 101*c2c66affSColin Finck } 102*c2c66affSColin Finck 103*c2c66affSColin Finck static inline PVOID ARRAY_AtWorker(PARRAY Array, DWORD ItemSize, DWORD n) 104*c2c66affSColin Finck { 105*c2c66affSColin Finck PBYTE pData; 106*c2c66affSColin Finck 107*c2c66affSColin Finck ASSERT(Array); 108*c2c66affSColin Finck ASSERT(ItemSize == Array->ItemSize__); 109*c2c66affSColin Finck ASSERT(n < Array->Size__); 110*c2c66affSColin Finck 111*c2c66affSColin Finck pData = Array->Data__; 112*c2c66affSColin Finck return pData + (n * ItemSize); 113*c2c66affSColin Finck } 114*c2c66affSColin Finck 115*c2c66affSColin Finck 116*c2c66affSColin Finck #define ARRAY_Init(Array, TypeOfArray) ARRAY_InitWorker((Array), sizeof(TypeOfArray)) 117*c2c66affSColin Finck #define ARRAY_Append(Array, TypeOfArray) (TypeOfArray*)ARRAY_AppendWorker((Array), sizeof(TypeOfArray), 5) 118*c2c66affSColin Finck #define ARRAY_At(Array, TypeOfArray, at) (TypeOfArray*)ARRAY_AtWorker((Array), sizeof(TypeOfArray), at) 119*c2c66affSColin Finck #define ARRAY_Size(Array) (Array)->Size__ 120*c2c66affSColin Finck 121*c2c66affSColin Finck 122*c2c66affSColin Finck VOID SeiInitDebugSupport(VOID) 123*c2c66affSColin Finck { 124*c2c66affSColin Finck static const UNICODE_STRING DebugKey = RTL_CONSTANT_STRING(L"SHIMENG_DEBUG_LEVEL"); 125*c2c66affSColin Finck UNICODE_STRING DebugValue; 126*c2c66affSColin Finck NTSTATUS Status; 127*c2c66affSColin Finck ULONG NewLevel = SEI_MSG; /* Show some basic info in the logs, unless configured different */ 128*c2c66affSColin Finck WCHAR Buffer[40]; 129*c2c66affSColin Finck 130*c2c66affSColin Finck RtlInitEmptyUnicodeString(&DebugValue, Buffer, sizeof(Buffer)); 131*c2c66affSColin Finck 132*c2c66affSColin Finck Status = RtlQueryEnvironmentVariable_U(NULL, &DebugKey, &DebugValue); 133*c2c66affSColin Finck 134*c2c66affSColin Finck if (NT_SUCCESS(Status)) 135*c2c66affSColin Finck { 136*c2c66affSColin Finck if (!NT_SUCCESS(RtlUnicodeStringToInteger(&DebugValue, 10, &NewLevel))) 137*c2c66affSColin Finck NewLevel = 0; 138*c2c66affSColin Finck } 139*c2c66affSColin Finck g_ShimEngDebugLevel = NewLevel; 140*c2c66affSColin Finck } 141*c2c66affSColin Finck 142*c2c66affSColin Finck 143*c2c66affSColin Finck /** 144*c2c66affSColin Finck * Outputs diagnostic info. 145*c2c66affSColin Finck * 146*c2c66affSColin Finck * @param [in] Level The level to log this message with, choose any of [SHIM_ERR, 147*c2c66affSColin Finck * SHIM_WARN, SHIM_INFO]. 148*c2c66affSColin Finck * @param [in] FunctionName The function this log should be attributed to. 149*c2c66affSColin Finck * @param [in] Format The format string. 150*c2c66affSColin Finck * @param ... Variable arguments providing additional information. 151*c2c66affSColin Finck * 152*c2c66affSColin Finck * @return Success: TRUE Failure: FALSE. 153*c2c66affSColin Finck */ 154*c2c66affSColin Finck BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR Function, PCSTR Format, ...) 155*c2c66affSColin Finck { 156*c2c66affSColin Finck char Buffer[512]; 157*c2c66affSColin Finck char* Current = Buffer; 158*c2c66affSColin Finck const char* LevelStr; 159*c2c66affSColin Finck size_t Length = sizeof(Buffer); 160*c2c66affSColin Finck va_list ArgList; 161*c2c66affSColin Finck HRESULT hr; 162*c2c66affSColin Finck 163*c2c66affSColin Finck if (g_ShimEngDebugLevel == 0xffffffff) 164*c2c66affSColin Finck SeiInitDebugSupport(); 165*c2c66affSColin Finck 166*c2c66affSColin Finck if (Level > g_ShimEngDebugLevel) 167*c2c66affSColin Finck return FALSE; 168*c2c66affSColin Finck 169*c2c66affSColin Finck switch (Level) 170*c2c66affSColin Finck { 171*c2c66affSColin Finck case SEI_MSG: 172*c2c66affSColin Finck LevelStr = "MSG "; 173*c2c66affSColin Finck break; 174*c2c66affSColin Finck case SEI_FAIL: 175*c2c66affSColin Finck LevelStr = "FAIL"; 176*c2c66affSColin Finck break; 177*c2c66affSColin Finck case SEI_WARN: 178*c2c66affSColin Finck LevelStr = "WARN"; 179*c2c66affSColin Finck break; 180*c2c66affSColin Finck case SEI_INFO: 181*c2c66affSColin Finck LevelStr = "INFO"; 182*c2c66affSColin Finck break; 183*c2c66affSColin Finck default: 184*c2c66affSColin Finck LevelStr = "USER"; 185*c2c66affSColin Finck break; 186*c2c66affSColin Finck } 187*c2c66affSColin Finck 188*c2c66affSColin Finck if (Function) 189*c2c66affSColin Finck hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] [%s] ", LevelStr, Function); 190*c2c66affSColin Finck else 191*c2c66affSColin Finck hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] ", LevelStr); 192*c2c66affSColin Finck 193*c2c66affSColin Finck if (!SUCCEEDED(hr)) 194*c2c66affSColin Finck return FALSE; 195*c2c66affSColin Finck 196*c2c66affSColin Finck va_start(ArgList, Format); 197*c2c66affSColin Finck hr = StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList); 198*c2c66affSColin Finck va_end(ArgList); 199*c2c66affSColin Finck if (!SUCCEEDED(hr)) 200*c2c66affSColin Finck return FALSE; 201*c2c66affSColin Finck 202*c2c66affSColin Finck DbgPrint("%s", Buffer); 203*c2c66affSColin Finck return TRUE; 204*c2c66affSColin Finck } 205*c2c66affSColin Finck 206*c2c66affSColin Finck 207*c2c66affSColin Finck PVOID SeiGetModuleFromAddress(PVOID addr) 208*c2c66affSColin Finck { 209*c2c66affSColin Finck PVOID hModule = NULL; 210*c2c66affSColin Finck RtlPcToFileHeader(addr, &hModule); 211*c2c66affSColin Finck return hModule; 212*c2c66affSColin Finck } 213*c2c66affSColin Finck 214*c2c66affSColin Finck 215*c2c66affSColin Finck 216*c2c66affSColin Finck /* TODO: Guard against recursive calling / calling init multiple times! */ 217*c2c66affSColin Finck VOID NotifyShims(DWORD dwReason, PVOID Info) 218*c2c66affSColin Finck { 219*c2c66affSColin Finck DWORD n; 220*c2c66affSColin Finck 221*c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&g_pShimInfo); ++n) 222*c2c66affSColin Finck { 223*c2c66affSColin Finck PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, n); 224*c2c66affSColin Finck if (!pShimModule->pNotifyShims) 225*c2c66affSColin Finck continue; 226*c2c66affSColin Finck 227*c2c66affSColin Finck pShimModule->pNotifyShims(dwReason, Info); 228*c2c66affSColin Finck } 229*c2c66affSColin Finck } 230*c2c66affSColin Finck 231*c2c66affSColin Finck 232*c2c66affSColin Finck 233*c2c66affSColin Finck VOID SeiCheckComPlusImage(PVOID BaseAddress) 234*c2c66affSColin Finck { 235*c2c66affSColin Finck ULONG ComSectionSize; 236*c2c66affSColin Finck g_bComPlusImage = RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &ComSectionSize) != NULL; 237*c2c66affSColin Finck 238*c2c66affSColin Finck SHIMENG_INFO("COM+ executable %s\n", g_bComPlusImage ? "TRUE" : "FALSE"); 239*c2c66affSColin Finck } 240*c2c66affSColin Finck 241*c2c66affSColin Finck 242*c2c66affSColin Finck PSHIMMODULE SeiGetShimModuleInfo(PVOID BaseAddress) 243*c2c66affSColin Finck { 244*c2c66affSColin Finck DWORD n; 245*c2c66affSColin Finck 246*c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&g_pShimInfo); ++n) 247*c2c66affSColin Finck { 248*c2c66affSColin Finck PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, n); 249*c2c66affSColin Finck 250*c2c66affSColin Finck if (pShimModule->BaseAddress == BaseAddress) 251*c2c66affSColin Finck return pShimModule; 252*c2c66affSColin Finck } 253*c2c66affSColin Finck return NULL; 254*c2c66affSColin Finck } 255*c2c66affSColin Finck 256*c2c66affSColin Finck PSHIMMODULE SeiCreateShimModuleInfo(PCWSTR DllName, PVOID BaseAddress) 257*c2c66affSColin Finck { 258*c2c66affSColin Finck static const ANSI_STRING GetHookAPIs = RTL_CONSTANT_STRING("GetHookAPIs"); 259*c2c66affSColin Finck static const ANSI_STRING NotifyShims = RTL_CONSTANT_STRING("NotifyShims"); 260*c2c66affSColin Finck PSHIMMODULE* pData, Data; 261*c2c66affSColin Finck PVOID pGetHookAPIs, pNotifyShims; 262*c2c66affSColin Finck 263*c2c66affSColin Finck if (!NT_SUCCESS(LdrGetProcedureAddress(BaseAddress, (PANSI_STRING)&GetHookAPIs, 0, &pGetHookAPIs)) || 264*c2c66affSColin Finck !NT_SUCCESS(LdrGetProcedureAddress(BaseAddress, (PANSI_STRING)&NotifyShims, 0, &pNotifyShims))) 265*c2c66affSColin Finck { 266*c2c66affSColin Finck SHIMENG_WARN("Failed to resolve entry points for %S\n", DllName); 267*c2c66affSColin Finck return NULL; 268*c2c66affSColin Finck } 269*c2c66affSColin Finck 270*c2c66affSColin Finck pData = ARRAY_Append(&g_pShimInfo, PSHIMMODULE); 271*c2c66affSColin Finck if (!pData) 272*c2c66affSColin Finck return NULL; 273*c2c66affSColin Finck 274*c2c66affSColin Finck *pData = SeiAlloc(sizeof(SHIMMODULE)); 275*c2c66affSColin Finck 276*c2c66affSColin Finck Data = *pData; 277*c2c66affSColin Finck 278*c2c66affSColin Finck RtlCreateUnicodeString(&Data->Name, DllName); 279*c2c66affSColin Finck Data->BaseAddress = BaseAddress; 280*c2c66affSColin Finck 281*c2c66affSColin Finck Data->pGetHookAPIs = pGetHookAPIs; 282*c2c66affSColin Finck Data->pNotifyShims = pNotifyShims; 283*c2c66affSColin Finck 284*c2c66affSColin Finck ARRAY_Init(&Data->EnabledShims, PSHIMINFO); 285*c2c66affSColin Finck 286*c2c66affSColin Finck return Data; 287*c2c66affSColin Finck } 288*c2c66affSColin Finck 289*c2c66affSColin Finck PSHIMINFO SeiAppendHookInfo(PSHIMMODULE pShimModuleInfo, PHOOKAPIEX pHookApi, DWORD dwHookCount, PCWSTR ShimName) 290*c2c66affSColin Finck { 291*c2c66affSColin Finck PSHIMINFO* pData, Data; 292*c2c66affSColin Finck 293*c2c66affSColin Finck pData = ARRAY_Append(&pShimModuleInfo->EnabledShims, PSHIMINFO); 294*c2c66affSColin Finck if (!pData) 295*c2c66affSColin Finck return NULL; 296*c2c66affSColin Finck 297*c2c66affSColin Finck *pData = SeiAlloc(sizeof(SHIMINFO)); 298*c2c66affSColin Finck Data = *pData; 299*c2c66affSColin Finck 300*c2c66affSColin Finck if (!Data) 301*c2c66affSColin Finck return NULL; 302*c2c66affSColin Finck 303*c2c66affSColin Finck Data->ShimName = SdbpStrDup(ShimName); 304*c2c66affSColin Finck if (!Data->ShimName) 305*c2c66affSColin Finck return NULL; 306*c2c66affSColin Finck 307*c2c66affSColin Finck Data->pHookApi = pHookApi; 308*c2c66affSColin Finck Data->dwHookCount = dwHookCount; 309*c2c66affSColin Finck Data->pShimModule = pShimModuleInfo; 310*c2c66affSColin Finck ARRAY_Init(&Data->InExclude, INEXCLUDE); 311*c2c66affSColin Finck return Data; 312*c2c66affSColin Finck } 313*c2c66affSColin Finck 314*c2c66affSColin Finck PHOOKMODULEINFO SeiFindHookModuleInfo(PUNICODE_STRING ModuleName, PVOID BaseAddress) 315*c2c66affSColin Finck { 316*c2c66affSColin Finck DWORD n; 317*c2c66affSColin Finck 318*c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&g_pHookArray); ++n) 319*c2c66affSColin Finck { 320*c2c66affSColin Finck PHOOKMODULEINFO pModuleInfo = ARRAY_At(&g_pHookArray, HOOKMODULEINFO, n); 321*c2c66affSColin Finck 322*c2c66affSColin Finck if (BaseAddress && BaseAddress == pModuleInfo->BaseAddress) 323*c2c66affSColin Finck return pModuleInfo; 324*c2c66affSColin Finck 325*c2c66affSColin Finck if (!BaseAddress && RtlEqualUnicodeString(ModuleName, &pModuleInfo->Name, TRUE)) 326*c2c66affSColin Finck return pModuleInfo; 327*c2c66affSColin Finck } 328*c2c66affSColin Finck 329*c2c66affSColin Finck return NULL; 330*c2c66affSColin Finck } 331*c2c66affSColin Finck 332*c2c66affSColin Finck PHOOKMODULEINFO SeiFindHookModuleInfoForImportDescriptor(PBYTE DllBase, PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor) 333*c2c66affSColin Finck { 334*c2c66affSColin Finck UNICODE_STRING DllName; 335*c2c66affSColin Finck PVOID DllHandle; 336*c2c66affSColin Finck NTSTATUS Success; 337*c2c66affSColin Finck 338*c2c66affSColin Finck if (!RtlCreateUnicodeStringFromAsciiz(&DllName, (PCSZ)(DllBase + ImportDescriptor->Name))) 339*c2c66affSColin Finck { 340*c2c66affSColin Finck SHIMENG_FAIL("Unable to convert dll name to unicode\n"); 341*c2c66affSColin Finck return NULL; 342*c2c66affSColin Finck } 343*c2c66affSColin Finck 344*c2c66affSColin Finck Success = LdrGetDllHandle(NULL, NULL, &DllName, &DllHandle); 345*c2c66affSColin Finck RtlFreeUnicodeString(&DllName); 346*c2c66affSColin Finck 347*c2c66affSColin Finck if (!NT_SUCCESS(Success)) 348*c2c66affSColin Finck { 349*c2c66affSColin Finck SHIMENG_FAIL("Unable to get module handle for %wZ\n", &DllName); 350*c2c66affSColin Finck return NULL; 351*c2c66affSColin Finck } 352*c2c66affSColin Finck 353*c2c66affSColin Finck return SeiFindHookModuleInfo(NULL, DllHandle); 354*c2c66affSColin Finck } 355*c2c66affSColin Finck 356*c2c66affSColin Finck static LPCWSTR SeiGetStringPtr(PDB pdb, TAGID tag, TAG type) 357*c2c66affSColin Finck { 358*c2c66affSColin Finck TAGID tagEntry = SdbFindFirstTag(pdb, tag, type); 359*c2c66affSColin Finck if (tagEntry == TAGID_NULL) 360*c2c66affSColin Finck return NULL; 361*c2c66affSColin Finck 362*c2c66affSColin Finck return SdbGetStringTagPtr(pdb, tagEntry); 363*c2c66affSColin Finck } 364*c2c66affSColin Finck 365*c2c66affSColin Finck static DWORD SeiGetDWORD(PDB pdb, TAGID tag, TAG type) 366*c2c66affSColin Finck { 367*c2c66affSColin Finck TAGID tagEntry = SdbFindFirstTag(pdb, tag, type); 368*c2c66affSColin Finck if (tagEntry == TAGID_NULL) 369*c2c66affSColin Finck return 0; 370*c2c66affSColin Finck 371*c2c66affSColin Finck return SdbReadDWORDTag(pdb, tagEntry, TAGID_NULL); 372*c2c66affSColin Finck } 373*c2c66affSColin Finck 374*c2c66affSColin Finck 375*c2c66affSColin Finck static VOID SeiAddShim(TAGREF trShimRef, PARRAY pShimRef) 376*c2c66affSColin Finck { 377*c2c66affSColin Finck TAGREF* Data; 378*c2c66affSColin Finck 379*c2c66affSColin Finck Data = ARRAY_Append(pShimRef, TAGREF); 380*c2c66affSColin Finck if (!Data) 381*c2c66affSColin Finck return; 382*c2c66affSColin Finck 383*c2c66affSColin Finck *Data = trShimRef; 384*c2c66affSColin Finck } 385*c2c66affSColin Finck 386*c2c66affSColin Finck /* Propagate layers to child processes */ 387*c2c66affSColin Finck static VOID SeiSetLayerEnvVar(LPCWSTR wszLayer) 388*c2c66affSColin Finck { 389*c2c66affSColin Finck NTSTATUS Status; 390*c2c66affSColin Finck UNICODE_STRING VarName = RTL_CONSTANT_STRING(L"__COMPAT_LAYER"); 391*c2c66affSColin Finck UNICODE_STRING Value; 392*c2c66affSColin Finck 393*c2c66affSColin Finck RtlInitUnicodeString(&Value, wszLayer); 394*c2c66affSColin Finck 395*c2c66affSColin Finck Status = RtlSetEnvironmentVariable(NULL, &VarName, &Value); 396*c2c66affSColin Finck if (NT_SUCCESS(Status)) 397*c2c66affSColin Finck SHIMENG_INFO("Set env var %wZ=%wZ\n", &VarName, &Value); 398*c2c66affSColin Finck else 399*c2c66affSColin Finck SHIMENG_FAIL("Failed to set %wZ: 0x%x\n", &VarName, Status); 400*c2c66affSColin Finck } 401*c2c66affSColin Finck 402*c2c66affSColin Finck #define MAX_LAYER_LENGTH 256 403*c2c66affSColin Finck 404*c2c66affSColin Finck /* Translate all Exe and Layer entries to Shims, and propagate all layers */ 405*c2c66affSColin Finck static VOID SeiBuildShimRefArray(HSDB hsdb, SDBQUERYRESULT* pQuery, PARRAY pShimRef) 406*c2c66affSColin Finck { 407*c2c66affSColin Finck WCHAR wszLayerEnvVar[MAX_LAYER_LENGTH] = { 0 }; 408*c2c66affSColin Finck DWORD n; 409*c2c66affSColin Finck 410*c2c66affSColin Finck for (n = 0; n < pQuery->dwExeCount; ++n) 411*c2c66affSColin Finck { 412*c2c66affSColin Finck PDB pdb; 413*c2c66affSColin Finck TAGID tag; 414*c2c66affSColin Finck if (SdbTagRefToTagID(hsdb, pQuery->atrExes[n], &pdb, &tag)) 415*c2c66affSColin Finck { 416*c2c66affSColin Finck LPCWSTR ExeName = SeiGetStringPtr(pdb, tag, TAG_NAME); 417*c2c66affSColin Finck TAGID ShimRef = SdbFindFirstTag(pdb, tag, TAG_SHIM_REF); 418*c2c66affSColin Finck 419*c2c66affSColin Finck if (ExeName) 420*c2c66affSColin Finck SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Exe(%S))\n", ExeName); 421*c2c66affSColin Finck 422*c2c66affSColin Finck while (ShimRef != TAGID_NULL) 423*c2c66affSColin Finck { 424*c2c66affSColin Finck TAGREF trShimRef; 425*c2c66affSColin Finck if (SdbTagIDToTagRef(hsdb, pdb, ShimRef, &trShimRef)) 426*c2c66affSColin Finck SeiAddShim(trShimRef, pShimRef); 427*c2c66affSColin Finck 428*c2c66affSColin Finck 429*c2c66affSColin Finck ShimRef = SdbFindNextTag(pdb, tag, ShimRef); 430*c2c66affSColin Finck } 431*c2c66affSColin Finck 432*c2c66affSColin Finck /* Handle FLAG_REF */ 433*c2c66affSColin Finck } 434*c2c66affSColin Finck } 435*c2c66affSColin Finck 436*c2c66affSColin Finck 437*c2c66affSColin Finck for (n = 0; n < pQuery->dwLayerCount; ++n) 438*c2c66affSColin Finck { 439*c2c66affSColin Finck PDB pdb; 440*c2c66affSColin Finck TAGID tag; 441*c2c66affSColin Finck if (SdbTagRefToTagID(hsdb, pQuery->atrLayers[n], &pdb, &tag)) 442*c2c66affSColin Finck { 443*c2c66affSColin Finck LPCWSTR LayerName = SeiGetStringPtr(pdb, tag, TAG_NAME); 444*c2c66affSColin Finck TAGID ShimRef = SdbFindFirstTag(pdb, tag, TAG_SHIM_REF); 445*c2c66affSColin Finck if (LayerName) 446*c2c66affSColin Finck { 447*c2c66affSColin Finck HRESULT hr; 448*c2c66affSColin Finck SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Layer(%S))\n", LayerName); 449*c2c66affSColin Finck if (wszLayerEnvVar[0]) 450*c2c66affSColin Finck StringCchCatW(wszLayerEnvVar, ARRAYSIZE(wszLayerEnvVar), L" "); 451*c2c66affSColin Finck hr = StringCchCatW(wszLayerEnvVar, ARRAYSIZE(wszLayerEnvVar), LayerName); 452*c2c66affSColin Finck if (!SUCCEEDED(hr)) 453*c2c66affSColin Finck { 454*c2c66affSColin Finck SHIMENG_FAIL("Unable to append %S\n", LayerName); 455*c2c66affSColin Finck } 456*c2c66affSColin Finck } 457*c2c66affSColin Finck 458*c2c66affSColin Finck while (ShimRef != TAGID_NULL) 459*c2c66affSColin Finck { 460*c2c66affSColin Finck TAGREF trShimRef; 461*c2c66affSColin Finck if (SdbTagIDToTagRef(hsdb, pdb, ShimRef, &trShimRef)) 462*c2c66affSColin Finck SeiAddShim(trShimRef, pShimRef); 463*c2c66affSColin Finck 464*c2c66affSColin Finck ShimRef = SdbFindNextTag(pdb, tag, ShimRef); 465*c2c66affSColin Finck } 466*c2c66affSColin Finck 467*c2c66affSColin Finck /* Handle FLAG_REF */ 468*c2c66affSColin Finck } 469*c2c66affSColin Finck } 470*c2c66affSColin Finck if (wszLayerEnvVar[0]) 471*c2c66affSColin Finck SeiSetLayerEnvVar(wszLayerEnvVar); 472*c2c66affSColin Finck } 473*c2c66affSColin Finck 474*c2c66affSColin Finck /* Given the hooks from one shim, find the relevant modules and store the combination of module + hook */ 475*c2c66affSColin Finck VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO pShim) 476*c2c66affSColin Finck { 477*c2c66affSColin Finck DWORD n, j; 478*c2c66affSColin Finck UNICODE_STRING UnicodeModName; 479*c2c66affSColin Finck WCHAR Buf[512]; 480*c2c66affSColin Finck 481*c2c66affSColin Finck RtlInitEmptyUnicodeString(&UnicodeModName, Buf, sizeof(Buf)); 482*c2c66affSColin Finck 483*c2c66affSColin Finck for (n = 0; n < dwHookCount; ++n) 484*c2c66affSColin Finck { 485*c2c66affSColin Finck ANSI_STRING AnsiString; 486*c2c66affSColin Finck PVOID DllHandle; 487*c2c66affSColin Finck PHOOKAPIEX hook = hooks + n; 488*c2c66affSColin Finck PHOOKAPIEX* pHookApi; 489*c2c66affSColin Finck PHOOKMODULEINFO HookModuleInfo; 490*c2c66affSColin Finck 491*c2c66affSColin Finck RtlInitAnsiString(&AnsiString, hook->LibraryName); 492*c2c66affSColin Finck if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeModName, &AnsiString, FALSE))) 493*c2c66affSColin Finck { 494*c2c66affSColin Finck SHIMENG_FAIL("Unable to convert %s to Unicode\n", hook->LibraryName); 495*c2c66affSColin Finck continue; 496*c2c66affSColin Finck } 497*c2c66affSColin Finck 498*c2c66affSColin Finck RtlInitAnsiString(&AnsiString, hook->FunctionName); 499*c2c66affSColin Finck if (NT_SUCCESS(LdrGetDllHandle(NULL, 0, &UnicodeModName, &DllHandle))) 500*c2c66affSColin Finck { 501*c2c66affSColin Finck PVOID ProcAddress; 502*c2c66affSColin Finck 503*c2c66affSColin Finck 504*c2c66affSColin Finck if (!NT_SUCCESS(LdrGetProcedureAddress(DllHandle, &AnsiString, 0, &ProcAddress))) 505*c2c66affSColin Finck { 506*c2c66affSColin Finck SHIMENG_FAIL("Unable to retrieve %s!%s\n", hook->LibraryName, hook->FunctionName); 507*c2c66affSColin Finck continue; 508*c2c66affSColin Finck } 509*c2c66affSColin Finck 510*c2c66affSColin Finck HookModuleInfo = SeiFindHookModuleInfo(NULL, DllHandle); 511*c2c66affSColin Finck hook->OriginalFunction = ProcAddress; 512*c2c66affSColin Finck } 513*c2c66affSColin Finck else 514*c2c66affSColin Finck { 515*c2c66affSColin Finck HookModuleInfo = SeiFindHookModuleInfo(&UnicodeModName, NULL); 516*c2c66affSColin Finck DllHandle = NULL; 517*c2c66affSColin Finck } 518*c2c66affSColin Finck 519*c2c66affSColin Finck if (!HookModuleInfo) 520*c2c66affSColin Finck { 521*c2c66affSColin Finck HookModuleInfo = ARRAY_Append(&g_pHookArray, HOOKMODULEINFO); 522*c2c66affSColin Finck if (!HookModuleInfo) 523*c2c66affSColin Finck continue; 524*c2c66affSColin Finck 525*c2c66affSColin Finck HookModuleInfo->BaseAddress = DllHandle; 526*c2c66affSColin Finck ARRAY_Init(&HookModuleInfo->HookApis, PHOOKAPIEX); 527*c2c66affSColin Finck RtlCreateUnicodeString(&HookModuleInfo->Name, UnicodeModName.Buffer); 528*c2c66affSColin Finck } 529*c2c66affSColin Finck 530*c2c66affSColin Finck hook->pShimInfo = pShim; 531*c2c66affSColin Finck 532*c2c66affSColin Finck for (j = 0; j < ARRAY_Size(&HookModuleInfo->HookApis); ++j) 533*c2c66affSColin Finck { 534*c2c66affSColin Finck PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, j); 535*c2c66affSColin Finck int CmpResult = strcmp(hook->FunctionName, HookApi->FunctionName); 536*c2c66affSColin Finck if (CmpResult == 0) 537*c2c66affSColin Finck { 538*c2c66affSColin Finck /* Multiple hooks on one function? --> use ApiLink */ 539*c2c66affSColin Finck SHIMENG_FAIL("Multiple hooks on one API is not yet supported!\n"); 540*c2c66affSColin Finck ASSERT(0); 541*c2c66affSColin Finck } 542*c2c66affSColin Finck } 543*c2c66affSColin Finck pHookApi = ARRAY_Append(&HookModuleInfo->HookApis, PHOOKAPIEX); 544*c2c66affSColin Finck *pHookApi = hook; 545*c2c66affSColin Finck } 546*c2c66affSColin Finck } 547*c2c66affSColin Finck 548*c2c66affSColin Finck typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HINSTANCE, LPCSTR); 549*c2c66affSColin Finck 550*c2c66affSColin Finck /* Check if we should fake the return from GetProcAddress (because we also redirected the iat for this module) */ 551*c2c66affSColin Finck FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName) 552*c2c66affSColin Finck { 553*c2c66affSColin Finck char szOrdProcName[10] = ""; 554*c2c66affSColin Finck LPCSTR lpPrintName = lpProcName; 555*c2c66affSColin Finck PVOID Addr = _ReturnAddress(); 556*c2c66affSColin Finck PHOOKMODULEINFO HookModuleInfo; 557*c2c66affSColin Finck FARPROC proc = ((GETPROCADDRESSPROC)g_IntHookEx[0].OriginalFunction)(hModule, lpProcName); 558*c2c66affSColin Finck 559*c2c66affSColin Finck if (!HIWORD(lpProcName)) 560*c2c66affSColin Finck { 561*c2c66affSColin Finck sprintf(szOrdProcName, "#%lu", (DWORD)lpProcName); 562*c2c66affSColin Finck lpPrintName = szOrdProcName; 563*c2c66affSColin Finck } 564*c2c66affSColin Finck 565*c2c66affSColin Finck Addr = SeiGetModuleFromAddress(Addr); 566*c2c66affSColin Finck if (SE_IsShimDll(Addr)) 567*c2c66affSColin Finck { 568*c2c66affSColin Finck SHIMENG_MSG("Not touching GetProcAddress for shim dll (%p!%s)", hModule, lpPrintName); 569*c2c66affSColin Finck return proc; 570*c2c66affSColin Finck } 571*c2c66affSColin Finck 572*c2c66affSColin Finck SHIMENG_MSG("(GetProcAddress(%p!%s) => %p\n", hModule, lpPrintName, proc); 573*c2c66affSColin Finck 574*c2c66affSColin Finck HookModuleInfo = SeiFindHookModuleInfo(NULL, hModule); 575*c2c66affSColin Finck 576*c2c66affSColin Finck /* FIXME: Ordinal not yet supported */ 577*c2c66affSColin Finck if (HookModuleInfo && HIWORD(lpProcName)) 578*c2c66affSColin Finck { 579*c2c66affSColin Finck DWORD n; 580*c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n) 581*c2c66affSColin Finck { 582*c2c66affSColin Finck PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n); 583*c2c66affSColin Finck int CmpResult = strcmp(lpProcName, HookApi->FunctionName); 584*c2c66affSColin Finck if (CmpResult == 0) 585*c2c66affSColin Finck { 586*c2c66affSColin Finck SHIMENG_MSG("Redirecting %p to %p\n", proc, HookApi->ReplacementFunction); 587*c2c66affSColin Finck proc = HookApi->ReplacementFunction; 588*c2c66affSColin Finck break; 589*c2c66affSColin Finck } 590*c2c66affSColin Finck } 591*c2c66affSColin Finck } 592*c2c66affSColin Finck 593*c2c66affSColin Finck return proc; 594*c2c66affSColin Finck } 595*c2c66affSColin Finck 596*c2c66affSColin Finck /* Walk all shim modules / enabled shims, and add their hooks */ 597*c2c66affSColin Finck VOID SeiResolveAPIs(VOID) 598*c2c66affSColin Finck { 599*c2c66affSColin Finck DWORD mod, n; 600*c2c66affSColin Finck 601*c2c66affSColin Finck /* Enumerate all Shim modules */ 602*c2c66affSColin Finck for (mod = 0; mod < ARRAY_Size(&g_pShimInfo); ++mod) 603*c2c66affSColin Finck { 604*c2c66affSColin Finck PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, mod); 605*c2c66affSColin Finck DWORD dwShimCount = ARRAY_Size(&pShimModule->EnabledShims); 606*c2c66affSColin Finck 607*c2c66affSColin Finck /* Enumerate all Shims */ 608*c2c66affSColin Finck for (n = 0; n < dwShimCount; ++n) 609*c2c66affSColin Finck { 610*c2c66affSColin Finck PSHIMINFO pShim = *ARRAY_At(&pShimModule->EnabledShims, PSHIMINFO, n); 611*c2c66affSColin Finck 612*c2c66affSColin Finck PHOOKAPIEX hooks = pShim->pHookApi; 613*c2c66affSColin Finck DWORD dwHookCount = pShim->dwHookCount; 614*c2c66affSColin Finck 615*c2c66affSColin Finck SeiAddHooks(hooks, dwHookCount, pShim); 616*c2c66affSColin Finck } 617*c2c66affSColin Finck } 618*c2c66affSColin Finck } 619*c2c66affSColin Finck 620*c2c66affSColin Finck /* If we hooked something, we should also redirect GetProcAddress */ 621*c2c66affSColin Finck VOID SeiAddInternalHooks(DWORD dwNumHooks) 622*c2c66affSColin Finck { 623*c2c66affSColin Finck if (dwNumHooks == 0) 624*c2c66affSColin Finck { 625*c2c66affSColin Finck g_bInternalHooksUsed = FALSE; 626*c2c66affSColin Finck return; 627*c2c66affSColin Finck } 628*c2c66affSColin Finck 629*c2c66affSColin Finck SeiAddHooks(g_IntHookEx, ARRAYSIZE(g_IntHookEx), NULL); 630*c2c66affSColin Finck g_bInternalHooksUsed = TRUE; 631*c2c66affSColin Finck } 632*c2c66affSColin Finck 633*c2c66affSColin Finck /* Patch one function in the iat */ 634*c2c66affSColin Finck VOID SeiPatchNewImport(PIMAGE_THUNK_DATA FirstThunk, PHOOKAPIEX HookApi, PLDR_DATA_TABLE_ENTRY LdrEntry) 635*c2c66affSColin Finck { 636*c2c66affSColin Finck ULONG OldProtection = 0; 637*c2c66affSColin Finck PVOID Ptr; 638*c2c66affSColin Finck ULONG Size; 639*c2c66affSColin Finck NTSTATUS Status; 640*c2c66affSColin Finck 641*c2c66affSColin Finck SHIMENG_INFO("Hooking API \"%s!%s\" for DLL \"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName, &LdrEntry->BaseDllName); 642*c2c66affSColin Finck 643*c2c66affSColin Finck Ptr = &FirstThunk->u1.Function; 644*c2c66affSColin Finck Size = sizeof(FirstThunk->u1.Function); 645*c2c66affSColin Finck Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size, PAGE_EXECUTE_READWRITE, &OldProtection); 646*c2c66affSColin Finck 647*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 648*c2c66affSColin Finck { 649*c2c66affSColin Finck SHIMENG_FAIL("Unable to unprotect 0x%p\n", &FirstThunk->u1.Function); 650*c2c66affSColin Finck return; 651*c2c66affSColin Finck } 652*c2c66affSColin Finck 653*c2c66affSColin Finck SHIMENG_INFO("changing 0x%p to 0x%p\n", FirstThunk->u1.Function, HookApi->ReplacementFunction); 654*c2c66affSColin Finck #ifdef _WIN64 655*c2c66affSColin Finck FirstThunk->u1.Function = (ULONGLONG)HookApi->ReplacementFunction; 656*c2c66affSColin Finck #else 657*c2c66affSColin Finck FirstThunk->u1.Function = (DWORD)HookApi->ReplacementFunction; 658*c2c66affSColin Finck #endif 659*c2c66affSColin Finck 660*c2c66affSColin Finck Size = sizeof(FirstThunk->u1.Function); 661*c2c66affSColin Finck Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size, OldProtection, &OldProtection); 662*c2c66affSColin Finck 663*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 664*c2c66affSColin Finck { 665*c2c66affSColin Finck SHIMENG_WARN("Unable to reprotect 0x%p\n", &FirstThunk->u1.Function); 666*c2c66affSColin Finck } 667*c2c66affSColin Finck } 668*c2c66affSColin Finck 669*c2c66affSColin Finck 670*c2c66affSColin Finck PINEXCLUDE SeiFindInExclude(PARRAY InExclude, PCUNICODE_STRING DllName) 671*c2c66affSColin Finck { 672*c2c66affSColin Finck DWORD n; 673*c2c66affSColin Finck 674*c2c66affSColin Finck for (n = 0; n < ARRAY_Size(InExclude); ++n) 675*c2c66affSColin Finck { 676*c2c66affSColin Finck PINEXCLUDE InEx = ARRAY_At(InExclude, INEXCLUDE, n); 677*c2c66affSColin Finck 678*c2c66affSColin Finck if (RtlEqualUnicodeString(&InEx->Module, DllName, TRUE)) 679*c2c66affSColin Finck return InEx; 680*c2c66affSColin Finck } 681*c2c66affSColin Finck 682*c2c66affSColin Finck return NULL; 683*c2c66affSColin Finck } 684*c2c66affSColin Finck 685*c2c66affSColin Finck BOOL SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry, PHOOKAPIEX HookApi) 686*c2c66affSColin Finck { 687*c2c66affSColin Finck PSHIMINFO pShimInfo = HookApi->pShimInfo; 688*c2c66affSColin Finck PINEXCLUDE InExclude; 689*c2c66affSColin Finck BOOL IsExcluded = FALSE; 690*c2c66affSColin Finck 691*c2c66affSColin Finck if (!pShimInfo) 692*c2c66affSColin Finck { 693*c2c66affSColin Finck /* Internal hook, do not exclude it */ 694*c2c66affSColin Finck return FALSE; 695*c2c66affSColin Finck } 696*c2c66affSColin Finck 697*c2c66affSColin Finck /* By default, everything from System32 or WinSxs is excluded */ 698*c2c66affSColin Finck if (RtlPrefixUnicodeString(&g_System32Directory, &LdrEntry->FullDllName, TRUE) || 699*c2c66affSColin Finck RtlPrefixUnicodeString(&g_SxsDirectory, &LdrEntry->FullDllName, TRUE)) 700*c2c66affSColin Finck IsExcluded = TRUE; 701*c2c66affSColin Finck 702*c2c66affSColin Finck InExclude = SeiFindInExclude(&pShimInfo->InExclude, &LdrEntry->BaseDllName); 703*c2c66affSColin Finck if (InExclude) 704*c2c66affSColin Finck { 705*c2c66affSColin Finck /* If it is on the 'exclude' list, bail out */ 706*c2c66affSColin Finck if (!InExclude->Include) 707*c2c66affSColin Finck { 708*c2c66affSColin Finck SHIMENG_INFO("Module '%wZ' excluded for shim %S, API '%s!%s', because it on in the exclude list.\n", 709*c2c66affSColin Finck &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName); 710*c2c66affSColin Finck 711*c2c66affSColin Finck return TRUE; 712*c2c66affSColin Finck } 713*c2c66affSColin Finck /* If it is on the 'include' list, override System32 / Winsxs check. */ 714*c2c66affSColin Finck if (IsExcluded) 715*c2c66affSColin Finck { 716*c2c66affSColin Finck SHIMENG_INFO("Module '%wZ' included for shim %S, API '%s!%s', because it is on the include list.\n", 717*c2c66affSColin Finck &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName); 718*c2c66affSColin Finck 719*c2c66affSColin Finck } 720*c2c66affSColin Finck IsExcluded = FALSE; 721*c2c66affSColin Finck } 722*c2c66affSColin Finck 723*c2c66affSColin Finck if (IsExcluded) 724*c2c66affSColin Finck { 725*c2c66affSColin Finck SHIMENG_INFO("Module '%wZ' excluded for shim %S, API '%s!%s', because it is in System32/WinSXS.\n", 726*c2c66affSColin Finck &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName); 727*c2c66affSColin Finck } 728*c2c66affSColin Finck 729*c2c66affSColin Finck return IsExcluded; 730*c2c66affSColin Finck } 731*c2c66affSColin Finck 732*c2c66affSColin Finck VOID SeiAppendInExclude(PARRAY dest, PCWSTR ModuleName, BOOL IsInclude) 733*c2c66affSColin Finck { 734*c2c66affSColin Finck PINEXCLUDE InExclude; 735*c2c66affSColin Finck UNICODE_STRING ModuleNameU; 736*c2c66affSColin Finck RtlInitUnicodeString(&ModuleNameU, ModuleName); 737*c2c66affSColin Finck 738*c2c66affSColin Finck InExclude = SeiFindInExclude(dest, &ModuleNameU); 739*c2c66affSColin Finck if (InExclude) 740*c2c66affSColin Finck { 741*c2c66affSColin Finck InExclude->Include = IsInclude; 742*c2c66affSColin Finck return; 743*c2c66affSColin Finck } 744*c2c66affSColin Finck 745*c2c66affSColin Finck InExclude = ARRAY_Append(dest, INEXCLUDE); 746*c2c66affSColin Finck if (InExclude) 747*c2c66affSColin Finck { 748*c2c66affSColin Finck PCWSTR ModuleNameCopy = SdbpStrDup(ModuleName); 749*c2c66affSColin Finck RtlInitUnicodeString(&InExclude->Module, ModuleNameCopy); 750*c2c66affSColin Finck InExclude->Include = IsInclude; 751*c2c66affSColin Finck } 752*c2c66affSColin Finck } 753*c2c66affSColin Finck 754*c2c66affSColin Finck /* Read the INEXCLUD tags from a given parent tag */ 755*c2c66affSColin Finck VOID SeiReadInExclude(PDB pdb, TAGID parent, PARRAY dest) 756*c2c66affSColin Finck { 757*c2c66affSColin Finck TAGID InExcludeTag; 758*c2c66affSColin Finck 759*c2c66affSColin Finck InExcludeTag = SdbFindFirstTag(pdb, parent, TAG_INEXCLUD); 760*c2c66affSColin Finck 761*c2c66affSColin Finck while (InExcludeTag != TAGID_NULL) 762*c2c66affSColin Finck { 763*c2c66affSColin Finck PCWSTR ModuleName; 764*c2c66affSColin Finck TAGID ModuleTag = SdbFindFirstTag(pdb, InExcludeTag, TAG_MODULE); 765*c2c66affSColin Finck TAGID IncludeTag = SdbFindFirstTag(pdb, InExcludeTag, TAG_INCLUDE); 766*c2c66affSColin Finck 767*c2c66affSColin Finck ModuleName = SdbGetStringTagPtr(pdb, ModuleTag); 768*c2c66affSColin Finck if (ModuleName) 769*c2c66affSColin Finck { 770*c2c66affSColin Finck SeiAppendInExclude(dest, ModuleName, IncludeTag != TAGID_NULL); 771*c2c66affSColin Finck } 772*c2c66affSColin Finck else 773*c2c66affSColin Finck { 774*c2c66affSColin Finck SHIMENG_WARN("INEXCLUDE without Module: 0x%x\n", InExcludeTag); 775*c2c66affSColin Finck } 776*c2c66affSColin Finck 777*c2c66affSColin Finck InExcludeTag = SdbFindNextTag(pdb, parent, InExcludeTag); 778*c2c66affSColin Finck } 779*c2c66affSColin Finck } 780*c2c66affSColin Finck 781*c2c66affSColin Finck VOID SeiBuildGlobalInclExclList(HSDB hsdb) 782*c2c66affSColin Finck { 783*c2c66affSColin Finck PDB pdb; 784*c2c66affSColin Finck TAGREF tr = TAGREF_ROOT; 785*c2c66affSColin Finck TAGID root, db, library; 786*c2c66affSColin Finck 787*c2c66affSColin Finck if (!SdbTagRefToTagID(hsdb, tr, &pdb, &root)) 788*c2c66affSColin Finck { 789*c2c66affSColin Finck SHIMENG_WARN("Unable to resolve database root\n"); 790*c2c66affSColin Finck return; 791*c2c66affSColin Finck } 792*c2c66affSColin Finck db = SdbFindFirstTag(pdb, root, TAG_DATABASE); 793*c2c66affSColin Finck if (db == TAGID_NULL) 794*c2c66affSColin Finck { 795*c2c66affSColin Finck SHIMENG_WARN("Unable to resolve database\n"); 796*c2c66affSColin Finck return; 797*c2c66affSColin Finck } 798*c2c66affSColin Finck library = SdbFindFirstTag(pdb, db, TAG_LIBRARY); 799*c2c66affSColin Finck if (library == TAGID_NULL) 800*c2c66affSColin Finck { 801*c2c66affSColin Finck SHIMENG_WARN("Unable to resolve library\n"); 802*c2c66affSColin Finck return; 803*c2c66affSColin Finck } 804*c2c66affSColin Finck 805*c2c66affSColin Finck SeiReadInExclude(pdb, library, &g_InExclude); 806*c2c66affSColin Finck } 807*c2c66affSColin Finck 808*c2c66affSColin Finck VOID SeiBuildInclExclList(PDB pdb, TAGID ShimTag, PSHIMINFO pShimInfo) 809*c2c66affSColin Finck { 810*c2c66affSColin Finck DWORD n; 811*c2c66affSColin Finck 812*c2c66affSColin Finck /* First duplicate the global in/excludes */ 813*c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&g_InExclude); ++n) 814*c2c66affSColin Finck { 815*c2c66affSColin Finck PINEXCLUDE InEx = ARRAY_At(&g_InExclude, INEXCLUDE, n); 816*c2c66affSColin Finck SeiAppendInExclude(&pShimInfo->InExclude, InEx->Module.Buffer, InEx->Include); 817*c2c66affSColin Finck } 818*c2c66affSColin Finck 819*c2c66affSColin Finck /* Now read this shim's in/excludes (possibly overriding the global ones) */ 820*c2c66affSColin Finck SeiReadInExclude(pdb, ShimTag, &pShimInfo->InExclude); 821*c2c66affSColin Finck } 822*c2c66affSColin Finck 823*c2c66affSColin Finck /* Given one loaded module, redirect (hook) all functions from the iat that are registered by shims */ 824*c2c66affSColin Finck VOID SeiHookImports(PLDR_DATA_TABLE_ENTRY LdrEntry) 825*c2c66affSColin Finck { 826*c2c66affSColin Finck ULONG Size; 827*c2c66affSColin Finck PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor; 828*c2c66affSColin Finck PBYTE DllBase = LdrEntry->DllBase; 829*c2c66affSColin Finck 830*c2c66affSColin Finck if (SE_IsShimDll(DllBase) || g_hInstance == LdrEntry->DllBase) 831*c2c66affSColin Finck { 832*c2c66affSColin Finck SHIMENG_INFO("Skipping shim module 0x%p \"%wZ\"\n", LdrEntry->DllBase, &LdrEntry->BaseDllName); 833*c2c66affSColin Finck return; 834*c2c66affSColin Finck } 835*c2c66affSColin Finck 836*c2c66affSColin Finck ImportDescriptor = RtlImageDirectoryEntryToData(DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size); 837*c2c66affSColin Finck if (!ImportDescriptor) 838*c2c66affSColin Finck { 839*c2c66affSColin Finck SHIMENG_INFO("Skipping module 0x%p \"%wZ\" due to no iat found\n", LdrEntry->DllBase, &LdrEntry->BaseDllName); 840*c2c66affSColin Finck return; 841*c2c66affSColin Finck } 842*c2c66affSColin Finck 843*c2c66affSColin Finck SHIMENG_INFO("Hooking module 0x%p \"%wZ\"\n", LdrEntry->DllBase, &LdrEntry->BaseDllName); 844*c2c66affSColin Finck 845*c2c66affSColin Finck for ( ;ImportDescriptor->Name && ImportDescriptor->OriginalFirstThunk; ImportDescriptor++) 846*c2c66affSColin Finck { 847*c2c66affSColin Finck PHOOKMODULEINFO HookModuleInfo; 848*c2c66affSColin Finck 849*c2c66affSColin Finck /* Do we have hooks for this module? */ 850*c2c66affSColin Finck HookModuleInfo = SeiFindHookModuleInfoForImportDescriptor(DllBase, ImportDescriptor); 851*c2c66affSColin Finck 852*c2c66affSColin Finck if (HookModuleInfo) 853*c2c66affSColin Finck { 854*c2c66affSColin Finck PIMAGE_THUNK_DATA OriginalThunk, FirstThunk; 855*c2c66affSColin Finck DWORD n; 856*c2c66affSColin Finck 857*c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n) 858*c2c66affSColin Finck { 859*c2c66affSColin Finck DWORD dwFound = 0; 860*c2c66affSColin Finck PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n); 861*c2c66affSColin Finck 862*c2c66affSColin Finck /* Check if this module should be excluded from being hooked (system32/winsxs, global or shim exclude) */ 863*c2c66affSColin Finck if (SeiIsExcluded(LdrEntry, HookApi)) 864*c2c66affSColin Finck { 865*c2c66affSColin Finck continue; 866*c2c66affSColin Finck } 867*c2c66affSColin Finck 868*c2c66affSColin Finck OriginalThunk = (PIMAGE_THUNK_DATA)(DllBase + ImportDescriptor->OriginalFirstThunk); 869*c2c66affSColin Finck FirstThunk = (PIMAGE_THUNK_DATA)(DllBase + ImportDescriptor->FirstThunk); 870*c2c66affSColin Finck 871*c2c66affSColin Finck /* Walk all imports */ 872*c2c66affSColin Finck for (;OriginalThunk->u1.AddressOfData && FirstThunk->u1.Function; OriginalThunk++, FirstThunk++) 873*c2c66affSColin Finck { 874*c2c66affSColin Finck if (!IMAGE_SNAP_BY_ORDINAL32(OriginalThunk->u1.AddressOfData)) 875*c2c66affSColin Finck { 876*c2c66affSColin Finck PIMAGE_IMPORT_BY_NAME ImportName; 877*c2c66affSColin Finck 878*c2c66affSColin Finck ImportName = (PIMAGE_IMPORT_BY_NAME)(DllBase + OriginalThunk->u1.AddressOfData); 879*c2c66affSColin Finck if (!strcmp((PCSTR)ImportName->Name, HookApi->FunctionName)) 880*c2c66affSColin Finck { 881*c2c66affSColin Finck SeiPatchNewImport(FirstThunk, HookApi, LdrEntry); 882*c2c66affSColin Finck 883*c2c66affSColin Finck /* Sadly, iat does not have to be sorted, and can even contain duplicate entries. */ 884*c2c66affSColin Finck dwFound++; 885*c2c66affSColin Finck } 886*c2c66affSColin Finck } 887*c2c66affSColin Finck else 888*c2c66affSColin Finck { 889*c2c66affSColin Finck SHIMENG_FAIL("Ordinals not yet supported\n"); 890*c2c66affSColin Finck ASSERT(0); 891*c2c66affSColin Finck } 892*c2c66affSColin Finck } 893*c2c66affSColin Finck 894*c2c66affSColin Finck if (dwFound != 1) 895*c2c66affSColin Finck { 896*c2c66affSColin Finck /* One entry not found. */ 897*c2c66affSColin Finck if (!dwFound) 898*c2c66affSColin Finck SHIMENG_INFO("Entry \"%s!%s\" not found for \"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName, &LdrEntry->BaseDllName); 899*c2c66affSColin Finck else 900*c2c66affSColin Finck SHIMENG_INFO("Entry \"%s!%s\" found %d times for \"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName, dwFound, &LdrEntry->BaseDllName); 901*c2c66affSColin Finck } 902*c2c66affSColin Finck } 903*c2c66affSColin Finck } 904*c2c66affSColin Finck } 905*c2c66affSColin Finck } 906*c2c66affSColin Finck 907*c2c66affSColin Finck 908*c2c66affSColin Finck VOID PatchNewModules(PPEB Peb) 909*c2c66affSColin Finck { 910*c2c66affSColin Finck PLIST_ENTRY ListHead, ListEntry; 911*c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY LdrEntry; 912*c2c66affSColin Finck 913*c2c66affSColin Finck ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 914*c2c66affSColin Finck ListEntry = ListHead->Flink; 915*c2c66affSColin Finck 916*c2c66affSColin Finck while (ListHead != ListEntry) 917*c2c66affSColin Finck { 918*c2c66affSColin Finck LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 919*c2c66affSColin Finck SeiHookImports(LdrEntry); 920*c2c66affSColin Finck 921*c2c66affSColin Finck ListEntry = ListEntry->Flink; 922*c2c66affSColin Finck } 923*c2c66affSColin Finck } 924*c2c66affSColin Finck 925*c2c66affSColin Finck 926*c2c66affSColin Finck VOID SeiInitPaths(VOID) 927*c2c66affSColin Finck { 928*c2c66affSColin Finck #define SYSTEM32 L"\\system32" 929*c2c66affSColin Finck #define WINSXS L"\\winsxs" 930*c2c66affSColin Finck 931*c2c66affSColin Finck PWSTR WindowsDirectory = SdbpStrDup(SharedUserData->NtSystemRoot); 932*c2c66affSColin Finck RtlInitUnicodeString(&g_WindowsDirectory, WindowsDirectory); 933*c2c66affSColin Finck 934*c2c66affSColin Finck g_System32Directory.MaximumLength = g_WindowsDirectory.Length + SdbpStrsize(SYSTEM32); 935*c2c66affSColin Finck g_System32Directory.Buffer = SdbpAlloc(g_System32Directory.MaximumLength); 936*c2c66affSColin Finck RtlCopyUnicodeString(&g_System32Directory, &g_WindowsDirectory); 937*c2c66affSColin Finck RtlAppendUnicodeToString(&g_System32Directory, SYSTEM32); 938*c2c66affSColin Finck 939*c2c66affSColin Finck g_SxsDirectory.MaximumLength = g_WindowsDirectory.Length + SdbpStrsize(WINSXS); 940*c2c66affSColin Finck g_SxsDirectory.Buffer = SdbpAlloc(g_SxsDirectory.MaximumLength); 941*c2c66affSColin Finck RtlCopyUnicodeString(&g_SxsDirectory, &g_WindowsDirectory); 942*c2c66affSColin Finck RtlAppendUnicodeToString(&g_SxsDirectory, WINSXS); 943*c2c66affSColin Finck 944*c2c66affSColin Finck #undef SYSTEM32 945*c2c66affSColin Finck #undef WINSXS 946*c2c66affSColin Finck } 947*c2c66affSColin Finck 948*c2c66affSColin Finck /* 949*c2c66affSColin Finck Level(INFO) Using USER apphack flags 0x2080000 950*c2c66affSColin Finck */ 951*c2c66affSColin Finck 952*c2c66affSColin Finck VOID SeiInit(PUNICODE_STRING ProcessImage, HSDB hsdb, SDBQUERYRESULT* pQuery) 953*c2c66affSColin Finck { 954*c2c66affSColin Finck DWORD n; 955*c2c66affSColin Finck ARRAY ShimRefArray; 956*c2c66affSColin Finck DWORD dwTotalHooks = 0; 957*c2c66affSColin Finck 958*c2c66affSColin Finck PPEB Peb = NtCurrentPeb(); 959*c2c66affSColin Finck 960*c2c66affSColin Finck /* We should only be called once! */ 961*c2c66affSColin Finck ASSERT(g_pShimInfo.ItemSize__ == 0); 962*c2c66affSColin Finck 963*c2c66affSColin Finck ARRAY_Init(&ShimRefArray, TAGREF); 964*c2c66affSColin Finck ARRAY_Init(&g_pShimInfo, PSHIMMODULE); 965*c2c66affSColin Finck ARRAY_Init(&g_pHookArray, HOOKMODULEINFO); 966*c2c66affSColin Finck ARRAY_Init(&g_InExclude, INEXCLUDE); 967*c2c66affSColin Finck 968*c2c66affSColin Finck SeiInitPaths(); 969*c2c66affSColin Finck 970*c2c66affSColin Finck SeiCheckComPlusImage(Peb->ImageBaseAddress); 971*c2c66affSColin Finck 972*c2c66affSColin Finck /* TODO: 973*c2c66affSColin Finck if (pQuery->trApphelp) 974*c2c66affSColin Finck SeiDisplayAppHelp(?pQuery->trApphelp?); 975*c2c66affSColin Finck */ 976*c2c66affSColin Finck 977*c2c66affSColin Finck SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(ExePath(%wZ))\n", ProcessImage); 978*c2c66affSColin Finck SeiBuildShimRefArray(hsdb, pQuery, &ShimRefArray); 979*c2c66affSColin Finck SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Complete)\n"); 980*c2c66affSColin Finck 981*c2c66affSColin Finck SHIMENG_INFO("Got %d shims\n", ARRAY_Size(&ShimRefArray)); 982*c2c66affSColin Finck SeiBuildGlobalInclExclList(hsdb); 983*c2c66affSColin Finck 984*c2c66affSColin Finck /* Walk all shims referenced (in layers + exes), and load their modules */ 985*c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&ShimRefArray); ++n) 986*c2c66affSColin Finck { 987*c2c66affSColin Finck PDB pdb; 988*c2c66affSColin Finck TAGID ShimRef; 989*c2c66affSColin Finck 990*c2c66affSColin Finck TAGREF tr = *ARRAY_At(&ShimRefArray, TAGREF, n); 991*c2c66affSColin Finck 992*c2c66affSColin Finck if (SdbTagRefToTagID(hsdb, tr, &pdb, &ShimRef)) 993*c2c66affSColin Finck { 994*c2c66affSColin Finck LPCWSTR ShimName, DllName, CommandLine = NULL; 995*c2c66affSColin Finck TAGID ShimTag; 996*c2c66affSColin Finck WCHAR FullNameBuffer[MAX_PATH]; 997*c2c66affSColin Finck UNICODE_STRING UnicodeDllName; 998*c2c66affSColin Finck PVOID BaseAddress; 999*c2c66affSColin Finck PSHIMMODULE pShimModuleInfo = NULL; 1000*c2c66affSColin Finck ANSI_STRING AnsiCommandLine = RTL_CONSTANT_STRING(""); 1001*c2c66affSColin Finck PSHIMINFO pShimInfo = NULL; 1002*c2c66affSColin Finck PHOOKAPIEX pHookApi; 1003*c2c66affSColin Finck DWORD dwHookCount; 1004*c2c66affSColin Finck 1005*c2c66affSColin Finck ShimName = SeiGetStringPtr(pdb, ShimRef, TAG_NAME); 1006*c2c66affSColin Finck if (!ShimName) 1007*c2c66affSColin Finck { 1008*c2c66affSColin Finck SHIMENG_FAIL("Failed to retrieve the name for 0x%x\n", tr); 1009*c2c66affSColin Finck continue; 1010*c2c66affSColin Finck } 1011*c2c66affSColin Finck 1012*c2c66affSColin Finck CommandLine = SeiGetStringPtr(pdb, ShimRef, TAG_COMMAND_LINE); 1013*c2c66affSColin Finck if (CommandLine && *CommandLine) 1014*c2c66affSColin Finck { 1015*c2c66affSColin Finck RtlInitUnicodeString(&UnicodeDllName, CommandLine); 1016*c2c66affSColin Finck if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiCommandLine, &UnicodeDllName, TRUE))) 1017*c2c66affSColin Finck { 1018*c2c66affSColin Finck SHIMENG_INFO("COMMAND LINE %s for %S", AnsiCommandLine.Buffer, ShimName); 1019*c2c66affSColin Finck } 1020*c2c66affSColin Finck else 1021*c2c66affSColin Finck { 1022*c2c66affSColin Finck AnsiCommandLine.Buffer = ""; 1023*c2c66affSColin Finck CommandLine = NULL; 1024*c2c66affSColin Finck } 1025*c2c66affSColin Finck } 1026*c2c66affSColin Finck 1027*c2c66affSColin Finck ShimTag = SeiGetDWORD(pdb, ShimRef, TAG_SHIM_TAGID); 1028*c2c66affSColin Finck if (!ShimTag) 1029*c2c66affSColin Finck { 1030*c2c66affSColin Finck SHIMENG_FAIL("Failed to resolve %S to a shim\n", ShimName); 1031*c2c66affSColin Finck continue; 1032*c2c66affSColin Finck } 1033*c2c66affSColin Finck 1034*c2c66affSColin Finck if (!SdbGetAppPatchDir(NULL, FullNameBuffer, ARRAYSIZE(FullNameBuffer))) 1035*c2c66affSColin Finck { 1036*c2c66affSColin Finck SHIMENG_WARN("Failed to get the AppPatch dir\n"); 1037*c2c66affSColin Finck continue; 1038*c2c66affSColin Finck } 1039*c2c66affSColin Finck 1040*c2c66affSColin Finck DllName = SeiGetStringPtr(pdb, ShimTag, TAG_DLLFILE); 1041*c2c66affSColin Finck if (DllName == NULL || 1042*c2c66affSColin Finck !SUCCEEDED(StringCchCatW(FullNameBuffer, ARRAYSIZE(FullNameBuffer), L"\\")) || 1043*c2c66affSColin Finck !SUCCEEDED(StringCchCatW(FullNameBuffer, ARRAYSIZE(FullNameBuffer), DllName))) 1044*c2c66affSColin Finck { 1045*c2c66affSColin Finck SHIMENG_WARN("Failed to build a full path for %S\n", ShimName); 1046*c2c66affSColin Finck continue; 1047*c2c66affSColin Finck } 1048*c2c66affSColin Finck 1049*c2c66affSColin Finck RtlInitUnicodeString(&UnicodeDllName, FullNameBuffer); 1050*c2c66affSColin Finck if (NT_SUCCESS(LdrGetDllHandle(NULL, NULL, &UnicodeDllName, &BaseAddress))) 1051*c2c66affSColin Finck { 1052*c2c66affSColin Finck /* This shim dll was already loaded, let's find it */ 1053*c2c66affSColin Finck pShimModuleInfo = SeiGetShimModuleInfo(BaseAddress); 1054*c2c66affSColin Finck } 1055*c2c66affSColin Finck else if (!NT_SUCCESS(LdrLoadDll(NULL, NULL, &UnicodeDllName, &BaseAddress))) 1056*c2c66affSColin Finck { 1057*c2c66affSColin Finck SHIMENG_WARN("Failed to load %wZ for %S\n", &UnicodeDllName, ShimName); 1058*c2c66affSColin Finck continue; 1059*c2c66affSColin Finck } 1060*c2c66affSColin Finck /* No shim module found (or we just loaded it) */ 1061*c2c66affSColin Finck if (!pShimModuleInfo) 1062*c2c66affSColin Finck { 1063*c2c66affSColin Finck pShimModuleInfo = SeiCreateShimModuleInfo(DllName, BaseAddress); 1064*c2c66affSColin Finck if (!pShimModuleInfo) 1065*c2c66affSColin Finck { 1066*c2c66affSColin Finck SHIMENG_FAIL("Failed to allocate ShimInfo for %S\n", DllName); 1067*c2c66affSColin Finck continue; 1068*c2c66affSColin Finck } 1069*c2c66affSColin Finck } 1070*c2c66affSColin Finck 1071*c2c66affSColin Finck SHIMENG_INFO("Shim DLL 0x%p \"%wZ\" loaded\n", BaseAddress, &UnicodeDllName); 1072*c2c66affSColin Finck SHIMENG_INFO("Using SHIM \"%S!%S\"\n", DllName, ShimName); 1073*c2c66affSColin Finck 1074*c2c66affSColin Finck /* Ask this shim what hooks it needs (and pass along the commandline) */ 1075*c2c66affSColin Finck pHookApi = pShimModuleInfo->pGetHookAPIs(AnsiCommandLine.Buffer, ShimName, &dwHookCount); 1076*c2c66affSColin Finck SHIMENG_INFO("GetHookAPIs returns %d hooks for DLL \"%wZ\" SHIM \"%S\"\n", dwHookCount, &UnicodeDllName, ShimName); 1077*c2c66affSColin Finck if (dwHookCount) 1078*c2c66affSColin Finck pShimInfo = SeiAppendHookInfo(pShimModuleInfo, pHookApi, dwHookCount, ShimName); 1079*c2c66affSColin Finck 1080*c2c66affSColin Finck /* If this shim has hooks, create the include / exclude lists */ 1081*c2c66affSColin Finck if (pShimInfo) 1082*c2c66affSColin Finck SeiBuildInclExclList(pdb, ShimTag, pShimInfo); 1083*c2c66affSColin Finck 1084*c2c66affSColin Finck if (CommandLine && *CommandLine) 1085*c2c66affSColin Finck RtlFreeAnsiString(&AnsiCommandLine); 1086*c2c66affSColin Finck 1087*c2c66affSColin Finck dwTotalHooks += dwHookCount; 1088*c2c66affSColin Finck } 1089*c2c66affSColin Finck } 1090*c2c66affSColin Finck 1091*c2c66affSColin Finck SeiAddInternalHooks(dwTotalHooks); 1092*c2c66affSColin Finck SeiResolveAPIs(); 1093*c2c66affSColin Finck PatchNewModules(Peb); 1094*c2c66affSColin Finck } 1095*c2c66affSColin Finck 1096*c2c66affSColin Finck 1097*c2c66affSColin Finck /* Load the database + unpack the shim data (if this process is allowed) */ 1098*c2c66affSColin Finck BOOL SeiGetShimData(PUNICODE_STRING ProcessImage, PVOID pShimData, HSDB* pHsdb, SDBQUERYRESULT* pQuery) 1099*c2c66affSColin Finck { 1100*c2c66affSColin Finck static const UNICODE_STRING ForbiddenShimmingApps[] = { 1101*c2c66affSColin Finck RTL_CONSTANT_STRING(L"ntsd.exe"), 1102*c2c66affSColin Finck RTL_CONSTANT_STRING(L"windbg.exe"), 1103*c2c66affSColin Finck #if WINVER >= 0x600 1104*c2c66affSColin Finck RTL_CONSTANT_STRING(L"slsvc.exe"), 1105*c2c66affSColin Finck #endif 1106*c2c66affSColin Finck }; 1107*c2c66affSColin Finck static const UNICODE_STRING BackSlash = RTL_CONSTANT_STRING(L"\\"); 1108*c2c66affSColin Finck static const UNICODE_STRING ForwdSlash = RTL_CONSTANT_STRING(L"/"); 1109*c2c66affSColin Finck UNICODE_STRING ProcessName; 1110*c2c66affSColin Finck USHORT Back, Forward; 1111*c2c66affSColin Finck HSDB hsdb; 1112*c2c66affSColin Finck DWORD n; 1113*c2c66affSColin Finck 1114*c2c66affSColin Finck if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, ProcessImage, &BackSlash, &Back))) 1115*c2c66affSColin Finck Back = 0; 1116*c2c66affSColin Finck 1117*c2c66affSColin Finck if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, ProcessImage, &ForwdSlash, &Forward))) 1118*c2c66affSColin Finck Forward = 0; 1119*c2c66affSColin Finck 1120*c2c66affSColin Finck if (Back < Forward) 1121*c2c66affSColin Finck Back = Forward; 1122*c2c66affSColin Finck 1123*c2c66affSColin Finck if (Back) 1124*c2c66affSColin Finck Back += sizeof(WCHAR); 1125*c2c66affSColin Finck 1126*c2c66affSColin Finck ProcessName.Buffer = ProcessImage->Buffer + Back / sizeof(WCHAR); 1127*c2c66affSColin Finck ProcessName.Length = ProcessImage->Length - Back; 1128*c2c66affSColin Finck ProcessName.MaximumLength = ProcessImage->MaximumLength - Back; 1129*c2c66affSColin Finck 1130*c2c66affSColin Finck for (n = 0; n < ARRAYSIZE(ForbiddenShimmingApps); ++n) 1131*c2c66affSColin Finck { 1132*c2c66affSColin Finck if (RtlEqualUnicodeString(&ProcessName, ForbiddenShimmingApps + n, TRUE)) 1133*c2c66affSColin Finck { 1134*c2c66affSColin Finck SHIMENG_MSG("Not shimming %wZ\n", ForbiddenShimmingApps + n); 1135*c2c66affSColin Finck return FALSE; 1136*c2c66affSColin Finck } 1137*c2c66affSColin Finck } 1138*c2c66affSColin Finck 1139*c2c66affSColin Finck /* We should probably load all db's here, but since we do not support that yet... */ 1140*c2c66affSColin Finck hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL); 1141*c2c66affSColin Finck if (hsdb) 1142*c2c66affSColin Finck { 1143*c2c66affSColin Finck if (SdbUnpackAppCompatData(hsdb, ProcessImage->Buffer, pShimData, pQuery)) 1144*c2c66affSColin Finck { 1145*c2c66affSColin Finck *pHsdb = hsdb; 1146*c2c66affSColin Finck return TRUE; 1147*c2c66affSColin Finck } 1148*c2c66affSColin Finck SdbReleaseDatabase(hsdb); 1149*c2c66affSColin Finck } 1150*c2c66affSColin Finck return FALSE; 1151*c2c66affSColin Finck } 1152*c2c66affSColin Finck 1153*c2c66affSColin Finck 1154*c2c66affSColin Finck 1155*c2c66affSColin Finck VOID NTAPI SE_InstallBeforeInit(PUNICODE_STRING ProcessImage, PVOID pShimData) 1156*c2c66affSColin Finck { 1157*c2c66affSColin Finck HSDB hsdb = NULL; 1158*c2c66affSColin Finck SDBQUERYRESULT QueryResult = { { 0 } }; 1159*c2c66affSColin Finck SHIMENG_MSG("(%wZ, %p)\n", ProcessImage, pShimData); 1160*c2c66affSColin Finck 1161*c2c66affSColin Finck if (!SeiGetShimData(ProcessImage, pShimData, &hsdb, &QueryResult)) 1162*c2c66affSColin Finck { 1163*c2c66affSColin Finck SHIMENG_FAIL("Failed to get shim data\n"); 1164*c2c66affSColin Finck return; 1165*c2c66affSColin Finck } 1166*c2c66affSColin Finck 1167*c2c66affSColin Finck g_bShimDuringInit = TRUE; 1168*c2c66affSColin Finck SeiInit(ProcessImage, hsdb, &QueryResult); 1169*c2c66affSColin Finck g_bShimDuringInit = FALSE; 1170*c2c66affSColin Finck 1171*c2c66affSColin Finck SdbReleaseDatabase(hsdb); 1172*c2c66affSColin Finck } 1173*c2c66affSColin Finck 1174*c2c66affSColin Finck VOID NTAPI SE_InstallAfterInit(PUNICODE_STRING ProcessImage, PVOID pShimData) 1175*c2c66affSColin Finck { 1176*c2c66affSColin Finck NotifyShims(SHIM_NOTIFY_ATTACH, NULL); 1177*c2c66affSColin Finck } 1178*c2c66affSColin Finck 1179*c2c66affSColin Finck VOID NTAPI SE_ProcessDying(VOID) 1180*c2c66affSColin Finck { 1181*c2c66affSColin Finck SHIMENG_MSG("()\n"); 1182*c2c66affSColin Finck NotifyShims(SHIM_NOTIFY_DETACH, NULL); 1183*c2c66affSColin Finck } 1184*c2c66affSColin Finck 1185*c2c66affSColin Finck VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry) 1186*c2c66affSColin Finck { 1187*c2c66affSColin Finck SHIMENG_INFO("%sINIT. loading DLL \"%wZ\"\n", g_bShimDuringInit ? "" : "AFTER ", &LdrEntry->BaseDllName); 1188*c2c66affSColin Finck NotifyShims(SHIM_REASON_DLL_LOAD, LdrEntry); 1189*c2c66affSColin Finck } 1190*c2c66affSColin Finck 1191*c2c66affSColin Finck VOID WINAPI SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY LdrEntry) 1192*c2c66affSColin Finck { 1193*c2c66affSColin Finck SHIMENG_INFO("(%p)\n", LdrEntry); 1194*c2c66affSColin Finck NotifyShims(SHIM_REASON_DLL_UNLOAD, LdrEntry); 1195*c2c66affSColin Finck } 1196*c2c66affSColin Finck 1197*c2c66affSColin Finck BOOL WINAPI SE_IsShimDll(PVOID BaseAddress) 1198*c2c66affSColin Finck { 1199*c2c66affSColin Finck SHIMENG_INFO("(%p)\n", BaseAddress); 1200*c2c66affSColin Finck 1201*c2c66affSColin Finck return SeiGetShimModuleInfo(BaseAddress) != NULL; 1202*c2c66affSColin Finck } 1203*c2c66affSColin Finck 1204