读书人

请问一个64位WIN7下进行COM HOOK的有关

发布时间: 2013-10-04 21:41:43 作者: rapoo

请教一个64位WIN7下进行COM HOOK的问题。
我HOOK了 IFileOperation 的 CopyItems MoveItems PerformOperations 这些操作,在32位WIN7上运行良好,但在64位WIN7上完全不行。
于是我写了一个非常小的DEMO工程,代码如下:


#include <windows.h>
#include <stdio.h>

size_t WINAPI HookVtbl(void* pObject, size_t classIdx, size_t methodIdx, size_t newMethod)
{
size_t** vtbl = (size_t**)pObject;
DWORD oldProtect = 0;
size_t oldMethod = vtbl[classIdx][methodIdx];
VirtualProtect(vtbl[classIdx] + sizeof(size_t*) * methodIdx, sizeof(size_t*), PAGE_READWRITE, &oldProtect);
vtbl[classIdx][methodIdx] = newMethod;
VirtualProtect(vtbl[classIdx] + sizeof(size_t*) * methodIdx, sizeof(size_t*), oldProtect, &oldProtect);
return oldMethod;
}

class A
{
public:
virtual void printa()
{
printf("print in A\n");
}

virtual void print(int i, int j, int k)
{
printf("print in A\n");
}

virtual void print2(int i, int j, int k)
{
printf("print2 in A\n");
}
};

void WINAPI print(int i, int j, int k)
{
printf("print in global name space %d %d %d\n", i, j, k);
}

void WINAPI print2(int i, int j, int k)
{
printf("print2 in global name space %d %d %d\n", i, j, k);
}

int main()
{
printf("sizeof(int) = %d\n", sizeof(int));
printf("sizeof(size_t) = %d\n", sizeof(size_t));
A* a = new A();
int old = NULL;
size_t oldSizeT = NULL;
size_t oldSize2 = NULL;
oldSizeT = HookVtbl(a, 0, 1, (size_t)print);
oldSize2 = HookVtbl(a, 0, 2, (size_t)print2);
a->print(1, 2 ,3);
a->print2(1, 2 ,3);
HookVtbl(a, 0, 1, oldSizeT);
HookVtbl(a, 0, 2, oldSize2);
a->print(1, 2 ,3);
a->print2(1, 2 ,3);
}



分别编译成32位和64位,然后拿到64位机上测试,得出结果如下:

C:\Users\hiroyukki>C:\Users\hiroyukki\Desktop\vtb.exe
sizeof(int) = 4
sizeof(size_t) = 4
print in global name space 1 2 3
print2 in global name space 1 2 3
print in A
print2 in A

C:\Users\hiroyukki>C:\Users\hiroyukki\Desktop\vtb64.exe
sizeof(int) = 4
sizeof(size_t) = 8
print in global name space 3792736 1 2
print2 in global name space 3792736 1 2
print in A
print2 in A

可以注意到,64位的时候,HOOK用的函数参数不太对劲……。
然后我把全局函数在64位时候增加参数,则运行正常了。代码如下:

#include <windows.h>
#include <stdio.h>

size_t WINAPI HookVtbl(void* pObject, size_t classIdx, size_t methodIdx, size_t newMethod)
{
size_t** vtbl = (size_t**)pObject;
DWORD oldProtect = 0;
size_t oldMethod = vtbl[classIdx][methodIdx];
VirtualProtect(vtbl[classIdx] + sizeof(size_t*) * methodIdx, sizeof(size_t*), PAGE_READWRITE, &oldProtect);
vtbl[classIdx][methodIdx] = newMethod;
VirtualProtect(vtbl[classIdx] + sizeof(size_t*) * methodIdx, sizeof(size_t*), oldProtect, &oldProtect);
return oldMethod;
}

class A
{
public:
virtual void printa()
{
printf("print in A\n");
}

virtual void print(int i, int j, int k)
{
printf("print in A\n");
}

virtual void print2(int i, int j, int k)
{
printf("print2 in A\n");


}
};

void WINAPI print(
#ifdef _WIN64
int t,
#endif
int i, int j, int k)
{
printf("print in global name space %d %d %d\n", i, j, k);
}

void WINAPI print2(
#ifdef _WIN64
int t,
#endif
int i, int j, int k)
{
printf("print2 in global name space %d %d %d\n", i, j, k);
}

int main()
{
printf("sizeof(int) = %d\n", sizeof(int));
printf("sizeof(size_t) = %d\n", sizeof(size_t));
A* a = new A();
int old = NULL;
size_t oldSizeT = NULL;
size_t oldSize2 = NULL;
oldSizeT = HookVtbl(a, 0, 1, (size_t)print);
oldSize2 = HookVtbl(a, 0, 2, (size_t)print2);
a->print(1, 2 ,3);
a->print2(1, 2 ,3);
HookVtbl(a, 0, 1, oldSizeT);
HookVtbl(a, 0, 2, oldSize2);
a->print(1, 2 ,3);
a->print2(1, 2 ,3);
}



则输出“看起来”是正常的:
C:\Users\hiroyukki>C:\Users\hiroyukki\Desktop\vtb.exe
sizeof(int) = 4
sizeof(size_t) = 4
print in global name space 1 2 3
print2 in global name space 1 2 3
print in A
print2 in A

C:\Users\hiroyukki>C:\Users\hiroyukki\Desktop\vtb64.exe
sizeof(int) = 4
sizeof(size_t) = 8
print in global name space 1 2 3
print2 in global name space 1 2 3
print in A
print2 in A
[解决办法]
win64 下用 rcx , rdx , r8 , r9 传递前4个参数, 多余的参数由堆栈传递, 并且会留下这4个参数的位置, 浮点数用 xmm0 ... 寄存器传递 ...
elf64 下用 rdi , rsi , rdx , rcx , r8 , r9 传递前6个参数...

读书人网 >C++

热点推荐