|
|
Comments and Discussions
|
|
 |

|
https://github.com/RaMMicHaeL/minhook[^]
Main differences from original v1.1
- Removed boost dependency (jarredholman).
- Fixed a small bug in the GetRelativeBranchDestination function (pillbug99).
- Added the
MH_RemoveHook function, which removes a hook created with the MH_CreateHook function.
- Added the following functions to enable or disable multiple hooks in one go:
MH_EnableAllHooks, MH_DisableAllHooks, MH_EnableMultipleHooks, MH_DisableMultipleHooks. This is the preferred way of handling multiple hooks as every call to MH_EnableHook or MH_DisableHook suspends and resumes all threads.
- If the target function is too small to be patched with a jump, MinHook tries to place the jump above the function. If that fails as well, the
MH_CreateHook function returns MH_ERROR_UNSUPPORTED_FUNCTION. This fixes an issue of hooking the LoadLibraryExW function on Windows 7 x64 (reported by Obble).
modified 5-Jun-13 15:32pm.
|
|
|
|

|
I think it's a pretty good idea to create a fork and open it to the public on GitHub.
I appreciate very much that someone takes over my work.
|
|
|
|

|
I wasn't sure I'd hear from you, after all the library wasn't updated for more than three years.
Good to know you're approving it.
I'm not a C++ programmer, so I hope I'm getting things right.
P.S. Thanks for the library. It's probably the best hooking library around.
|
|
|
|

|
I reviewed the code after a long time, and I have recalled that I wrote the comments in Japanese.
I think it's somewhat inappropriate for the open project, so want to rewrite them in English. Are you ready to accept a pull request?
|
|
|
|

|
Sure, that would be great.
In fact, I thought about using Google Translate to automatically translate the comments, but of course a proper translation is much better.
|
|
|
|

|
Thanks.
At that time, I was not very skilled with C++, so the code is not sophisticated as a C++ program.
I want to give an overall review, but I'm a little busy now. But I will do it sooner or later.
|
|
|
|

|
Updated
- Made the
MH_CreateHook function return MH_ERROR_UNSUPPORTED_FUNCTION when the target function is too small and is not padded with zero bytes, nops, or INT3 commands.
- If the target function begins with a short jump, MinHook considers the jump destination as the target (Obble). This fixes an issue on Windows 7 x64 with the patched jump overwriting code of a different function.
|
|
|
|

|
Updated
- Added:
If the target function is too small to be patched with a jump, MinHook tries to place the jump above the function.
- Reverted:
If the target function begins with a short jump, MinHook considers the jump destination as the target.
See this post[^] for more details.
|
|
|
|

|
Hi,
Thanks for your great work!
I just found a project setting missed so that when using
VS 2012 to compile Debug x64 version, MinHook will never be generated.
|
|
|
|
|

|
Hello, does your library work for hooking vtables (i.e. hooking function of specific object?).
I know I can change the address of the function directly in vtable but the process where I inject to periodically restores vtable to original state. Therefor I would rather inject some JMP instruction into the original function. And I need a simple solution for x64. Thanks in advance.
|
|
|
|

|
Seen from a technical point of view (after looking at the MinHook code myself) there should be no issue with hooking a V-Table function.
To do so you need to...
1. Read the V-Table yourself and figure out which offset / function in it is interesting to you...
2. Get the function address from that V-Table offset and place a hook on it like you would do normally with MinHook.
3. In your replacement function add a new leading argument corresponding to the type of the class you are hooking into.
So if you were hooking into lets say...
DummyClass::YourDummyMethod(int a, int b, int c)
... then your replacement hook function would have to be...
MyDummyMethodReplacement(DummyClass * objectReference, int a, int b, int c)
Thats all there is to it. Happy Hooking.
|
|
|
|

|
Thanks. I already managed to do it for x64. Problem is that it does not work in 32-bit for functions declared with __thiscall convention. The function hooks properly but the problem is that in many cases I need to call the original function. And this simply crashes because "objectReference" reference must be passed in ecx. Is it possible to store it in ecx without using inline assembler?
|
|
|
|

|
If __thiscall doesn't work, you can try using __fastcall as a workaround. Just add an extra variable for edx.
e.g.:
void __fastcall func(void *this, size_t _edx_var, int a, int whatever)
{
}
|
|
|
|

|
If I copy and paste the code into a DLL (DLL_PROCESS_ATTACH) I get lots of compile errors (unresolved external symbol).
The code wokred in a console application. But that's pretty useless. I want to inject the DLL.
|
|
|
|

|
Probably because you arent linking boost into it correctly.
But dont worry, in one of the comments here you find a patch to fully remove Boost Dependencies.
That plus some manual patches and you should be ready to go.
|
|
|
|
|

