可以按序号挂接 IAT 函数吗?
Possible to hook IAT function by ordinal?
我正在处理一些 dll 注入/函数挂钩。通过比较 IAT 中的函数名称,我可以按名称挂钩导入地址 table 的函数。 (获取IMAGE_THUNK_DATA并读取值)
但是当我注入的应用程序按序号导入函数时,我将无法使用该方法取得成功。例如,有时当我检查 IMAGE_THUNK_DATA* thunkData->u1.Function 时,它似乎是一些序数。
现在回答我的问题:有没有办法获取例如 Sleep 函数 ( https://msdn.microsoft.com/de-de/library/windows/desktop/ms686298(v=vs.85).aspx ) 的序号并检查 IAT 中的值是否等于该序号?
例如这样的事情:
if (IMAGE_SNAP_BY_ORDINAL(thunkData->u1.Function)) {
//check if u1.Function is my desired ordinal number of sleep
}
或者我注入的应用程序的IAT中的序号与原始dll中的Sleep函数的序号不一样?
希望你明白我的意思。
当然可以通过序号挂钩函数,但是如果我们知道这个序号。
总的来说序数不稳定。因此,例如 Sleep
在每个 windows 版本中都有不同的序数。甚至更多 - 在相同的寡妇版本中,它在 kernel32.dll
的 x86 和 x64 版本中具有不同的序数 - 但是 Sleep
是按序数 在您的应用程序中导入的 吗?我 100% 肯定不会。
然而,在某些 dll 中(如 ws2_32.dll
或 oleaut32.dll
),某些序号是稳定的。我们如何知道哪些序数是稳定的(可以使用)?想一想 - 我们使用链接 someimport.lib
从 some.dll
导入函数 - 并且在这个导入 LIB
中包含如何导入函数的信息 - 按名称或序号。所以你需要从 LIB
文件中获取信息。这可以通过命令完成:
link.exe -dump /EXPORTS "somepath\somelib.lib" > somelib.log
让我们以 ws2_32.lib
- i 运行
为例
link.exe -dump /EXPORTS "my path\x64\ws2_32.lib" > ws2_32.log
ordinal name
?WSApSetPostRoutine@@YAHPEAX@Z (int __cdecl WSApSetPostRoutine(void *))
FreeAddrInfoEx
FreeAddrInfoExW
FreeAddrInfoW
GetAddrInfoExA
GetAddrInfoExCancel
GetAddrInfoExOverlappedResult
GetAddrInfoExW
GetAddrInfoW
GetHostNameW
GetNameInfoW
InetNtopW
InetPtonW
SetAddrInfoExA
SetAddrInfoExW
500 WEP
WPUCompleteOverlappedRequest
WPUGetProviderPathEx
WSAAccept
WSAAddressToStringA
WSAAddressToStringW
WSAAdvertiseProvider
102 WSAAsyncGetHostByAddr
103 WSAAsyncGetHostByName
105 WSAAsyncGetProtoByName
104 WSAAsyncGetProtoByNumber
107 WSAAsyncGetServByName
106 WSAAsyncGetServByPort
101 WSAAsyncSelect
108 WSACancelAsyncRequest
113 WSACancelBlockingCall
116 WSACleanup
WSACloseEvent
WSAConnect
WSAConnectByList
WSAConnectByNameA
WSAConnectByNameW
WSACreateEvent
WSADuplicateSocketA
WSADuplicateSocketW
WSAEnumNameSpaceProvidersA
WSAEnumNameSpaceProvidersExA
WSAEnumNameSpaceProvidersExW
WSAEnumNameSpaceProvidersW
WSAEnumNetworkEvents
WSAEnumProtocolsA
WSAEnumProtocolsW
WSAEventSelect
111 WSAGetLastError
WSAGetOverlappedResult
WSAGetQOSByName
WSAGetServiceClassInfoA
WSAGetServiceClassInfoW
WSAGetServiceClassNameByClassIdA
WSAGetServiceClassNameByClassIdW
WSAHtonl
WSAHtons
WSAInstallServiceClassA
WSAInstallServiceClassW
WSAIoctl
114 WSAIsBlocking
WSAJoinLeaf
WSALookupServiceBeginA
WSALookupServiceBeginW
WSALookupServiceEnd
WSALookupServiceNextA
WSALookupServiceNextW
WSANSPIoctl
WSANtohl
WSANtohs
WSAPoll
WSAProviderCompleteAsyncCall
WSAProviderConfigChange
WSARecv
WSARecvDisconnect
WSARecvFrom
WSARemoveServiceClass
WSAResetEvent
WSASend
WSASendDisconnect
WSASendMsg
WSASendTo
109 WSASetBlockingHook
WSASetEvent
112 WSASetLastError
WSASetServiceA
WSASetServiceW
WSASocketA
WSASocketW
115 WSAStartup
WSAStringToAddressA
WSAStringToAddressW
WSAUnadvertiseProvider
110 WSAUnhookBlockingHook
WSAWaitForMultipleEvents
WSCDeinstallProvider
WSCDeinstallProvider32
WSCDeinstallProviderEx
WSCEnableNSProvider
WSCEnableNSProvider32
WSCEnumNameSpaceProviders32
WSCEnumNameSpaceProvidersEx32
WSCEnumProtocols
WSCEnumProtocols32
WSCEnumProtocolsEx
WSCGetApplicationCategory
WSCGetApplicationCategoryEx
WSCGetProviderInfo
WSCGetProviderInfo32
WSCGetProviderPath
WSCGetProviderPath32
WSCInstallNameSpace
WSCInstallNameSpace32
WSCInstallNameSpaceEx
WSCInstallNameSpaceEx2
WSCInstallNameSpaceEx32
WSCInstallProvider
WSCInstallProvider64_32
WSCInstallProviderAndChains64_32
WSCInstallProviderEx
WSCSetApplicationCategory
WSCSetApplicationCategoryEx
WSCSetProviderInfo
WSCSetProviderInfo32
WSCUnInstallNameSpace
WSCUnInstallNameSpace32
WSCUnInstallNameSpaceEx2
WSCUpdateProvider
WSCUpdateProvider32
WSCUpdateProviderEx
WSCWriteNameSpaceOrder
WSCWriteNameSpaceOrder32
WSCWriteProviderOrder
WSCWriteProviderOrder32
WSCWriteProviderOrderEx
WahCloseApcHelper
WahCloseHandleHelper
WahCloseNotificationHandleHelper
WahCloseSocketHandle
WahCloseThread
WahCompleteRequest
WahCreateHandleContextTable
WahCreateNotificationHandle
WahCreateSocketHandle
WahDestroyHandleContextTable
WahDisableNonIFSHandleSupport
WahEnableNonIFSHandleSupport
WahEnumerateHandleContexts
WahInsertHandleContext
WahNotifyAllProcesses
WahOpenApcHelper
WahOpenCurrentThread
WahOpenHandleHelper
WahOpenNotificationHandleHelper
WahQueueUserApc
WahReferenceContextByHandle
WahRemoveHandleContext
WahWaitForNotification
WahWriteLSPEvent
151 __WSAFDIsSet
1 accept
2 bind
3 closesocket
4 connect
freeaddrinfo
getaddrinfo
51 gethostbyaddr
52 gethostbyname
57 gethostname
getnameinfo
5 getpeername
53 getprotobyname
54 getprotobynumber
55 getservbyname
56 getservbyport
6 getsockname
7 getsockopt
8 htonl
9 htons
11 inet_addr
12 inet_ntoa
inet_ntop
inet_pton
10 ioctlsocket
13 listen
14 ntohl
15 ntohs
16 recv
17 recvfrom
18 select
19 send
20 sendto
21 setsockopt
22 shutdown
23 socket
如果我们查看序号不为空 - API 将按序号导入(如果 PE 通过链接此库构建 )如果为空 - 将按名称导入.例如,当 WSASocketW
将按名称导入时,WSAStartup
将按序号 115 (0x73) 导入。如果 Microsoft 库 (ws2_32.lib
) 按序号 115 导出 WSAStartup
- 这意味着在所有 windows (x64) 版本中 WSAStartup
必须 以相同的序号 115 导出 - 否则与此官方库链接的大量应用程序 - 在 运行 时间内未启动或崩溃。所以在未来,ws2_32.lib
的某些其他版本可以 开始按名称导入 WSAStartup
,但是所有 windows ws2_32.dll
已经必须始终导出WSAStartup
序数为 115。
如果您检查 kernel32.lib
,您可以看到序数列全部为空 - 所以没有任何受让人说 Sleep
序数 - 它确实非常不稳定。
所以怎么写代码,比如检测WSAStartup
import entry ?
#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++;
}
我正在处理一些 dll 注入/函数挂钩。通过比较 IAT 中的函数名称,我可以按名称挂钩导入地址 table 的函数。 (获取IMAGE_THUNK_DATA并读取值)
但是当我注入的应用程序按序号导入函数时,我将无法使用该方法取得成功。例如,有时当我检查 IMAGE_THUNK_DATA* thunkData->u1.Function 时,它似乎是一些序数。
现在回答我的问题:有没有办法获取例如 Sleep 函数 ( https://msdn.microsoft.com/de-de/library/windows/desktop/ms686298(v=vs.85).aspx ) 的序号并检查 IAT 中的值是否等于该序号? 例如这样的事情:
if (IMAGE_SNAP_BY_ORDINAL(thunkData->u1.Function)) {
//check if u1.Function is my desired ordinal number of sleep
}
或者我注入的应用程序的IAT中的序号与原始dll中的Sleep函数的序号不一样?
希望你明白我的意思。
当然可以通过序号挂钩函数,但是如果我们知道这个序号。
总的来说序数不稳定。因此,例如 Sleep
在每个 windows 版本中都有不同的序数。甚至更多 - 在相同的寡妇版本中,它在 kernel32.dll
的 x86 和 x64 版本中具有不同的序数 - 但是 Sleep
是按序数 在您的应用程序中导入的 吗?我 100% 肯定不会。
然而,在某些 dll 中(如 ws2_32.dll
或 oleaut32.dll
),某些序号是稳定的。我们如何知道哪些序数是稳定的(可以使用)?想一想 - 我们使用链接 someimport.lib
从 some.dll
导入函数 - 并且在这个导入 LIB
中包含如何导入函数的信息 - 按名称或序号。所以你需要从 LIB
文件中获取信息。这可以通过命令完成:
link.exe -dump /EXPORTS "somepath\somelib.lib" > somelib.log
让我们以 ws2_32.lib
- i 运行
link.exe -dump /EXPORTS "my path\x64\ws2_32.lib" > ws2_32.log
ordinal name
?WSApSetPostRoutine@@YAHPEAX@Z (int __cdecl WSApSetPostRoutine(void *))
FreeAddrInfoEx
FreeAddrInfoExW
FreeAddrInfoW
GetAddrInfoExA
GetAddrInfoExCancel
GetAddrInfoExOverlappedResult
GetAddrInfoExW
GetAddrInfoW
GetHostNameW
GetNameInfoW
InetNtopW
InetPtonW
SetAddrInfoExA
SetAddrInfoExW
500 WEP
WPUCompleteOverlappedRequest
WPUGetProviderPathEx
WSAAccept
WSAAddressToStringA
WSAAddressToStringW
WSAAdvertiseProvider
102 WSAAsyncGetHostByAddr
103 WSAAsyncGetHostByName
105 WSAAsyncGetProtoByName
104 WSAAsyncGetProtoByNumber
107 WSAAsyncGetServByName
106 WSAAsyncGetServByPort
101 WSAAsyncSelect
108 WSACancelAsyncRequest
113 WSACancelBlockingCall
116 WSACleanup
WSACloseEvent
WSAConnect
WSAConnectByList
WSAConnectByNameA
WSAConnectByNameW
WSACreateEvent
WSADuplicateSocketA
WSADuplicateSocketW
WSAEnumNameSpaceProvidersA
WSAEnumNameSpaceProvidersExA
WSAEnumNameSpaceProvidersExW
WSAEnumNameSpaceProvidersW
WSAEnumNetworkEvents
WSAEnumProtocolsA
WSAEnumProtocolsW
WSAEventSelect
111 WSAGetLastError
WSAGetOverlappedResult
WSAGetQOSByName
WSAGetServiceClassInfoA
WSAGetServiceClassInfoW
WSAGetServiceClassNameByClassIdA
WSAGetServiceClassNameByClassIdW
WSAHtonl
WSAHtons
WSAInstallServiceClassA
WSAInstallServiceClassW
WSAIoctl
114 WSAIsBlocking
WSAJoinLeaf
WSALookupServiceBeginA
WSALookupServiceBeginW
WSALookupServiceEnd
WSALookupServiceNextA
WSALookupServiceNextW
WSANSPIoctl
WSANtohl
WSANtohs
WSAPoll
WSAProviderCompleteAsyncCall
WSAProviderConfigChange
WSARecv
WSARecvDisconnect
WSARecvFrom
WSARemoveServiceClass
WSAResetEvent
WSASend
WSASendDisconnect
WSASendMsg
WSASendTo
109 WSASetBlockingHook
WSASetEvent
112 WSASetLastError
WSASetServiceA
WSASetServiceW
WSASocketA
WSASocketW
115 WSAStartup
WSAStringToAddressA
WSAStringToAddressW
WSAUnadvertiseProvider
110 WSAUnhookBlockingHook
WSAWaitForMultipleEvents
WSCDeinstallProvider
WSCDeinstallProvider32
WSCDeinstallProviderEx
WSCEnableNSProvider
WSCEnableNSProvider32
WSCEnumNameSpaceProviders32
WSCEnumNameSpaceProvidersEx32
WSCEnumProtocols
WSCEnumProtocols32
WSCEnumProtocolsEx
WSCGetApplicationCategory
WSCGetApplicationCategoryEx
WSCGetProviderInfo
WSCGetProviderInfo32
WSCGetProviderPath
WSCGetProviderPath32
WSCInstallNameSpace
WSCInstallNameSpace32
WSCInstallNameSpaceEx
WSCInstallNameSpaceEx2
WSCInstallNameSpaceEx32
WSCInstallProvider
WSCInstallProvider64_32
WSCInstallProviderAndChains64_32
WSCInstallProviderEx
WSCSetApplicationCategory
WSCSetApplicationCategoryEx
WSCSetProviderInfo
WSCSetProviderInfo32
WSCUnInstallNameSpace
WSCUnInstallNameSpace32
WSCUnInstallNameSpaceEx2
WSCUpdateProvider
WSCUpdateProvider32
WSCUpdateProviderEx
WSCWriteNameSpaceOrder
WSCWriteNameSpaceOrder32
WSCWriteProviderOrder
WSCWriteProviderOrder32
WSCWriteProviderOrderEx
WahCloseApcHelper
WahCloseHandleHelper
WahCloseNotificationHandleHelper
WahCloseSocketHandle
WahCloseThread
WahCompleteRequest
WahCreateHandleContextTable
WahCreateNotificationHandle
WahCreateSocketHandle
WahDestroyHandleContextTable
WahDisableNonIFSHandleSupport
WahEnableNonIFSHandleSupport
WahEnumerateHandleContexts
WahInsertHandleContext
WahNotifyAllProcesses
WahOpenApcHelper
WahOpenCurrentThread
WahOpenHandleHelper
WahOpenNotificationHandleHelper
WahQueueUserApc
WahReferenceContextByHandle
WahRemoveHandleContext
WahWaitForNotification
WahWriteLSPEvent
151 __WSAFDIsSet
1 accept
2 bind
3 closesocket
4 connect
freeaddrinfo
getaddrinfo
51 gethostbyaddr
52 gethostbyname
57 gethostname
getnameinfo
5 getpeername
53 getprotobyname
54 getprotobynumber
55 getservbyname
56 getservbyport
6 getsockname
7 getsockopt
8 htonl
9 htons
11 inet_addr
12 inet_ntoa
inet_ntop
inet_pton
10 ioctlsocket
13 listen
14 ntohl
15 ntohs
16 recv
17 recvfrom
18 select
19 send
20 sendto
21 setsockopt
22 shutdown
23 socket
如果我们查看序号不为空 - API 将按序号导入(如果 PE 通过链接此库构建 )如果为空 - 将按名称导入.例如,当 WSASocketW
将按名称导入时,WSAStartup
将按序号 115 (0x73) 导入。如果 Microsoft 库 (ws2_32.lib
) 按序号 115 导出 WSAStartup
- 这意味着在所有 windows (x64) 版本中 WSAStartup
必须 以相同的序号 115 导出 - 否则与此官方库链接的大量应用程序 - 在 运行 时间内未启动或崩溃。所以在未来,ws2_32.lib
的某些其他版本可以 开始按名称导入 WSAStartup
,但是所有 windows ws2_32.dll
已经必须始终导出WSAStartup
序数为 115。
如果您检查 kernel32.lib
,您可以看到序数列全部为空 - 所以没有任何受让人说 Sleep
序数 - 它确实非常不稳定。
所以怎么写代码,比如检测WSAStartup
import entry ?
#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++;
}