首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

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

2013-10-04 
请教一个64位WIN7下进行COM HOOK的问题。我HOOK了 IFileOperation 的 CopyItems MoveItems PerformOperatio

请教一个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个参数...

热点排行