Beispiel #1
0
	MH_STATUS CreateHook(void* pTarget, void* const pDetour, void** ppOriginal)
	{
		CriticalSection::ScopedLock lock(*gCS);

		if (!gIsInitialized)
		{
			return MH_ERROR_NOT_INITIALIZED;
		}

		HOOK_ENTRY *pHook = FindHook(pTarget);
		if (pHook != NULL)
		{
			return MH_ERROR_ALREADY_CREATED;
		}

		if (!IsExecutableAddress(pTarget) || !IsExecutableAddress(pDetour))
		{
			return MH_ERROR_NOT_EXECUTABLE;
		}

		{
			bool committed = false;
			RollbackIfNotCommitted scopedRollback(&committed);

			// トランポリン関数を作成する
			CREATE_TREMPOLINE_T ct = { 0 };
			ct.pTarget = pTarget;
			if (!CreateTrampolineFunction(ct))
			{
				return MH_ERROR_UNSUPPORTED_FUNCTION;
			}

			void* pJmpPtr = pTarget;
			if (ct.patchAbove)
			{
				pJmpPtr = reinterpret_cast<char*>(pJmpPtr) - sizeof(JMP_REL);
			}

			void* pTrampoline = AllocateCodeBuffer(pJmpPtr, ct.trampoline.size());
			if (pTrampoline == NULL)
			{
				return MH_ERROR_MEMORY_ALLOC;
			}
#if defined _M_X64
			void* pTable = AllocateDataBuffer(pTrampoline, (ct.table.size() + 1) * sizeof(uintptr_t));
			if (pTable == NULL)
			{
				return MH_ERROR_MEMORY_ALLOC;
			}
#endif

			ct.pTrampoline = pTrampoline;
#if defined _M_X64
			ct.pTable = pTable;
#endif
			if (!ResolveTemporaryAddresses(ct))
			{
				return MH_ERROR_UNSUPPORTED_FUNCTION;
			}

			memcpy(pTrampoline, &ct.trampoline[ 0 ], ct.trampoline.size());
#if defined _M_X64
			if (ct.table.size() != 0)
			{
				memcpy(pTable, &ct.table[ 0 ], ct.table.size() * sizeof(uintptr_t));
			}
#endif

			// ターゲット関数のバックアップをとる
			size_t backupSize = sizeof(JMP_REL);
			if (ct.patchAbove)
			{
				backupSize += sizeof(JMP_REL_SHORT);
			}

			void* pBackup = AllocateDataBuffer(NULL, backupSize);
			if (pBackup == NULL)
			{
				return MH_ERROR_MEMORY_ALLOC;
			}

			memcpy(pBackup, pJmpPtr, backupSize);

			// 中継関数を作成する
#if defined _M_X64
			void* pRelay = AllocateCodeBuffer(pJmpPtr, sizeof(JMP_ABS));
			if (pRelay == NULL)
			{
				return MH_ERROR_MEMORY_ALLOC;
			}

			WriteAbsoluteJump(pRelay, pDetour, reinterpret_cast<uintptr_t*>(pTable) + ct.table.size());
#endif
			CommitBuffer();
			committed = true;

			// フック情報の登録
			HOOK_ENTRY hook = { 0 };
			hook.pTarget = pTarget;
			hook.pDetour = pDetour;
#if defined _M_X64
			hook.pTable  = pTable;
			hook.pRelay  = pRelay;
#endif
			hook.pTrampoline = pTrampoline;
			hook.pBackup = pBackup;
			hook.patchAbove = ct.patchAbove;
			hook.isEnabled = false;
			hook.queueEnable = false;
			hook.oldIPs = ct.oldIPs;
			hook.newIPs = ct.newIPs;

			std::vector<HOOK_ENTRY>::iterator i	= std::lower_bound(gHooks.begin(), gHooks.end(), hook);
			i = gHooks.insert(i, hook);
			pHook = &(*i);
		}

		// OUT引数の処理
		*ppOriginal = pHook->pTrampoline;

		return MH_OK;
	}
