Files
Open-Shell-Menu/ClassicStartSrc/ClassicStartLib/IatHookHelper.cpp
Xenhat 0adcd693e4 Some branding and licensing work (#22)
* Fix stdafx include

* Fix basic handling of "Games" folder on Windows10 RS4 (#10)
This does the following:
- Sets the default state to hidden
- Skips the Games folder when searching

This does not:
- Hide the dead menu entry.

I do not currently know how to actively change the user preference setting to forcefully hide it.

* Add basic Visual Studio gitignore

* Add specific entries to gitignore

* Do not set default menu to Win7 on RS4 (#10)

* Rename "PC Settings" to "Settings" (#12)

* Create distinction between modern and legacy settings in search results

* Add more build artifacts to gitignore

* Add default paths for toolset and build all languages

* Fix several memsize, memtype and nullpointer issues

* create trunk branch containing all changes

* set fallback and next version to 4.3.2, set resource fallback value to allow loading in IDE

* add generated en-US.dll to gitignore

* Don't echo script contents, add disabled "git clean -dfx" to build fresh

* Initial re-branding work (#21)

* Create copy of __MakeFinal to build all languages (Use this file when releasing new versions)

* Move the registry key IvoSoft->Passionate-Coder (#21)

* Change company/mfg name IvoSoft->Passionate-Coder (#21)

* Update some leftover copyright dates (#21)

* Fix accidental copy-paste breaking MakeFinal scripts

* Fix invalid company name for Wix and change registry keys to match the new string (#21)

* Update more copyright and legal text (#21)

* Update RTF files format (Wordpad generated those) (#21)

* update license text in RTF files (#21)
We lost the blue link text in the installer page. Will have to manually re-color all the links later.
2018-06-25 01:42:52 -04:00

145 lines
4.7 KiB
C++

// Classic Shell (c) 2009-2017, Ivo Beltchev
// Classic Start (c) 2017-2018, The Passionate-Coder Team
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
#include <stdafx.h>
#include "IatHookHelper.h"
#include "Assert.h"
struct ImgDelayDescr
{
DWORD grAttrs; // attributes
DWORD rvaDLLName; // RVA to dll name
DWORD rvaHmod; // RVA of module handle
DWORD rvaIAT; // RVA of the IAT
DWORD rvaINT; // RVA of the INT
DWORD rvaBoundIAT; // RVA of the optional bound IAT
DWORD rvaUnloadIAT; // RVA of optional copy of original IAT
DWORD dwTimeStamp; // 0 if not bound, O.W. date/time stamp of DLL bound to (Old BIND)
};
static void *PtrFromRva( IMAGE_DOS_HEADER *dosHeader, size_t offset )
{
return (BYTE*)dosHeader+offset;
}
static IatHookData *g_IatHooks;
static int g_IatHookCount;
const int MAX_IAT_HOOKS=4096/sizeof(IatHookData);
void InitializeIatHooks( void )
{
Assert(!g_IatHooks);
g_IatHooks=(IatHookData*)VirtualAlloc(NULL,4096,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
g_IatHookCount=0;
}
void ClearIatHooks( void )
{
if (!g_IatHooks) return;
for (int i=0;i<g_IatHookCount;i++)
{
if (g_IatHooks[i].jump[0])
return; // still used
}
VirtualFree(g_IatHooks,0,MEM_RELEASE);
g_IatHooks=NULL;
g_IatHookCount=0;
}
IatHookData *SetIatHook( IMAGE_DOS_HEADER *dosHeader, DWORD iatOffset, DWORD intOfset, const char *targetProc, void *newProc )
{
IMAGE_THUNK_DATA *thunk=(IMAGE_THUNK_DATA*)PtrFromRva(dosHeader,iatOffset);
IMAGE_THUNK_DATA *origThunk=(IMAGE_THUNK_DATA*)PtrFromRva(dosHeader,intOfset);
for (;origThunk->u1.Function;origThunk++,thunk++)
{
if (origThunk->u1.Ordinal&IMAGE_ORDINAL_FLAG)
{
if (IS_INTRESOURCE(targetProc) && IMAGE_ORDINAL(origThunk->u1.Ordinal)==(uintptr_t)targetProc)
break;
}
else
{
IMAGE_IMPORT_BY_NAME *import=(IMAGE_IMPORT_BY_NAME*)PtrFromRva(dosHeader,origThunk->u1.AddressOfData);
if (!IS_INTRESOURCE(targetProc) && strcmp(targetProc,(char*)import->Name)==0)
break;
}
}
if (origThunk->u1.Function)
{
IatHookData *hook=g_IatHooks+g_IatHookCount;
g_IatHookCount++;
hook->jump[0]=hook->jump[1]=0x90; // NOP
hook->jump[2]=0xFF; hook->jump[3]=0x25; // JUMP
#ifdef _WIN64
hook->jumpOffs=0;
#else
hook->jumpOffs=(DWORD)(hook)+8;
#endif
hook->newProc=newProc;
hook->oldProc=(void*)thunk->u1.Function;
hook->thunk=thunk;
DWORD oldProtect;
VirtualProtect(&thunk->u1.Function,sizeof(void*),PAGE_READWRITE,&oldProtect);
thunk->u1.Function=(DWORD_PTR)hook;
VirtualProtect(&thunk->u1.Function,sizeof(void*),oldProtect,&oldProtect);
return hook;
}
return NULL;
}
IatHookData *SetIatHook( HMODULE hPatchedModule, const char *targetModule, const char *targetProc, void *newProc )
{
ATLASSERT(g_IatHooks);
if (g_IatHookCount>=MAX_IAT_HOOKS) return NULL;
IMAGE_DOS_HEADER *dosHeader=(IMAGE_DOS_HEADER*)hPatchedModule;
IMAGE_NT_HEADERS *ntHeader=(IMAGE_NT_HEADERS*)PtrFromRva(dosHeader,dosHeader->e_lfanew);
if (ntHeader->Signature!=IMAGE_NT_SIGNATURE) return NULL;
IMAGE_IMPORT_DESCRIPTOR *importDescriptor=(IMAGE_IMPORT_DESCRIPTOR*)PtrFromRva(dosHeader,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (;importDescriptor->Characteristics!=0;importDescriptor++)
{
const char *dllName=(char*)PtrFromRva(dosHeader,importDescriptor->Name);
if (_stricmp(dllName,targetModule)!=0) continue;
if (!importDescriptor->FirstThunk || !importDescriptor->OriginalFirstThunk) break;
return SetIatHook(dosHeader,importDescriptor->FirstThunk,importDescriptor->OriginalFirstThunk,targetProc,newProc);
}
ImgDelayDescr *delayDescriptor=(ImgDelayDescr*)PtrFromRva(dosHeader,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress);
for (;delayDescriptor->rvaDLLName!=0;delayDescriptor++)
{
const char *dllName=(char*)PtrFromRva(dosHeader,delayDescriptor->rvaDLLName);
if (_stricmp(dllName,targetModule)!=0) continue;
if (!delayDescriptor->rvaIAT || !delayDescriptor->rvaINT) break;
return SetIatHook(dosHeader,delayDescriptor->rvaIAT,delayDescriptor->rvaINT,targetProc,newProc);
}
return NULL;
}
void ClearIatHook( IatHookData *hook )
{
if (!hook || !hook->jump[0]) return;
if (hook->thunk->u1.Function==(DWORD_PTR)hook)
{
// the hook was untouched by anybody else
DWORD oldProtect;
VirtualProtect(&hook->thunk->u1.Function,sizeof(void*),PAGE_READWRITE,&oldProtect);
void *cex=InterlockedCompareExchangePointer((void**)&hook->thunk->u1.Function,hook->oldProc,hook);
VirtualProtect(&hook->thunk->u1.Function,sizeof(void*),oldProtect,&oldProtect);
if (cex==hook)
{
hook->jump[0]=0;
return; // successfully replaced the original function
}
}
// failed to replace the original function, leave behind the thunk
hook->newProc=hook->oldProc;
}