C++ 是否可以按顺序钩住IAT函数?

C++ 是否可以按顺序钩住IAT函数?,c++,hook,code-injection,C++,Hook,Code Injection,我正在搞一些dll注入/函数挂钩。我能够通过比较IAT中函数的名称,按名称钩住导入地址表的函数。获取图像\u THUNK\u数据并读取值 但是,当我注入的应用程序按顺序导入函数时,这种方法将不会成功。例如,有时当我检查IMAGE_THUNK_DATA*thunkData->u1.Function时,它似乎是一个序号 现在我的问题是:有没有一种方法可以获取睡眠函数的序号,并检查IAT中的值是否等于该序号? 例如,类似这样的事情: if (IMAGE_SNAP_BY_ORDINAL(thunkDat

我正在搞一些dll注入/函数挂钩。我能够通过比较IAT中函数的名称,按名称钩住导入地址表的函数。获取图像\u THUNK\u数据并读取值

但是,当我注入的应用程序按顺序导入函数时,这种方法将不会成功。例如,有时当我检查IMAGE_THUNK_DATA*thunkData->u1.Function时,它似乎是一个序号

现在我的问题是:有没有一种方法可以获取睡眠函数的序号,并检查IAT中的值是否等于该序号? 例如,类似这样的事情:

if (IMAGE_SNAP_BY_ORDINAL(thunkData->u1.Function)) {
    //check if u1.Function is my desired ordinal number of sleep
}
或者我正在注入的应用程序的IAT中的序号是否与原始dll中的Sleep函数的序号不同


我希望你能理解我的意思。

当然可能是序数的钩子函数,但如果我们知道这个序数

一般来说,序数是不稳定的。例如,睡眠在每个windows版本中都有不同的序号。更重要的是,在同一widows版本中,它在x86和x64版本的kernel32.dll中有不同的序号,但是睡眠在应用程序中是按序号导入的吗?我百分之百肯定不会

但是,在某些dll(如ws2_32.dll或oleaut32.dll)中,某些序号是稳定的。我们如何知道哪些序数是稳定的?让我们想想-我们使用链接someimport.lib从some.dll导入函数-在这个导入库中,包含如何导入函数的信息-按名称或顺序。所以你需要从LIB文件中获取信息。这可以通过以下命令完成:

link.exe-dump/EXPORTS somepath\somelib.lib>somelib.log

让我们以ws2_32.lib为例—我运行

link.exe-转储/导出我的路径\x64\ws2_32.lib>ws2_32.log

如果我们查看ordinal not empty-API将按ordinal导入,如果PE通过链接此库生成,如果为空-将按名称导入。例如,当WSASocketW按名称导入时,WSAStartup将按序号115 0x73导入。如果Microsoft library ws2_32.lib按序号115导出WSAStartup-这意味着在所有windows x64版本中,WSAStartup必须以相同的序号115导出-否则与此官方lib链接的应用程序数量巨大-在运行时未启动或崩溃。因此,将来,ws2_32.lib的另一个版本可以开始按名称导入WSAStartup,但所有windows ws2_32.dll都必须始终以115序号导出WSAStartup

如果您检查kernel32.lib,您可以看到序号列都是空的——因此没有任何被授权人会说Sleep ordinal——而且它确实非常不稳定

那么,需要如何编写代码,例如检测WSAStartup导入条目

#define WSAStartup_Ordinal 115

PVOID hmod;
PIMAGE_IMPORT_DESCRIPTOR piid;
ULONG size/* size of IMPORT directory*/, d;
// assume hmod, piid, size already initialized

while ((INT)size >= sizeof(IMAGE_IMPORT_DESCRIPTOR) && (d = piid->Name))
{
    PCSTR name = RtlOffsetToPointer(hmod, d);

    if (!_stricmp(name, "ws2_32.dll"))
    {
        if (d = piid->FirstThunk)
        {
            PIMAGE_THUNK_DATA FirstThunk = (PIMAGE_THUNK_DATA)RtlOffsetToPointer(hmod, d);

            if (d = piid->OriginalFirstThunk)
            {
                PIMAGE_THUNK_DATA OriginalFirstThunk = (PIMAGE_THUNK_DATA)RtlOffsetToPointer(hmod, d);

                while (ULONG_PTR Ordinal = OriginalFirstThunk->u1.Ordinal)
                {
                    ULONG_PTR Function = 0;

                    if (IMAGE_SNAP_BY_ORDINAL(Ordinal))
                    {
                        if (IMAGE_ORDINAL(Ordinal) == WSAStartup_Ordinal) // 115
                        {
                            Function = FirstThunk->u1.Function;
                        }
                    }
                    else
                    {
                        if (!strcmp((PCSTR)((PIMAGE_IMPORT_BY_NAME)RtlOffsetToPointer(hmod, Ordinal))->Name, "WSAStartup"))
                        {
                            Function = FirstThunk->u1.Function;
                        }
                    }

                    if (Function)
                    {
                        __nop();
                    }
                }
            }
        }
    }

    size -= sizeof(IMAGE_IMPORT_DESCRIPTOR), piid++;
}

@用户-你完全错了-顺序不稳定。我们不能使用序数进行睡眠-它在不同的windows版本中是不同的。@RbMm哦,好的,谢谢。如果说睡眠是通过序数导入的,通过IAT钩住该函数,还有其他解决方案吗?睡眠从来不是通过序数导入的,这是不正确的。不过我当然知道解决方案哇谢谢你回答:你说得对,实际上我想挂接的函数是ws2_32.sendto,但我在IAT中找不到它的名字,所以我猜它是按序号导入的。我会继续阅读你的代码,直到我100%理解它,但是谢谢你,巴迪:@User90234-sendto有序号20-look-in表,我刚刚用你的指南修改了我的函数,效果非常好,谢谢巴迪:我可以再问你一件事吗:如果两个函数实际上有相同的序号,会发生什么?像sendto有序号20,而另一个dll的其他函数也有序号20?那么会发生什么呢?在同一个dll中,只有一个函数具有此序号。你检查dll名称了吗?哦,漏掉了那部分。。。似乎是合乎逻辑的,现在明白了:你可能知道,现在已经离题了,为什么如果我覆盖了IAT的函数,游戏会崩溃,但当我覆盖了测试应用程序的IAT函数时,一切都正常了?有什么我不知道的保护措施吗?我已经将内存保护更改为读写访问。抱歉打扰你这么久
#define WSAStartup_Ordinal 115

PVOID hmod;
PIMAGE_IMPORT_DESCRIPTOR piid;
ULONG size/* size of IMPORT directory*/, d;
// assume hmod, piid, size already initialized

while ((INT)size >= sizeof(IMAGE_IMPORT_DESCRIPTOR) && (d = piid->Name))
{
    PCSTR name = RtlOffsetToPointer(hmod, d);

    if (!_stricmp(name, "ws2_32.dll"))
    {
        if (d = piid->FirstThunk)
        {
            PIMAGE_THUNK_DATA FirstThunk = (PIMAGE_THUNK_DATA)RtlOffsetToPointer(hmod, d);

            if (d = piid->OriginalFirstThunk)
            {
                PIMAGE_THUNK_DATA OriginalFirstThunk = (PIMAGE_THUNK_DATA)RtlOffsetToPointer(hmod, d);

                while (ULONG_PTR Ordinal = OriginalFirstThunk->u1.Ordinal)
                {
                    ULONG_PTR Function = 0;

                    if (IMAGE_SNAP_BY_ORDINAL(Ordinal))
                    {
                        if (IMAGE_ORDINAL(Ordinal) == WSAStartup_Ordinal) // 115
                        {
                            Function = FirstThunk->u1.Function;
                        }
                    }
                    else
                    {
                        if (!strcmp((PCSTR)((PIMAGE_IMPORT_BY_NAME)RtlOffsetToPointer(hmod, Ordinal))->Name, "WSAStartup"))
                        {
                            Function = FirstThunk->u1.Function;
                        }
                    }

                    if (Function)
                    {
                        __nop();
                    }
                }
            }
        }
    }

    size -= sizeof(IMAGE_IMPORT_DESCRIPTOR), piid++;
}