首页
社区
课程
招聘
未解决 [求助]关于Hook高频函数
发表于: 2024-4-21 02:24 2018

未解决 [求助]关于Hook高频函数

2024-4-21 02:24
2018

我在Hook一个调用频率极高的函数发生崩溃,于是看了MinHook的解决方案,用的是自旋锁,MH关键代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
static VOID EnterSpinLock(VOID)
{
    SIZE_T spinCount = 0;
    while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE)
    {
        if (spinCount < 32)
            Sleep(0);
        else
            Sleep(1);
        spinCount++;
    }
}
 
static VOID LeaveSpinLock(VOID)
{
    InterlockedExchange(&g_isLocked, FALSE);
}
 
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal)
{
    EnterSpinLock();
    // ... Hook过程
 
    LeaveSpinLock();
 
    // ...
}

于是我照搬自旋锁代码加到我的hook函数前后,问题解决。

我对于Hook多线程问题的理解如下:
在Hook多条指令时,如果环境是多核,有可能有部分指令还没有修改完成,此时有另一条线程来执行不完整或错误的指令,程序崩溃
我的疑惑在于:自旋锁仅仅保护用于Hook的函数同时仅被一个线程执行,但是这与被hook的位置无关,依然有可能发生指令修改了一半被其他线程执行的可能,所以我感觉这个自旋锁没有意义。当然肯定是我理解有问题,还请大家不吝赐教
还有一个疑惑,如果是单核环境,有没有一种可能,指令修改到一半时,线程切换,恰巧切换到另一条线程执行被hook位置,发生崩溃?


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 2149
活跃值: (5178)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
hook的时候应该是关中断的,不存在线程切换
2024-4-21 10:03
0
雪    币: 57
活跃值: (2433)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
申请一个新地址然后模拟函数的头部字节 在JUMP到要hook的函数下面的正常段 形成一个新接口  调用的时候就调用这个新接口  这样就不需要还原函数头部的hook字节  自然就不会造成崩溃
2024-4-21 14:02
0
雪    币: 1129
活跃值: (2761)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
Lock指令会锁总线,独占访问的
2024-4-21 15:37
0
雪    币: 237
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5

实际上在inlinehook,多线程冲突不是单单一个自旋锁能完成的,就像你说的“发生指令修改了一半被其他线程执行的可能”。这里的锁只是为了多线程调用MinHook,而不关乎hook时候的线程安全。


MinHook和Detours实际上都是做了线程安全的,是这样做的:

多线程下安全的 attach hook 步骤

1> 遍历当前进程的所有线程,暂停当前线程以外的所有线程。
(遍历所有线程可以用TH32CS_SNAPTHREAD,暂停线程函数为SuspendThread。)

2>执行attach hook流程。
(覆盖目标函数头jmp到detour函数。创建跳板函数。)

3>判断其他所有线程的执行的代码ip地址,如果正在执行目标函数,且恰好正在执行起始几个覆盖的汇编,则将此线程的ip地址重新设置到trampoline跳板函数对应的地址。
(获取线程ip地址的函数为GetThreadContext,32eip 64rip,重新设置为SetThreadContext)

4>恢复其他所有线程。
(ResumeThread)


MinHook源代码,在EnableHook里都会先执行 Freeze函数,这个 Freeze就是停止其它线程的,并且在ProcessThreadIPs函数里重设某些ip到对应的Trampoline段,在hook完成后会Unfreeze恢复线程。


minhook/src/hook.c at master · TsudaKageyu/minhook (github.com)

static MH_STATUS Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action)
{
...
                SuspendThread(hThread);
                ProcessThreadIPs(hThread, pos, action);//当某些线程的ip正执行要hook的函数头上,重设ip位置到跳板函数
                CloseHandle(hThread);
...

}

参考博文:inline hook 原理 教程 - 0xc - 博客园 (cnblogs.com) 的 线程安全段落


最后于 2024-4-21 17:21 被mb_hgrbqfun编辑 ,原因:
2024-4-21 17:01
2
游客
登录 | 注册 方可回帖
返回
//