https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1570f08b4d82e44928d7b…
commit 1570f08b4d82e44928d7b328fa07aa32759858e5
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sun Feb 11 22:40:51 2018 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Wed May 1 19:22:19 2019 +0200
[APPHELP] Add ordinal import support
---
dll/appcompat/apphelp/shimeng.c | 155 +++++++++++++++++++++++++---------------
1 file changed, 96 insertions(+), 59 deletions(-)
diff --git a/dll/appcompat/apphelp/shimeng.c b/dll/appcompat/apphelp/shimeng.c
index 3e8a169617..190e17c2a7 100644
--- a/dll/appcompat/apphelp/shimeng.c
+++ b/dll/appcompat/apphelp/shimeng.c
@@ -37,6 +37,7 @@ static ARRAY g_pShimInfo; /* PSHIMMODULE */
static ARRAY g_pHookArray; /* HOOKMODULEINFO */
static ARRAY g_InExclude; /* INEXCLUDE */
+typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HINSTANCE, LPCSTR);
/* If we have setup a hook for a function, we should also redirect GetProcAddress for
this function */
HOOKAPIEX g_IntHookEx[] =
{
@@ -207,6 +208,39 @@ BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR Function, PCSTR
Format, ...)
return TRUE;
}
+static
+BOOL SeiIsOrdinalName(LPCSTR lpProcName)
+{
+ return (ULONG_PTR)lpProcName <= MAXUSHORT;
+}
+
+LPCSTR SeiPrintFunctionName(LPCSTR lpProcName, char szOrdProcFmt[10])
+{
+ if (SeiIsOrdinalName(lpProcName))
+ {
+ StringCchPrintfA(szOrdProcFmt, 10, "#%Iu", (ULONG_PTR)lpProcName);
+ return szOrdProcFmt;
+ }
+ return lpProcName;
+}
+
+int SeiCompareFunctionName(LPCSTR lpProcName1, LPCSTR lpProcName2)
+{
+ BOOL Ord1 = SeiIsOrdinalName(lpProcName1);
+ BOOL Ord2 = SeiIsOrdinalName(lpProcName2);
+
+ /* One is an ordinal, the other not */
+ if (Ord1 != Ord2)
+ return 1;
+
+ /* Compare ordinals */
+ if (Ord1)
+ return (ULONG_PTR)lpProcName1 != (ULONG_PTR)lpProcName2;
+
+ /* Compare names */
+ return strcmp(lpProcName1, lpProcName2);
+}
+
PVOID SeiGetModuleFromAddress(PVOID addr)
{
@@ -216,7 +250,6 @@ PVOID SeiGetModuleFromAddress(PVOID addr)
}
-
/* TODO: Guard against recursive calling / calling init multiple times! */
VOID NotifyShims(DWORD dwReason, PVOID Info)
{
@@ -429,7 +462,7 @@ static VOID SeiSetLayerEnvVar(LPCWSTR wszLayer)
Status = RtlSetEnvironmentVariable(NULL, &VarName, &Value);
if (NT_SUCCESS(Status))
- SHIMENG_INFO("Set env var %wZ=%wZ\n", &VarName, &Value);
+ SHIMENG_INFO("%wZ=%wZ\n", &VarName, &Value);
else
SHIMENG_FAIL("Failed to set %wZ: 0x%x\n", &VarName, Status);
}
@@ -542,7 +575,6 @@ VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO
pShim)
continue;
}
- RtlInitAnsiString(&AnsiString, hook->FunctionName);
if (NT_SUCCESS(LdrGetDllHandle(NULL, 0, &UnicodeModName, &DllHandle)))
{
HookModuleInfo = SeiFindHookModuleInfo(NULL, DllHandle);
@@ -569,7 +601,7 @@ VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO
pShim)
for (j = 0; j < ARRAY_Size(&HookModuleInfo->HookApis); ++j)
{
PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX,
j);
- int CmpResult = strcmp(hook->FunctionName, HookApi->FunctionName);
+ int CmpResult = SeiCompareFunctionName(hook->FunctionName,
HookApi->FunctionName);
if (CmpResult == 0)
{
while (HookApi->ApiLink)
@@ -591,42 +623,32 @@ VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO
pShim)
}
}
-typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HINSTANCE, LPCSTR);
-
/* Check if we should fake the return from GetProcAddress (because we also redirected the
iat for this module) */
FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName)
{
- char szOrdProcName[10] = "";
- LPCSTR lpPrintName = lpProcName;
PVOID Addr = _ReturnAddress();
PHOOKMODULEINFO HookModuleInfo;
FARPROC proc = ((GETPROCADDRESSPROC)g_IntHookEx[0].OriginalFunction)(hModule,
lpProcName);
-
- if ((DWORD_PTR)lpProcName <= MAXUSHORT)
- {
- sprintf(szOrdProcName, "#%Iu", (DWORD_PTR)lpProcName);
- lpPrintName = szOrdProcName;
- }
+ char szOrdProcFmt[10];
Addr = SeiGetModuleFromAddress(Addr);
if (SE_IsShimDll(Addr))
{
- SHIMENG_MSG("Not touching GetProcAddress for shim dll (%p!%s)",
hModule, lpPrintName);
+ SHIMENG_MSG("Not touching GetProcAddress for shim dll (%p!%s)",
hModule, SeiPrintFunctionName(lpProcName, szOrdProcFmt));
return proc;
}
- SHIMENG_INFO("(GetProcAddress(%p!%s) => %p\n", hModule, lpPrintName,
proc);
+ SHIMENG_INFO("(GetProcAddress(%p!%s) => %p\n", hModule,
SeiPrintFunctionName(lpProcName, szOrdProcFmt), proc);
HookModuleInfo = SeiFindHookModuleInfo(NULL, hModule);
- /* FIXME: Ordinal not yet supported */
- if (HookModuleInfo && HIWORD(lpProcName))
+ if (HookModuleInfo)
{
DWORD n;
for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n)
{
PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX,
n);
- int CmpResult = strcmp(lpProcName, HookApi->FunctionName);
+ int CmpResult = SeiCompareFunctionName(lpProcName,
HookApi->FunctionName);
if (CmpResult == 0)
{
SHIMENG_MSG("Redirecting %p to %p\n", proc,
HookApi->ReplacementFunction);
@@ -648,13 +670,25 @@ VOID SeiResolveAPI(PHOOKMODULEINFO HookModuleInfo)
for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n)
{
+ NTSTATUS Status;
PVOID ProcAddress;
PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n);
- RtlInitAnsiString(&AnsiString, HookApi->FunctionName);
- if (!NT_SUCCESS(LdrGetProcedureAddress(HookModuleInfo->BaseAddress,
&AnsiString, 0, &ProcAddress)))
+ if (!SeiIsOrdinalName(HookApi->FunctionName))
+ {
+ RtlInitAnsiString(&AnsiString, HookApi->FunctionName);
+ Status = LdrGetProcedureAddress(HookModuleInfo->BaseAddress,
&AnsiString, 0, &ProcAddress);
+ }
+ else
+ {
+ Status = LdrGetProcedureAddress(HookModuleInfo->BaseAddress, NULL,
(ULONG_PTR)HookApi->FunctionName, &ProcAddress);
+ }
+
+ if (!NT_SUCCESS(Status))
{
- SHIMENG_FAIL("Unable to retrieve %s!%s\n", HookApi->LibraryName,
HookApi->FunctionName);
+ char szOrdProcFmt[10];
+ LPCSTR lpFunctionName = SeiPrintFunctionName(HookApi->FunctionName,
szOrdProcFmt);
+ SHIMENG_FAIL("Unable to retrieve %s!%s\n", HookApi->LibraryName,
lpFunctionName);
continue;
}
@@ -732,8 +766,9 @@ VOID SeiPatchNewImport(PIMAGE_THUNK_DATA FirstThunk, PHOOKAPIEX
HookApi, PLDR_DA
PVOID Ptr;
SIZE_T Size;
NTSTATUS Status;
+ char szOrdProcFmt[10];
- SHIMENG_INFO("Hooking API \"%s!%s\" for DLL \"%wZ\"\n",
HookApi->LibraryName, HookApi->FunctionName, &LdrEntry->BaseDllName);
+ SHIMENG_INFO("Hooking API \"%s!%s\" for DLL \"%wZ\"\n",
HookApi->LibraryName, SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt),
&LdrEntry->BaseDllName);
Ptr = &FirstThunk->u1.Function;
Size = sizeof(FirstThunk->u1.Function);
@@ -746,11 +781,7 @@ VOID SeiPatchNewImport(PIMAGE_THUNK_DATA FirstThunk, PHOOKAPIEX
HookApi, PLDR_DA
}
SHIMENG_INFO("changing 0x%p to 0x%p\n", FirstThunk->u1.Function,
HookApi->ReplacementFunction);
-#ifdef _WIN64
- FirstThunk->u1.Function = (ULONGLONG)HookApi->ReplacementFunction;
-#else
- FirstThunk->u1.Function = (DWORD)HookApi->ReplacementFunction;
-#endif
+ FirstThunk->u1.Function = (ULONG_PTR)HookApi->ReplacementFunction;
Size = sizeof(FirstThunk->u1.Function);
Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size,
OldProtection, &OldProtection);
@@ -782,6 +813,7 @@ BOOL SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry, PHOOKAPIEX
HookApi)
PSHIMINFO pShimInfo = HookApi->pShimInfo;
PINEXCLUDE InExclude;
BOOL IsExcluded = FALSE;
+ char szOrdProcFmt[10];
if (!pShimInfo)
{
@@ -801,7 +833,7 @@ BOOL SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry, PHOOKAPIEX
HookApi)
if (!InExclude->Include)
{
SHIMENG_INFO("Module '%wZ' excluded for shim %S, API
'%s!%s', because it on in the exclude list.\n",
- &LdrEntry->BaseDllName, pShimInfo->ShimName,
HookApi->LibraryName, HookApi->FunctionName);
+ &LdrEntry->BaseDllName, pShimInfo->ShimName,
HookApi->LibraryName, SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt));
return TRUE;
}
@@ -809,7 +841,7 @@ BOOL SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry, PHOOKAPIEX
HookApi)
if (IsExcluded)
{
SHIMENG_INFO("Module '%wZ' included for shim %S, API
'%s!%s', because it is on the include list.\n",
- &LdrEntry->BaseDllName, pShimInfo->ShimName,
HookApi->LibraryName, HookApi->FunctionName);
+ &LdrEntry->BaseDllName, pShimInfo->ShimName,
HookApi->LibraryName, SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt));
}
IsExcluded = FALSE;
@@ -818,7 +850,7 @@ BOOL SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry, PHOOKAPIEX
HookApi)
if (IsExcluded)
{
SHIMENG_INFO("Module '%wZ' excluded for shim %S, API
'%s!%s', because it is in System32/WinSXS.\n",
- &LdrEntry->BaseDllName, pShimInfo->ShimName,
HookApi->LibraryName, HookApi->FunctionName);
+ &LdrEntry->BaseDllName, pShimInfo->ShimName,
HookApi->LibraryName, SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt));
}
return IsExcluded;
@@ -974,33 +1006,45 @@ VOID SeiHookImports(PLDR_DATA_TABLE_ENTRY LdrEntry)
/* Walk all imports */
for (;OriginalThunk->u1.AddressOfData &&
FirstThunk->u1.Function; OriginalThunk++, FirstThunk++)
{
- if (!IMAGE_SNAP_BY_ORDINAL32(OriginalThunk->u1.AddressOfData))
+ if (!IMAGE_SNAP_BY_ORDINAL(OriginalThunk->u1.Function))
{
- PIMAGE_IMPORT_BY_NAME ImportName;
-
- ImportName = (PIMAGE_IMPORT_BY_NAME)(DllBase +
OriginalThunk->u1.AddressOfData);
- if (!strcmp((PCSTR)ImportName->Name,
HookApi->FunctionName))
+ if (!SeiIsOrdinalName(HookApi->FunctionName))
{
- SeiPatchNewImport(FirstThunk, HookApi, LdrEntry);
+ PIMAGE_IMPORT_BY_NAME ImportName;
- /* Sadly, iat does not have to be sorted, and can even
contain duplicate entries. */
- dwFound++;
+ ImportName = (PIMAGE_IMPORT_BY_NAME)(DllBase +
OriginalThunk->u1.Function);
+ if (!strcmp((PCSTR)ImportName->Name,
HookApi->FunctionName))
+ {
+ SeiPatchNewImport(FirstThunk, HookApi, LdrEntry);
+
+ /* Sadly, iat does not have to be sorted, and can even
contain duplicate entries. */
+ dwFound++;
+ }
}
}
else
{
- SHIMENG_FAIL("Ordinals not yet supported\n");
- ASSERT(0);
+ if (SeiIsOrdinalName(HookApi->FunctionName))
+ {
+ if ((PCSTR)IMAGE_ORDINAL(OriginalThunk->u1.Function) ==
HookApi->FunctionName)
+ {
+ SeiPatchNewImport(FirstThunk, HookApi, LdrEntry);
+ dwFound++;
+ }
+ }
}
}
if (dwFound != 1)
{
+ char szOrdProcFmt[10];
+ LPCSTR FuncName = SeiPrintFunctionName(HookApi->FunctionName,
szOrdProcFmt);
+
/* One entry not found. */
if (!dwFound)
- SHIMENG_INFO("Entry \"%s!%s\" not found for
\"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName,
&LdrEntry->BaseDllName);
+ SHIMENG_INFO("Entry \"%s!%s\" not found for
\"%wZ\"\n", HookApi->LibraryName, FuncName,
&LdrEntry->BaseDllName);
else
- SHIMENG_INFO("Entry \"%s!%s\" found %d times for
\"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName, dwFound,
&LdrEntry->BaseDllName);
+ SHIMENG_INFO("Entry \"%s!%s\" found %d times for
\"%wZ\"\n", HookApi->LibraryName, FuncName, dwFound,
&LdrEntry->BaseDllName);
}
}
}
@@ -1315,28 +1359,21 @@ BOOL SeiGetShimData(PUNICODE_STRING ProcessImage, PVOID pShimData,
HSDB* pHsdb,
RTL_CONSTANT_STRING(L"slsvc.exe"),
#endif
};
- static const UNICODE_STRING BackSlash = RTL_CONSTANT_STRING(L"\\");
- static const UNICODE_STRING ForwdSlash = RTL_CONSTANT_STRING(L"/");
+ static const UNICODE_STRING PathDividerFind = RTL_CONSTANT_STRING(L"\\/");
UNICODE_STRING ProcessName;
- USHORT Back, Forward;
+ USHORT PathDivider;
HSDB hsdb;
DWORD n;
- if
(!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
ProcessImage, &BackSlash, &Back)))
- Back = 0;
-
- if
(!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
ProcessImage, &ForwdSlash, &Forward)))
- Forward = 0;
-
- if (Back < Forward)
- Back = Forward;
+ if
(!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
ProcessImage, &PathDividerFind, &PathDivider)))
+ PathDivider = 0;
- if (Back)
- Back += sizeof(WCHAR);
+ if (PathDivider)
+ PathDivider += sizeof(WCHAR);
- ProcessName.Buffer = ProcessImage->Buffer + Back / sizeof(WCHAR);
- ProcessName.Length = ProcessImage->Length - Back;
- ProcessName.MaximumLength = ProcessImage->MaximumLength - Back;
+ ProcessName.Buffer = ProcessImage->Buffer + PathDivider / sizeof(WCHAR);
+ ProcessName.Length = ProcessImage->Length - PathDivider;
+ ProcessName.MaximumLength = ProcessImage->MaximumLength - PathDivider;
for (n = 0; n < ARRAYSIZE(ForbiddenShimmingApps); ++n)
{