C++ 是否可以按顺序钩住IAT函数?
我正在搞一些dll注入/函数挂钩。我能够通过比较IAT中函数的名称,按名称钩住导入地址表的函数。获取图像\u THUNK\u数据并读取值 但是,当我注入的应用程序按顺序导入函数时,这种方法将不会成功。例如,有时当我检查IMAGE_THUNK_DATA*thunkData->u1.Function时,它似乎是一个序号 现在我的问题是:有没有一种方法可以获取睡眠函数的序号,并检查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
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++;
}