Skip to content

Commit

Permalink
[DOCS][TECHWIKI] Mention "MinHook"
Browse files Browse the repository at this point in the history
  • Loading branch information
RatinCN committed Jul 26, 2024
1 parent ec4f597 commit 8267d87
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,19 @@ Worker Thread Demo.exe!SetHookThread Demo.exe!__acrt_lock
```
Use [SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours) run this demo `"Demo.exe -Run DeadLock -Engine=SlimDetours"` will pass successfully.

## How did mhook and SlimDetours avoid this problem?
## How did other hooking libraries avoid this problem?

[mhook](https://github.com/martona/mhook) is a well-known Windows API hooking library like [Detours](https://github.com/microsoft/Detours), it uses [`Virtual­Alloc`](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc) to allocate memory pages instead of [`Heap­Alloc`](https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc) to allocate heap memory, which is a solution mentioned at the end of the above article.
[mhook](https://github.com/martona/mhook) uses [`Virtual­Alloc`](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc) to allocate memory pages instead of [`Heap­Alloc`](https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc) to allocate heap memory, which is a solution mentioned at the end of the above article.

[SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours) created a new private heap for internal use, which avoids this problem and saves memory usage:
Both of [MinHook](https://github.com/TsudaKageyu/minhook) and [SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours) created a new private heap for internal use, which avoids this problem and saves memory usage:
```C
_detour_memory_heap = RtlCreateHeap(HEAP_NO_SERIALIZE | HEAP_GROWABLE, NULL, 0, 0, NULL, NULL);
```
> [!NOTE]
> [Detours](https://github.com/microsoft/Detours) already has a transaction mechanism, and [SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours)' new feature "[Delay Hook](../Implement%20Delay%20Hook/README.md)" also uses SRW locks, so this heap does not need serialized access.
[MinHook](https://github.com/TsudaKageyu/minhook) creates in its initialization function `MH_Initialize`, and [SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours) creates in one-time initialization in the first called memory allocation function, so there is no and no need for a separate initialization function.

<br>
<hr>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,19 @@ Worker Thread Demo.exe!SetHookThread Demo.exe!__acrt_lock
```
使用[SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours)运行此示例`"Demo.exe -Run DeadLock -Engine=SlimDetours"`则能顺利通过。

## mhook与SlimDetours如何避免这个问题
## 其它挂钩库如何避免这个问题

