可以通过序数挂钩IAT功能吗?

时间:2017-01-22 15:37:15

标签: c++ hook code-injection

我正在搞乱一些dll注入/功能挂钩。我可以通过比较IAT中函数的名称来按名称挂钩导入地址表的函数。 (获取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函数的序号不同?

我希望你理解我的意思。

1 个答案:

答案 0 :(得分:1)

当然,如果我们知道这个序数,可以按顺序挂钩,

一般来说,序数不稳定。所以例如kernel32.dll在每个Windows版本中都有不同的序数。甚至更多 - 在相同的寡妇版本中,它在x86和x64版本的Sleep中有不同的序数 - 但是在您的应用程序中由{ordinal 导入 {em}我100%肯定不会。

但有些dll(如ws2_32.dlloleaut32.dll)中的某些序数是稳定的。我们怎么知道哪些序数是稳定的(可以使用)?让我们思考 - 我们使用someimport.lib链接来自some.dll的导入函数 - 并在此导入LIB中包含信息如何导入函数 - 按名称或按顺序。所以你需要从LIB文件中获取信息。这可以通过命令来完成:

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

让我们举例ws2_32.lib - 我运行

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) - 将按名称导入。所以说例如WSAStartup将由序号115(0x73)导入,当WSASocketW将按名称导入时。如果Microsoft库(ws2_32.lib)按序号115导出WSAStartup - 这意味着所有窗口(x64)版本WSAStartup 必须以相同的序数115导出 - 否则与此官方库链接的大量应用程序 - 未在运行时启动或崩溃。因此,将来某个版本的ws2_32.lib 可以按名称开始导入WSAStartup,但所有窗口ws2_32.dll必须始终导出WSAStartup 115序。

如果你检查kernel32.lib,你可以查看该序列列全部为空 - 所以没有关于说Sleep序号的任何受让人 - 而且它真的非常不稳定。

那么如何编写代码,例如检测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++;
}