Beispiel #2
0
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal)
{
    MH_STATUS status = MH_OK;

    EnterSpinLock();

    if (g_hHeap != NULL)
    {
        if ((g_Flags & MH_FLAGS_SKIP_EXEC_CHECK)
            || (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour))
            )
        {
            UINT pos = FindHookEntry(pTarget);
            if (pos == INVALID_HOOK_POS)
            {
                LPVOID pBuffer = AllocateBuffer(pTarget);
                if (pBuffer != NULL)
                {
                    TRAMPOLINE ct;

                    ct.pTarget = pTarget;
                    ct.pDetour = pDetour;
                    ct.pTrampoline = pBuffer;
                    if (CreateTrampolineFunction(&ct))
                    {
                        PHOOK_ENTRY pHook = AddHookEntry();
                        if (pHook != NULL)
                        {
                            pHook->pTarget     = ct.pTarget;
#ifdef _M_X64
                            pHook->pDetour     = ct.pRelay;
#else
                            pHook->pDetour     = ct.pDetour;
#endif
                            pHook->pTrampoline = ct.pTrampoline;
                            pHook->patchAbove  = ct.patchAbove;
                            pHook->isEnabled   = FALSE;
                            pHook->queueEnable = FALSE;
                            pHook->nIP         = ct.nIP;
                            memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs));
                            memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs));

                            // Back up the target function.

                            if (ct.patchAbove)
                            {
                                memcpy(
                                    pHook->backup,
                                    (LPBYTE)pTarget - sizeof(JMP_REL),
                                    sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
                            }
                            else
                            {
                                memcpy(pHook->backup, pTarget, sizeof(JMP_REL));
                            }

                            if (ppOriginal != NULL)
                                *ppOriginal = pHook->pTrampoline;
                        }
                        else
                        {
                            status = MH_ERROR_MEMORY_ALLOC;
                        }
                    }
                    else
                    {
                        status = MH_ERROR_UNSUPPORTED_FUNCTION;
                    }

                    if (status != MH_OK)
                    {
                        FreeBuffer(pBuffer);
                    }
                }
                else
                {
                    status = MH_ERROR_MEMORY_ALLOC;
                }
            }
            else
            {
                status = MH_ERROR_ALREADY_CREATED;
            }
        }
        else
        {
            status = MH_ERROR_NOT_EXECUTABLE;
        }
    }
    else
    {
        status = MH_ERROR_NOT_INITIALIZED;
    }

    LeaveSpinLock();

    return status;
}
Beispiel #3
0
PHOOK_ENTRY MinHookEnable(LPVOID pTarget, LPVOID pDetour, HANDLE *hHeap)
{
	LPVOID      pBuffer;
	TRAMPOLINE  ct;
	PHOOK_ENTRY pHook;
	DWORD  oldProtect;
	SIZE_T patchSize = sizeof(JMP_REL);
	LPBYTE pPatchTarget;
	PJMP_REL pJmp;

	pBuffer = AllocateBuffer(pTarget);
	if (pBuffer == NULL)
		return NULL;

	ct.pTarget = pTarget;
	ct.pDetour = pDetour;
	ct.pTrampoline = pBuffer;
	if (!CreateTrampolineFunction(&ct))
	{
		FreeBuffer(pBuffer);
		return NULL;
	}
	*hHeap = HeapCreate(0, 0, 0);
	if (*hHeap == NULL)
		return NULL;
	pHook = (PHOOK_ENTRY)HeapAlloc(*hHeap, 0, sizeof(HOOK_ENTRY));
	if (pHook == NULL)
	{
		FreeBuffer(pBuffer);
		return NULL;
	}

	pHook->pTarget = ct.pTarget;
#ifdef _M_X64
	pHook->pDetour = ct.pRelay;
#else
	pHook->pDetour = ct.pDetour;
#endif
	pHook->pTrampoline = ct.pTrampoline;
	pHook->patchAbove = ct.patchAbove;
	pHook->isEnabled = FALSE;
	pHook->queueEnable = FALSE;
	pHook->nIP = ct.nIP;
	memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs));
	memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs));

	// Back up the target function.
	if (ct.patchAbove)
	{
		memcpy(
			pHook->backup,
			(LPBYTE)pTarget - sizeof(JMP_REL),
			sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
	}
	else
	{
		memcpy(pHook->backup, (LPVOID)pTarget, sizeof(JMP_REL));
	}

	// Enable Hook
	pPatchTarget = (LPBYTE)pHook->pTarget;

	if (pHook->patchAbove)
	{
		pPatchTarget -= sizeof(JMP_REL);
		patchSize += sizeof(JMP_REL_SHORT);
	}

	if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
		return NULL;

	pJmp = (PJMP_REL)pPatchTarget;
	pJmp->opcode = 0xE9;
	pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL)));
	if (pHook->patchAbove)
	{
		PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget;
		pShortJmp->opcode = 0xEB;
		pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL)));
	}

	VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);

	// Just-in-case measure.
	FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize);

	return pHook;
}