[mhook](https://github.com/martona/mhook)[Detours](https://github.com/microsoft/Detours)一样也是一个熟知的Windows API挂钩库,它使用[`Virtual­Alloc`](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc)分配内存页代替[`Heap­Alloc`](https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc)分配堆内存,是上文末尾提到的一个解决方案。
[mhook](https://github.com/martona/mhook)使用[`Virtual­Alloc`](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc)分配内存页代替[`Heap­Alloc`](https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc)分配堆内存,是上文末尾提到的一个解决方案。

[SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours)新创建了一个私有堆供内部使用,避免此问题的同时也节约了内存使用:
[MinHook](https://github.com/TsudaKageyu/minhook)[SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours)都新创建了一个私有堆供内部使用,避免此问题的同时也节约了内存使用:
```C
_detour_memory_heap = RtlCreateHeap(HEAP_NO_SERIALIZE | HEAP_GROWABLE, NULL, 0, 0, NULL, NULL);
```
> [!NOTE]
> [Detours](https://github.com/microsoft/Detours)已有事务机制,[SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours)新添功能“[延迟挂钩](../Implement%20Delay%20Hook/README.zh-CN.md)”也用了[SRW锁](https://learn.microsoft.com/en-us/windows/win32/sync/slim-reader-writer--srw--locks),所以此堆无需序列化访问。
[MinHook](https://github.com/TsudaKageyu/minhook)在其初始化函数`MH_Initialize`中创建,而[SlimDetours](https://github.com/KNSoft/KNSoft.SlimDetours)在首个被调用的内存分配函数中进行一次初始化时创建,故没有也不需要单独的初始化函数。

<br>
<hr>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static PVOID s_pSystemRegionUpperBound = (PVOID)(ULONG_PTR)0x80000000;
```
[jdu2600](https://github.com/jdu2600) is also aware of this issue and has opened an unofficial PR [microsoft/Detours PR #307](https://github.com/microsoft/Detours/pull/307) for [Detours](https://github.com/microsoft/Detours) wants to update this range to adapt the latest Windows.

[mhook](https://github.com/martona/mhook) is a well-known Windows API hooking library like [Detours](https://github.com/microsoft/Detours), it's a pity that it doesn't seem to take this issue into account.
[MinHook](https://github.com/TsudaKageyu/minhook) and [mhook](https://github.com/martona/mhook) are both well-known Windows API hooking libraries, but unfortunately they don't seem to take this issue into account.

## SlimDetours implementation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static PVOID s_pSystemRegionUpperBound = (PVOID)(ULONG_PTR)0x80000000;
```
同样注意到此问题的[jdu2600](https://github.com/jdu2600)[Detours](https://github.com/microsoft/Detours)开了一个非官方的PR [microsoft/Detours PR #307](https://github.com/microsoft/Detours/pull/307) 想更新这个范围以适配最新的Windows。

[mhook](https://github.com/martona/mhook)[Detours](https://github.com/microsoft/Detours)一样也是一个熟知的Windows API挂钩库,遗憾的是它似乎没有考虑到这个问题
[MinHook](https://github.com/TsudaKageyu/minhook)[mhook](https://github.com/martona/mhook)都是熟知的Windows API挂钩库,遗憾的是它们似乎都没有考虑到这个问题

## SlimDetours的实现

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ But [Detours](https://github.com/microsoft/Detours) updates threads very precise
> [!TIP]
> While its official example "[Using Detours](https://github.com/microsoft/Detours/wiki/Using-Detours)" has code like `DetourUpdateThread(GetCurrentThread())`, such usage is pointless and invalid, and should be used to update all threads in the process except the current thread, see also: [`DetourUpdateThread`](https://github.com/microsoft/Detours/wiki/DetourUpdateThread). But even updating threads in the right way, it also brings a new risk, see [🔗 TechWiki: Avoid Deadlocking on The Heap When Updating Threads](https://github.com/KNSoft/KNSoft.SlimDetours/blob/main/Docs/TechWiki/Avoid%20Deadlocking%20on%20The%20Heap%20When%20Updating%20Threads/README.md).
### MinHook
[MinHook](https://github.com/TsudaKageyu/minhook) does a better job, it updates threads automatically when set (or unset) hooks, and adjusts PC (Program Counter) in the thread context as accurately as [Detours](https://github.com/microsoft/Detours).
### mhook
[mhook](https://github.com/martona/mhook) is a well-known Windows API hooking library like [Detours](https://github.com/microsoft/Detours), it updates threads automatically when set (or unset) hooks, the caller doesn't need to be concerned about this problem, see [mhook/mhook-lib/mhook.cpp at e58a58ca · martona/mhook](https://github.com/martona/mhook/blob/e58a58ca31dbe14f202b9b26315bff9f7a32598c/mhook-lib/mhook.cpp#L557) for implementation.
[mhook](https://github.com/martona/mhook) updates threads automatically when set (or unset) hooks, the caller doesn't need to be concerned about this problem, see [mhook/mhook-lib/mhook.cpp at e58a58ca · martona/mhook](https://github.com/martona/mhook/blob/e58a58ca31dbe14f202b9b26315bff9f7a32598c/mhook-lib/mhook.cpp#L557) for implementation.
But the way it updates threads is a bit hacky compared to the [Detours](https://github.com/microsoft/Detours) mentioned above, wait 100ms if the thread is exactly in the area where the instruction is about to be modified, try up to 3 times:
But the way it updates threads is a bit hacky compared to the others mentioned above, wait 100ms if the thread is exactly in the area where the instruction is about to be modified, try up to 3 times:
```C
while (GetThreadContext(hThread, &ctx))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread);
> [!TIP]
> 虽然它的官方示例“[Using Detours](https://github.com/microsoft/Detours/wiki/Using-Detours)”中有`DetourUpdateThread(GetCurrentThread())`这样的代码,但这用法无意义且无效,应使用其更新进程中除当前线程外的所有线程,详见[`DetourUpdateThread`](https://github.com/microsoft/Detours/wiki/DetourUpdateThread)。但即便以正确的方式更新线程,也会带来一个新的风险,见[🔗 技术Wiki:更新线程时避免堆死锁](https://github.com/KNSoft/KNSoft.SlimDetours/blob/main/Docs/TechWiki/Avoid%20Deadlocking%20on%20The%20Heap%20When%20Updating%20Threads/README.zh-CN.md)。
### MinHook
[MinHook](https://github.com/TsudaKageyu/minhook)做的比较好,它在挂钩(和脱钩)时自动更新线程,并且像[Detours](https://github.com/microsoft/Detours)一样准确地更新线程上下文中的PC(程序计数器)。
### mhook
[mhook](https://github.com/martona/mhook)与[Detours](https://github.com/microsoft/Detours)一样也是一个熟知的Windows API挂钩库,它在挂钩(和脱钩)时自动更新线程,调用者无需关心此问题,实现参考[mhook/mhook-lib/mhook.cpp于e58a58ca · martona/mhook](https://github.com/martona/mhook/blob/e58a58ca31dbe14f202b9b26315bff9f7a32598c/mhook-lib/mhook.cpp#L557)。
[mhook](https://github.com/martona/mhook)在挂钩(和脱钩)时自动更新线程,实现参考[mhook/mhook-lib/mhook.cpp于e58a58ca · martona/mhook](https://github.com/martona/mhook/blob/e58a58ca31dbe14f202b9b26315bff9f7a32598c/mhook-lib/mhook.cpp#L557)。
但它更新线程的方式比起上述的[Detours](https://github.com/microsoft/Detours)则有点笨拙,若线程正好位于要修改指令的区域则等待100毫秒,最多尝试3次:
但它更新线程的方式比起上述几个则有点笨拙,若线程正好位于要修改指令的区域则等待100毫秒,最多尝试3次:
```C
while (GetThreadContext(hThread, &ctx))
{
Expand Down

0 comments on commit 8267d87

Please sign in to comment.