|
I've put together a small patch that removes libMinHook's dependency on boost as I found it quite annoying to have to install it and keep libMinHook pointing at it; especially with VS2010's idea about where to configure third party library directories. The patch also includes a fix for pillbug99's short jump bug (http://www.codeproject.com/Messages/4058892/Small-Bug-Found.aspx[^]).
libMinHook is an excellent little library that does just enough and no more .
diff -urw MinHook_110_src.original/MinHook/libMinHook/src/buffer.cpp MinHook_110_src/MinHook/libMinHook/src/buffer.cpp
--- MinHook_110_src.original/MinHook/libMinHook/src/buffer.cpp 2009-11-25 06:42:50.000000000 +0000
+++ MinHook_110_src/MinHook/libMinHook/src/buffer.cpp 2012-04-19 11:26:47.960409100 +0100
@@ -29,7 +29,6 @@
#include <cassert>
#include <vector>
#include <algorithm>
-#include <boost/foreach.hpp>
#include <Windows.h>
#include "buffer.h"
@@ -77,9 +76,10 @@
void UninitializeBuffer()
{
- BOOST_FOREACH (MEMORY_BLOCK& block, gMemoryBlocks)
+ for (std::vector<MEMORY_BLOCK>::iterator block = gMemoryBlocks.begin();
+ block != gMemoryBlocks.end(); block++)
{
- VirtualFree(block.pAddress, 0, MEM_RELEASE);
+ VirtualFree(block->pAddress, 0, MEM_RELEASE);
}
std::vector<MEMORY_BLOCK> v;
@@ -102,25 +102,27 @@
void RollbackBuffer()
{
- BOOST_FOREACH (MEMORY_BLOCK& block, gMemoryBlocks)
+ for (std::vector<MEMORY_BLOCK>::iterator block = gMemoryBlocks.begin();
+ block != gMemoryBlocks.end(); block++)
{
- block.usedSize = block.fixedSize;
+ block->usedSize = block->fixedSize;
}
}
void CommitBuffer()
{
- BOOST_FOREACH (MEMORY_BLOCK& block, gMemoryBlocks)
+ for (std::vector<MEMORY_BLOCK>::iterator block = gMemoryBlocks.begin();
+ block != gMemoryBlocks.end(); block++)
{
- if (block.usedSize == block.fixedSize)
+ if (block->usedSize == block->fixedSize)
{
continue;
}
- void* pBuffer = reinterpret_cast<char*>(block.pAddress) + block.fixedSize;
- size_t size = block.usedSize - block.fixedSize;
+ void* pBuffer = reinterpret_cast<char*>(block->pAddress) + block->fixedSize;
+ size_t size = block->usedSize - block->fixedSize;
DWORD op;
- VirtualProtect(pBuffer, size, block.protect, &op);
+ VirtualProtect(pBuffer, size, block->protect, &op);
}
}
}
diff -urw MinHook_110_src.original/MinHook/libMinHook/src/hook.cpp MinHook_110_src/MinHook/libMinHook/src/hook.cpp
--- MinHook_110_src.original/MinHook/libMinHook/src/hook.cpp 2009-11-25 06:47:02.000000000 +0000
+++ MinHook_110_src/MinHook/libMinHook/src/hook.cpp 2012-04-19 11:26:47.963409300 +0100
@@ -30,8 +30,6 @@
#include <vector>
#include <algorithm>
#include <functional>
-#include <boost/scope_exit.hpp>
-#include <boost/foreach.hpp>
#include <Windows.h>
#include "pstdint.h"
@@ -116,14 +114,15 @@
}
- BOOST_FOREACH (const HOOK_ENTRY& hook, gHooks)
+ for (std::vector<HOOK_ENTRY>::const_iterator hook = gHooks.begin();
+ hook != gHooks.end(); hook++)
{
- if (!hook.isEnabled)
+ if (!hook->isEnabled)
{
continue;
}
- MH_STATUS status = DisableHook(hook.pTarget);
+ MH_STATUS status = DisableHook(hook->pTarget);
if (status != MH_OK)
{
return status;
@@ -162,33 +161,26 @@
if (pHook == NULL)
{
- bool committed = false;
- BOOST_SCOPE_EXIT((&committed))
- {
- if (!committed)
- {
- RollbackBuffer();
- }
- }
- BOOST_SCOPE_EXIT_END;
-
CREATE_TREMPOLINE_T ct = { 0 };
ct.pTarget = pTarget;
if (!CreateTrampolineFunction(ct))
{
+ RollbackBuffer();
return MH_ERROR_UNSUPPORTED_FUNCTION;
}
void* pTrampoline = AllocateCodeBuffer(pTarget, ct.trampoline.size());
if (pTrampoline == NULL)
{
+ RollbackBuffer();
return MH_ERROR_MEMORY_ALLOC;
}
#if defined _M_X64
void* pTable = AllocateDataBuffer(pTrampoline, (ct.table.size() + 1) * sizeof(uintptr_t));
if (pTable == NULL)
{
+ RollbackBuffer();
return MH_ERROR_MEMORY_ALLOC;
}
#endif
@@ -199,6 +191,7 @@
#endif
if (!ResolveTemporaryAddresses(ct))
{
+ RollbackBuffer();
return MH_ERROR_UNSUPPORTED_FUNCTION;
}
@@ -214,6 +207,7 @@
void* pBackup = AllocateDataBuffer(NULL, sizeof(JMP_REL));
if (pBackup == NULL)
{
+ RollbackBuffer();
return MH_ERROR_MEMORY_ALLOC;
}
@@ -224,13 +218,13 @@
void* pRelay = AllocateCodeBuffer(pTarget, sizeof(JMP_ABS));
if (pRelay == NULL)
{
+ RollbackBuffer();
return MH_ERROR_MEMORY_ALLOC;
}
WriteAbsoluteJump(pRelay, pDetour, reinterpret_cast<uintptr_t*>(pTable) + ct.table.size());
#endif
CommitBuffer();
- committed = true;
HOOK_ENTRY hook = { 0 };
diff -urw MinHook_110_src.original/MinHook/libMinHook/src/thread.cpp MinHook_110_src/MinHook/libMinHook/src/thread.cpp
--- MinHook_110_src.original/MinHook/libMinHook/src/thread.cpp 2009-11-21 00:29:02.000000000 +0000
+++ MinHook_110_src/MinHook/libMinHook/src/thread.cpp 2012-04-19 11:26:47.965409400 +0100
@@ -29,7 +29,6 @@
#include <cassert>
#include <vector>
#include <algorithm>
-#include <boost/foreach.hpp>
#include <windows.h>
#include <TlHelp32.h>
@@ -38,7 +37,7 @@
namespace MinHook { namespace
{
- class ScopedHandle : boost::noncopyable
+ class ScopedHandle
{
private:
HANDLE handle_;
@@ -57,6 +56,9 @@
{
return handle_;
}
+ private:
+ ScopedHandle(const ScopedHandle&);
+ const ScopedHandle& operator=(const ScopedHandle&);
};
}}
@@ -143,9 +145,10 @@
static const DWORD ThreadAccess
= THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT;
- BOOST_FOREACH (const DWORD& tid, threads)
+ for (std::vector<DWORD>::const_iterator tid = threads.begin();
+ tid != threads.end(); tid++)
{
- ScopedHandle hThread = OpenThread(ThreadAccess, FALSE, tid);
+ ScopedHandle hThread = OpenThread(ThreadAccess, FALSE, *tid);
SuspendThread(hThread);
@@ -176,9 +179,10 @@
void ScopedThreadExclusive::Unfreeze(const std::vector<DWORD>& threads)
{
- BOOST_FOREACH (const DWORD& tid, threads)
+ for (std::vector<DWORD>::const_iterator tid = threads.begin();
+ tid != threads.end(); tid++)
{
- ScopedHandle hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, tid);
+ ScopedHandle hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, *tid);
ResumeThread(hThread);
}
}
diff -urw MinHook_110_src.original/MinHook/libMinHook/src/thread.h MinHook_110_src/MinHook/libMinHook/src/thread.h
--- MinHook_110_src.original/MinHook/libMinHook/src/thread.h 2009-11-17 22:48:38.000000000 +0000
+++ MinHook_110_src/MinHook/libMinHook/src/thread.h 2012-04-19 11:26:47.967409500 +0100
@@ -29,7 +29,6 @@
#pragma once
#include <vector>
-#include <boost/utility.hpp>
#include <windows.h>
#include "trampoline.h"
@@ -37,16 +36,19 @@
namespace MinHook
{
- class CriticalSection : boost::noncopyable
+ class CriticalSection
{
public:
- class ScopedLock : boost::noncopyable
+ class ScopedLock
{
private:
CriticalSection& cs_;
public:
ScopedLock(CriticalSection& cs);
~ScopedLock();
+ private:
+ ScopedLock(const ScopedLock&);
+ const ScopedLock& operator=(const ScopedLock&);
};
private:
@@ -56,6 +58,9 @@
~CriticalSection();
void enter();
void leave();
+ private:
+ CriticalSection(const CriticalSection&);
+ const CriticalSection& operator=(const CriticalSection&);
};
diff -urw MinHook_110_src.original/MinHook/libMinHook/src/trampoline.cpp MinHook_110_src/MinHook/libMinHook/src/trampoline.cpp
--- MinHook_110_src.original/MinHook/libMinHook/src/trampoline.cpp 2009-11-25 06:40:56.000000000 +0000
+++ MinHook_110_src/MinHook/libMinHook/src/trampoline.cpp 2012-04-19 11:26:47.971409700 +0100
@@ -28,7 +28,6 @@
#include <cassert>
#include <vector>
-#include <boost/foreach.hpp>
#include "pstdint.h"
#if defined _M_X64
@@ -229,9 +228,10 @@
#if defined _M_X64
uintptr_t* pt = reinterpret_cast<uintptr_t*>(ct.pTable);
#endif
- BOOST_FOREACH (const TEMP_ADDR& ta, ct.tempAddr)
+ for (std::vector<TEMP_ADDR>::iterator ta = ct.tempAddr.begin();
+ ta != ct.tempAddr.end(); ta++)
{
- if (ta.position > ct.trampoline.size() - sizeof(uint32_t))
+ if (ta->position > ct.trampoline.size() - sizeof(uint32_t))
{
return false;
}
@@ -245,11 +245,11 @@
else
#endif
{
- addr = ta.address;
+ addr = ta->address;
}
- *reinterpret_cast<uint32_t*>(&ct.trampoline[ ta.position ])
- = static_cast<uint32_t>(addr - (reinterpret_cast<uintptr_t>(ct.pTrampoline) + ta.pc));
+ *reinterpret_cast<uint32_t*>(&ct.trampoline[ ta->position ])
+ = static_cast<uint32_t>(addr - (reinterpret_cast<uintptr_t>(ct.pTrampoline) + ta->pc));
}
for (size_t i = 0; i < ct.oldIPs.size(); ++i)
@@ -266,7 +266,20 @@
{
inline uintptr_t GetRelativeBranchDestination(uint8_t* pInst, const hde_t& hs)
{
- return reinterpret_cast<uintptr_t>(pInst) + hs.len + static_cast<int32_t>(hs.imm.imm32);
+ int32_t imm;
+
+ if (hs.opcode == 0xEB || + (hs.opcode & 0xF0) == 0x70 || + hs.opcode == 0xE3) + {
+ imm = (int32_t)(int8_t)hs.imm.imm8;
+ }
+ else
+ {
+ imm = (int32_t)hs.imm.imm32;
+ }
+
+ return (uintptr_t)pInst + hs.len + imm;
}
inline bool IsInternalJump(void* pTarget, uintptr_t dest)
|
|
|
|

|
one little miss on x64 build line 241,
need to change: "if (ta.address < 0x10000)" to "if (ta->address < 0x10000)"
|
|
|
|

|
I get a crash ( access violation ) every time hooking CreateFileA, CreateFileW etc. on Windows7 x64 First-chance exception at 0x61cbf10f (msvcr100d.dll) in test_ntfs_parser.exe: 0xC0000005: Access violation reading location 0x0000000000000014. having trashed the stack.
|
|
|
|

|
Hi,
Thank you for having a look at this post.
I am facing a problem when I hook LoadLibraryExW function in windows 2008 r2 SP1. A crash occurs when this function is called.
But ANSI version (LoadLibraryExA) works fine.
Both versions of LoadLibraryEx work fine on windows 2008.
Note: I modified your sample code to hook LoadLibraryExW function (I am loading dynamically notepad.exe) process.
Thanks,
Gulshan
|
|
|
|

|
Can't hook LoadLibraryExW also on win7 x64 ... any help ?
the rest works fine ...
Thanks!
|
|
|
|

|
Couldn't reproduce it on Windows 7 x64.
Source code:
http://pastebin.com/9Vij4mAh[^]
It should show a message box if the hook succeeded.
Works as expected on my machine.
|
|
|
|

|
Sorry, found out a coding issue on my side, hooking loadlibraryExW under x64 Win7 works perfect
Thanks
|
|
|
|

|
I am getting the same issue. Although the DetourFunc will be call, any attempt to call the function pointer to the original function "pFoo" (probably casted) will crash. Basically call pFoo in DetourFunc() in Win7 x64 and it will crash, but not ExA or in 86bit mode. Also, any attempt to call the original LoadLibaryExW, when hooked but not enabled, will report invalid instructions.
-- modified 31-May-13 12:13pm.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Provides the basic part of Microsoft Detours functionality for both x64/x86 environments.
| Type | Article |
| Licence | BSD |
| First Posted | 22 Nov 2009 |
| Views | 74,923 |
| Downloads | 6,144 |
| Bookmarked | 131 times |
|
|