I am messing around with some dll injection / function hooking. I am able to hook functions of the import address table by name, by comparing the name of the function in the IAT. (Getting IMAGE_THUNK_DATA and reading the value)
But when the application I am injecting into is importing the functions by ordinal I will not have success with that approach. For example sometimes when I check IMAGE_THUNK_DATA* thunkData->u1.Function it appears to be some ordinal number.
Now to my question: Is there a way to get the ordinal number of, for example, the Sleep function ( https://msdn.microsoft.com/de-de/library/windows/desktop/ms686298(v=vs.85).aspx ) and check if the value in the IAT is equal to that ordinal number? For example something like this:
if (IMAGE_SNAP_BY_ORDINAL(thunkData->u1.Function)) {
//check if u1.Function is my desired ordinal number of sleep
}
Or is the ordinal number in the IAT of my application I am injecting into not the same as the ordinal number of the Sleep function in the original dll?
I hope you understand what I mean.
of course possible hook function by ordinal, but if we know this ordinal.
in general ordinals is not stable. so for example Sleep
have different ordinals in every windows version. even more - in the same widows version it have different ordinals in x86 and x64 versions of kernel32.dll
- but are Sleep
imported by ordinal in your application ? i 100% sure that not.
however some ordinals is stable, in some dlls (like ws2_32.dll
or oleaut32.dll
). how we can know which ordinals is stable (can be using) ? let think - we use linking someimport.lib
for import functions from some.dll
- and in this import LIB
and containing info how import function - by name or by ordinal. so you need get info from LIB
file. this can be done by command:
link.exe -dump /EXPORTS "somepath\somelib.lib" > somelib.log
let for example take ws2_32.lib
- i run
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
if we view ordinal not empty - API will be imported by ordinal (if PE build by linking with this lib) if empty - will be import by name. so say for example WSAStartup
will be imported by ordinal 115 (0x73) when WSASocketW
will be imported by name. if Microsoft library (ws2_32.lib
) exported WSAStartup
by ordinal 115 - this mean in ALL windows (x64) versions WSAStartup
must be exported with same ordinal 115 - otherwise huge count of applications linked with this official lib - not started or crashed in runtime. so in future, some another version of ws2_32.lib
can begin import WSAStartup
by name, but all windows ws2_32.dll
already must always export WSAStartup
with 115 ordinal.
if you check kernel32.lib
you can view that ordinals column all empty - so no any grantee about say Sleep
ordinal - and it really very volatile.
so how need write code, for example detect 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++;
}