阅读:4424回复:11
API Hook如何hook到com组件?
我做了个api钩子,想截获dsound.dll(就是DirectSound)中有关音频操作的函数,我发现DirectSound是用com组件的方式实现的,我没办法了,不知道该怎么才能截获对接口中的函数的调用。
|
|
最新喜欢:![]()
|
沙发#
发布于:2002-06-17 22:05
It seems it does can be implemented.
我心中已经有数,你的结果价值千金,我开个贴子,你来领分,不成敬意。 |
|
板凳#
发布于:2002-06-17 11:34
虚函数表的地址和内容是不固定的
在创建类的生成的.. 下面我是写的一小段代码 HRESULT HookInterFace(int nCom, LPVOID pTableAddress, DWORD pFunction, int nFuncNum) { int nRetCode = 0; DWORD dwOldProct = 0; HRESULT hrRetCode = E_FAIL; LPDWORD pTempAddress = NULL; LPKAVComData pTempComData = NULL; if (nCom == defJScript) pTempComData = &g_JSKAVComData; if (nCom == defVBScript) pTempComData = &g_VBKAVComData; pTempAddress = (LPDWORD)*(LPDWORD)pTableAddress; pTempAddress = (LPDWORD)*pTempAddress; pTempAddress += nFuncNum; nRetCode = memcmp(&pFunction, pTempAddress, sizeof(DWORD)); if (nRetCode == 0) { hrRetCode = S_OK; goto Exit0; } switch (nFuncNum) { case 0: pTempComData->pQueryInterface = (API_QueryInterface)*pTempAddress; break; case 4: pTempComData->pAddScriptlet = (API_AddScriptlet)*pTempAddress; break; case 5: pTempComData->pParseScriptText = (API_ParseScriptText)*pTempAddress; break; } nRetCode = VirtualProtect(pTempAddress, sizeof(LPDWORD), PAGE_READWRITE, &dwOldProct); if (nRetCode == 0) goto Exit0; *pTempAddress = pFunction; VirtualProtect(pTempAddress, sizeof(LPDWORD), dwOldProct, NULL); hrRetCode = S_OK; Exit0: return hrRetCode; } |
|
|
地板#
发布于:2002-06-17 10:49
think more one time, I think what eqinzm said is also correct.
to inject winapi32, there is two method. 1.use detour to inject winapi32 run code, add something like jmp XXXXX (hookapi32 use this method) in 9x, because there is no copy on write, so it\'s global, inject one time, all ok. 2.modify importtable (process level) need modify every process because importtable is mapped seperately. (common inject tech) for COM. just as eqinzm said or i analysis .the vtable itself just LIKE an import table. maybe it make things easier. |
|
地下室#
发布于:2002-06-17 10:08
我们就是想知道到底原来的函数地址怎么得到?
|
|
|
5楼#
发布于:2002-06-17 09:59
hook com interface用不到detour和apispy32里面的技术
在修改函数表时把原来的函数地址保存下来就行了 |
|
|
6楼#
发布于:2002-06-17 09:12
zdhe,你好,没想到在这里又碰到你了,csdn的帖子也是我发的,我还在调试这个程序。以后可以在这里看到你了。 :D
|
|
|
7楼#
发布于:2002-06-16 00:37
I had not said what you say is wrong. I had use detour and modified apispy32 to use in my project.
for COM interface (main for directx), A member of my team had told me the same thing. I had thought about what you said but fill unsafe for this method. why: just like apispy32, it hook Certain Function (like read file ) , after do some thing special , it will call original func. so it is a monitor or a enhanced func, not a hacker. in real project, think about emulate a virtual direcoty in API level, when use directsound to play a file located in c:\\temp, we need redirect request to a server file. then , we need hook directx and in hooked com IF function, in hooked COM interface func, commonly need call original func.(no one want to implement a full directx player seperately) for this very common requeset, does we can call orginal COM IF func in hooked func? if you does had implemented something like this, We may think about cooperation. (include trade). |
|
8楼#
发布于:2002-06-15 12:11
我详细一点吧
1:当程序调用一个com时,windows会根据你给出的clsid在注册表 里面找到相应的com文件,如果我自己的clisid跟该com的clsid一样 那么当注册后,原来的会替换成我的com文件,所以程序调用一个com 时,windows就会去加载我的com文件 2:我这个方法只对没有正在使用的com有效,因为正在使用的com 的函数表已经给程序了,我办法去得到它。原来的接口是指程序里面 调用的接口,比如程序里面调用ShowWindow接口,调用时会先到我的 程序里面,而我的程序得到要调用的接口,再继续调用原来的com中的接口。 3:由于com类是动态创建的,所以在运行,会形成一个虚 函数表,这个表里面有所有的函数等。由于原来的com是你调用的 所以你得到接口后,去修改这个函数表,把要的函数地址替换成 你的,最后把修改的函数表也就是接口给程序。 |
|
|
9楼#
发布于:2002-06-14 19:48
I don\'t know what i think is right or not. just write here, wait someone to comment.
一般是做一个假的com dll 该com的clsid和要拦截的com clsid一样 这样当程序调用该com时会先调用你的程序 --why? really? original com internface may never been load any more. I am not sure, but I think it is. 而你的程序里面实现一套完整com接口 再由你的程序去调用原来的接口 -----where is 原来的接口? if 原来的接口 has been loaded in memory, your own CLSID will never be used anymore. if your CLSID has been loaded, 原来的接口 will never been load. anyway, Clsid\\InprocServer32 can only register one valid string 在得到接口后,去修改该接口里面虚函数表的QueryInterface 等接口,最后把修改后的接口给程序 -------------------------------------------------------- I also answer a question in msdn. i also don\'t know it\'s right or not. just paste here let someone to comment. ------------------------------------------ question: 主 题: 接口成员函数指针怎样转换成普通的字节指针?求求大侠帮我看看罢!! HRESULT (*pfIDirectSoundBufferPlay_t)(IDirectSoundBuffer * This, DWORD dwReserved1, DWORD dwPriority,DWORD dwFlags); HRESULT IDirectSoundBufferPlay (IDirectSoundBuffer * This, DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) { MessageBoxA(NULL,\"bingo in com\",\"ok\",MB_OK); return 0;//DS_OK } void BeginDetoursPlay(IDirectSoundBuffer *pi) { (*(PBYTE*)pfIDirectSoundBufferPlay_t) = DetourFunction( (PBYTE) pi->Play,//出错 (PBYTE)IDirectSoundBufferPlay);//这是我的函数 } int CancelDetoursPlay() { DWORD dwErrorCode; dwErrorCode=DetourRemove((PBYTE)pfIDirectSoundBufferPlay_t, (PBYTE)IDirectSoundBufferPlay); if (dwErrorCode=true) return 0; else return 1; } 编译时在pi->Play出错,不能将函数指针转换成字节指针,我非常奇怪,其它的参数都转换了,为什么偏偏这个不行,就因为它是COM组建接口中的函数?哪位大侠帮帮忙。 我甚至试验了reinterpret_cast<unsigned char *>(pi->Play),可编译还是出错,错误还是不能将函数指针转换成字节指针。pi->Play怎么才能转换成普通的字节指针呢? ---------here is my analysis it seems you want to hook COM function just like hook common Win32API. what Kerrie said is quite right. -------------------------- 成员函数指针永远没办法转化为普通的指针,如果你确实有需要,可以看看stl的mem_fun,是一种替代的方法,该指针区别于普通的指针 成员函数指针定义:returnvalue class::(*)(param) 使用: pObject->(*pfn)(param) -------------------------- but pObject->(*pfn)(param) may never fulfil your request. i don\'t know what i thought it correct or not. just think as following. because it\'s COM, so it use C++ standard. first we must know what all C++ (interface) have a vtable to manager function pointer. all function you call will be a DWORD align pointer. a function call like following p->func(100); // it will return nothing. in C++ will be compiled to like following push 64h //it 100d. push parameter one by one. c++ always use ESP to pass parameter, because ECX is used for THIS pointer. there is no fastcall standard for C++ mov edx,p mov eax,dword ptr [edx] //save vtable to eax mov ecx,p // __thiscall standard ask compiler to save class poiner to ecx. call dword ptr [eax+4] //it\'s func1 address, if have more func in your class or interface, maybe [eax + 8],.... Have you got any idea? so before get pointer , just do like following: wait a common test func and see assemble code ( for pi->play) , you will know shift [eax + n] (n is waht you want .) COM interface make sure that this number(n) will never be changed any more(else the caller program need rebuild ..hehe) so _asm{ mov edx,pi mov eax,dword ptr [edx] mov eax , [eax + n] //n is fix as you known. } then here, eax hold you pi->Play .... try it. |
|
10楼#
发布于:2002-06-14 11:57
这个要求对com的原理比较清楚
主要是虚函数表要相当了解 一般是做一个假的com dll 该com的clsid和要拦截的com clsid一样 这样当程序调用该com时会先调用你的程序 而你的程序里面实现一套完整com接口 再由你的程序去调用原来的接口 在得到接口后,去修改该接口里面虚函数表的QueryInterface 等接口,最后把修改后的接口给程序 这样程序调用一个接口时就到了你的程序里面 |
|
|
11楼#
发布于:2002-06-12 12:00
这问题较有趣。。。。。
是没考虑过。。。。。。 ;) |
|
|