首页
社区
课程
招聘
[求助]windows核心编程中的 IAT Hook 是否存在线程问题??
发表于: 2009-3-10 02:32 6675

[求助]windows核心编程中的 IAT Hook 是否存在线程问题??

2009-3-10 02:32
6675
最近在研究API Hook, 看了一下Jeffery 大师的<<windows核心编程>> 有些疑问, 听说看雪高手如手, 小弟特来求助

问题 : <<核心>>中Hook IAT的时候, 为了防止Hook之后某线程又用LoadLibrary*载入新的dll, 而新的dll(或其依赖的其它dll)又调用了需要被Hook的函数. 他对LoadLibrary*也进行了Hook.

他的方法是每次LoadLibrary时, 对本线程的所有模块的IAT再Hook一次。
此处小弟有一疑问, 某两个线程同时LoadLibrary, 那两线程有可能同时对某一模块调用
ReplaceIATEntryInOneMod(
            pszCalleeModName, pfnCurrent, pfnNew, me.hModule);
而其中的WriteProcessMemorry, 则会导致两线程同时对某内存地址写数据, 不是会造成访问冲突???

部分代码如下:
HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath) {

   HMODULE hmod = ::LoadLibraryA(pszModulePath);
   FixupNewlyLoadedModule(hmod, 0);
   return(hmod);
}

void CAPIHook::FixupNewlyLoadedModule(HMODULE hmod, DWORD dwFlags) {

   // If a new module is loaded, hook the hooked functions
   if ((hmod != NULL) &&   // Do not hook our own module
       (hmod != ModuleFromAddress(FixupNewlyLoadedModule)) &&
       ((dwFlags & LOAD_LIBRARY_AS_DATAFILE) == 0) &&
       ((dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) == 0) &&
       ((dwFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) == 0)
       ) {

      for (CAPIHook* p = sm_pHead; p != NULL; p = p->m_pNext) {
         if (p->m_pfnOrig != NULL) {
            ReplaceIATEntryInAllMods(p->m_pszCalleeModName,
               p->m_pfnOrig, p->m_pfnHook);  
         } else {
//
         }
      }
   }
}

void CAPIHook::ReplaceIATEntryInAllMods(PCSTR pszCalleeModName,
   PROC pfnCurrent, PROC pfnNew) {

   HMODULE hmodThisMod = ExcludeAPIHookMod
      ? ModuleFromAddress(ReplaceIATEntryInAllMods) : NULL;

   // Get the list of modules in this process
   CToolhelp th(TH32CS_SNAPMODULE, GetCurrentProcessId());

   MODULEENTRY32 me = { sizeof(me) };
   for (BOOL bOk = th.ModuleFirst(&me); bOk; bOk = th.ModuleNext(&me)) {

      // NOTE: We don't hook functions in our own module
      if (me.hModule != hmodThisMod) {

         // Hook this function in this module
         ReplaceIATEntryInOneMod(
            pszCalleeModName, pfnCurrent, pfnNew, me.hModule);
      }
   }
}

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

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
貌似这个“同时”并不是时空意义上绝对的同时
2009-3-10 09:34
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
如果写两个线程, 同时写某个全局全量, 是会造成访问冲突的,
兄弟的意思是WriteProcessMemory自带了临界区还是什么呢?? 还望指点一下
2009-3-10 14:57
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4
写本进程用InterlockedExchange就可以,如果是写其它进程,貌似Attach时有锁机制的,就是说这种情况下那两个线程不可能真的“同时”写,当然你也可以自己在写之前用临界区来互斥。我只能说到这儿了,其实这个问题最好的解决方案是用InLine Hook
2009-3-10 16:35
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
5
不需要用writeprocessmemory的,先virutal protect,然后再lock xxx即可
2009-3-10 17:05
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
qihoocom 是个高手, 多谢指点, 有辛拜读你的<<另类挂钩-RING3数据包监视>>, :)
有点不理解你说的不需要writeprocessmemory是什么意思 ? IAT Hook 都是需要使用WriteProcessMemory的吧, 请看您的代码中
void SuperHookDeviceIoControl()
{
...
WriteProcessMemory(GetCurrentProcess() , lpAddr , &myaddr , sizeof(ULONG), &btw );
...
}

可能我的问题没说清楚, 我的意思是Jeffrey 这样的大师应该不会犯这种低级错误吧?? 还是我的理解有误, <<核心>>中的代码本来就没多线程问题??

很多IAT Hook的代码都是改自<<核心>>中的代码, 那不是都可能存在多线程问题??

我觉得他的代码有两点问题
1 : Hook LoadLibrary*后, 若两线程同时调用LoadLibrary, 可能同时修改同一个模块的IAT表, 可能存在访问冲突(此问题可以用临界区解决)
2 : Hook LoadLibrary*后, 他对本进程所有模块的的IAT表都进行修改(使用WriteProcessMemory), 某线程可能此时访问正在被修改中的IAT表, 可能call 到其它地址去。(若真存在多线程问题, 此问题就有点麻烦)

不知道我的理解是否有问题? 还是说由于使用VirtualProcect, WriteProcess, 不会存在这样的访问冲突??
2009-3-10 17:22
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
多谢这位仁兄回复, InLine Hook 在x86, x64, alpha系列cpu上需要使用不同的反汇编库(而且大多是病毒模块, 可能被杀毒软件误杀), 觉得还是IAT Hook 稳定一些 :) .

而且可能我的问题没说清楚, 我的意思是Jeffrey 这样的大师应该不会犯这种低级错误吧?? 还是我的理解有误, <<核心>>中的代码本来就没多线程问题??

很多IAT Hook的代码都是改自<<核心>>中的代码, 那不是都可能存在多线程问题??

我觉得他的代码有两点问题
1 : Hook LoadLibrary*后, 若两线程同时调用LoadLibrary, 可能同时修改同一个模块的IAT表, 可能存在访问冲突 (此问题可以用临界区解决)
2 : Hook LoadLibrary*后, 他对本进程所有模块的的IAT表都进行修改(使用WriteProcessMemory), 某线程可能此时访问正在被修改中的IAT表, 可能call 到其它地址去。(若真有多线程问题, 此问题就有点麻烦)

不知道我的理解是否有问题? 还是说由于使用VirtualProcect, WriteProcess, 不会存在这样的访问冲突??
2009-3-10 17:31
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
8
WriteProcessMemory的ProcessHandle参数为当前进程时其实只相当于一个memcpy,所以说写本进程完全可以不用它(当然用了也没错),只需要你用VirtualProtect使得目标地址可写然后就可以改了。另外,如果要写的数据长度不超过机器字长,是可以用一条指令安全地实现修改而不会出现访问冲突,指针的长度和机器字长是一样的
2009-3-10 17:36
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
9
对本进程的用writeprocessmemory和virtual protect+直接写都可以
如果你想做到线程安全,不妨 virtual protect后用锁定总线再写入
另外32位机器上改写对齐的4字节IAT,是不会有多线程切换的问题的
2009-3-10 18:35
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
原来如此, 多谢各位指点 :)
2009-3-10 18:40
0
游客
登录 | 注册 方可回帖
返回
//