关键:
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk;// 指向一个 IMAGE_THUNK_DATA 结构数组的RVA
}
DWORD TimeDateStamp;// 文件生成的时间
DWORD ForwarderChain;// 这个数据一般为0,可以不关心
DWORD Name1; // RVA,指向DLL名字的指针,ASCII字符串
DWORD FirstThunk; //指向一个 IMAGE_THUNK_DATA 结构数组的RVA,这个数据与IAT所指向的地址一致
}IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR
IMAGE_THUNK_DATA 这是一个DWORD类型的集合。通常我们将其解释为指向一个 IMAGE_IMPORT_BY_NAME 结构的指针,其定义如下:
IMAGE_THUNK_DATA{
union {
PBYTE ForwarderString;
PDWORD Function;
DWORD Ordinal;//判定当前结构数据是不是以序号为输出的,如果是的话该值为0x800000000,此时PIMAGE_IMPORT_BY_NAME不可做为名称使用
PIMAGE_IMPORT_BY_NAME AddressOfData;
}u1;
} IMAGE_THUNK_DATA,*PIMAGE_THUNK_DATA;
typedef struct _IMAGE_IMPORT_BY_NAME{
WORD Hint;// 函数输出序号
BYTE Name1[1];//输出函数名称
} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME
现在我们知道如何找到引入表了。Data Directory数组第二项的VirtualAddress包含引入表地址。引入表实际上是一个 IMAGE_IMPORT_DESCRIPTOR 结构数组。每个结构包含PE文件引入函数的一个相关DLL的信息。比如,如果该PE文件从10个不同的DLL中引入函数,那么这个数组就有10个成员。该数组以一个全0的成员结尾。下面详细研究结构组成:
IMAGE_IMPORT_DESCRIPTOR STRUCT
union
Characteristics dd ?
OriginalFirstThunk dd ?
ends
TimeDateStamp dd ?
ForwarderChain dd ?
Name1 dd ?
FirstThunk dd ?
IMAGE_IMPORT_DESCRIPTOR ENDS
结构第一项是一个union子结构。事实上,这个union子结构只是给 OriginalFirstThunk 增添了个别名,您也可以称其为"Characteristics"。 该成员项是指向一个指向一个DWORD 数组的RVA。数组里的每一个DWORD 事实上是一个IMAGE_THUNK_DATA union。那么,什么 IMAGE_THUNK_DATA又是什么呢? 每个IMAGE_THUNK_DATA union对应于一个输入函数,这个DWORD(即IMAGE_THUNK_DATA union)的内容视文件被加载与否(即:加载前后内容不同,原因后面会解释),以及函数被以名称输入或以序号输入而定(即:输入方式不同,内容不同)。以名称输入是比较共同的方式。当一个函数以序号输入,EXE 文件的IMAGE_THUNK_DATA DWORD 中的最高位(0x80000000)设立。例如,考虑一个IMAGE_THUNK_DATA,其值为0x80000112,放在GDI32.DLL 数组中。表示这IMAGE_THUNK_DATA 将输入GDI32.DLL 中的第112号输出(exported)函数。如果函数以名称输入,IMAGE_THUNK_DATA DWORD 就内含一个RVA(Relative Virtual Address),指向IMAGE_IMPORT_BY_NAME 结构,由于一个输入函数对应一个IMAGE_THUNK_DATA union,而当函数以名称输入的时候IMAGE_THUNK_DATA又指向一个IMAGE_IMPORT_BY_NAME 结构,所以此时一个输入函数对应一个IMAGE_IMPORT_BY_NAME 结构。现在让我们看看IMAGE_IMPORT_BY_NAME 结构里面有些什么东东,我们希望里面存有一个引入函数的相关信息。奥,原来它真的如我们所愿:
IMAGE_IMPORT_BY_NAME STRUCT
Hint dw ?
Name1 db ?
IMAGE_IMPORT_BY_NAME ENDS
Hint 指示本函数在其所驻留DLL的引出表中的索引号。该域被PE装载器用来在DLL的引出表里快速查询函数。
Name1 含有引入函数的函数名。函数名是一个ASCIIZ字符串。现在请看这里: 假设程序中调用了N个输入函数,那么就对应着有N个 IMAGE_IMPORT_BY_NAME 结构,我们收集起这些结构的RVA 放在IMAGE_THUNK_DATA结构中组成一个数组,并以0结尾,然后再将此数组的RVA放入 OriginalFirstThunk。 这样一来我们就可以利用OriginalFirstThunk这条线把从某一个DLL中调用的函数全部給揪出来。
奥,刚才我们被IMAGE_IMPORT_BY_NAME 结构给中断了一下,现在让我们返回IMAGE_IMPORT_DESCRIPTOR结构,继续看里面的其他域。为了和上面的讨论保持连贯性先让我们来看一下最后一个域FirstThunk,FirstThunk 与 OriginalFirstThunk 非常相似,也是一个RVA,它也是指向一个 IMAGE_THUNK_DATA 结构数组(当然这是另外一个IMAGE_THUNK_DATA 结构数组,不过这个IMAGE_THUNK_DATA结构数组和OriginalFirstThunk指向的IMAGE_THUNK_DATA结构数组内容是完全一样的)。好的让我们理顺一下:现在有几个 IMAGE_IMPORT_BY_NAME 结构,同时您又创建了两个结构数组,并同样存入指向那些 IMAGE_IMPORT_BY_NAME 结构的RVA,这样两个数组就包含相同数值了(可谓相当精确的复制啊)。最后您决定将第一个数组的RVA赋给 OriginalFirstThunk,第二个数组的RVA赋给 FirstThunk,这样一切都很清楚了。如果你对上面一堆的RVA和结构数组的关系感到头晕的话那么请往下看,或许下面这个图解能让你清醒一些:
OriginalFirstThunk IMAGE_IMPORT_BY_NAME FirstThunk
IMAGE_THUNK_DATA ---> Function 1 <--- IMAGE_THUNK_DATA
IMAGE_THUNK_DATA ---> Function 2 <--- MAGE_THUNK_DATA
IMAGE_THUNK_DATA ---> Function 3 <--- IMAGE_THUNK_DATA
IMAGE_THUNK_DATA ---> Function 4 <--- IMAGE_THUNK_DATA
... ... ...
IMAGE_THUNK_DATA ---> Function n <--- IMAGE_THUNK_DATA
现在您应该明白我的意思。不要被IMAGE_THUNK_DATA这个名字弄糊涂: 当以名字引入函数时,它仅是指向 IMAGE_IMPORT_BY_NAME 结构的RVA。 如果将 IMAGE_THUNK_DATA 字眼想象成RVA,就更容易明白了。OriginalFirstThunk 和 FirstThunk 所指向的这两个数组大小取决于PE文件从DLL中引入函数的数目。比如,如果PE文件从kernel32.dll中引入10个函数,那么IMAGE_IMPORT_DESCRIPTOR 结构的 Name1域包含指向字符串"kernel32.dll"的RVA,同时每个IMAGE_THUNK_DATA 数组有10个元素。
附WS2_32.dll函数导出表:
(该dll特殊,当exe导入时,不会导入函数名,而是函数序号,即
“
当一个函数以序号输入,EXE 文件的IMAGE_THUNK_DATA DWORD 中的最高位(0x80000000)设立。”
注意ordinal是序号)
File Type: DLL
Section contains the following exports for WS2_32.dll
00000000 characteristics
4CE78957 time date stamp Sat Nov 20 16:39:51 2010
0.00 version
1 ordinal base
500 number of functions
167 number of names
ordinal hint RVA name
25 0 0000E14D FreeAddrInfoEx
26 1 0000E14D FreeAddrInfoExW
27 2 00004B1B FreeAddrInfoW
28 3 0001469B GetAddrInfoExA
29 4 0000D1EA GetAddrInfoExW
30 5 00004889 GetAddrInfoW
31 6 000066AF GetNameInfoW
32 7 00013ABF InetNtopW
33 8 000139DC InetPtonW
34 9 000145F7 SetAddrInfoExA
35 A 0000F4F6 SetAddrInfoExW
500 B 0001E764 WEP
36 C 0001E39B WPUCompleteOverlappedRequest
37 D 000068D6 WSAAccept
38 E 0000331E WSAAddressToStringA
39 F 00006CF6 WSAAddressToStringW
40 10 00020509 WSAAdvertiseProvider
102 11 0001736B WSAAsyncGetHostByAddr
103 12 0001726A WSAAsyncGetHostByName
105 13 0001744E WSAAsyncGetProtoByName
104 14 0001754F WSAAsyncGetProtoByNumber
107 15 000170A7 WSAAsyncGetServByName
106 16 000171AE WSAAsyncGetServByPort
101 17 0001B014 WSAAsyncSelect
108 18 00017602 WSACancelAsyncRequest
113 19 00015343 WSACancelBlockingCall
116 1A 00003C5F WSACleanup
41 1B 0000651F WSACloseEvent
42 1C 0000CC3F WSAConnect
43 1D 0001BFDD WSAConnectByList
44 1E 0001C8B6 WSAConnectByNameA
45 1F 0001C52F WSAConnectByNameW
46 20 000064FB WSACreateEvent
47 21 000161B6 WSADuplicateSocketA
48 22 00016128 WSADuplicateSocketW
49 23 00019FC1 WSAEnumNameSpaceProvidersA
50 24 0001A021 WSAEnumNameSpaceProvidersExA
58 25 0001A081 WSAEnumNameSpaceProvidersExW
59 26 0000D8D3 WSAEnumNameSpaceProvidersW
60 27 000031B1 WSAEnumNetworkEvents
61 28 0001627F WSAEnumProtocolsA
62 29 0000C8E1 WSAEnumProtocolsW
63 2A 0000648F WSAEventSelect
111 2B 000037AD WSAGetLastError
64 2C 00007489 WSAGetOverlappedResult
65 2D 00019B68 WSAGetQOSByName
66 2E 0001AA00 WSAGetServiceClassInfoA
67 2F 0001A849 WSAGetServiceClassInfoW
68 30 0001A44D WSAGetServiceClassNameByClassIdA
69 31 0001A651 WSAGetServiceClassNameByClassIdW
70 32 00013B24 WSAHtonl
71 33 00013C11 WSAHtons
72 34 0001A981 WSAInstallServiceClassA
73 35 0001A277 WSAInstallServiceClassW
74 36 00002FE7 WSAIoctl
114 37 000153BE WSAIsBlocking
75 38 0001CA7D WSAJoinLeaf
76 39 0000A642 WSALookupServiceBeginA
77 3A 0000575A WSALookupServiceBeginW
78 3B 00005239 WSALookupServiceEnd
79 3C 0000A27B WSALookupServiceNextA
80 3D 00004CBC WSALookupServiceNextW
81 3E 0000EF85 WSANSPIoctl
82 3F 00013B24 WSANtohl
83 40 00013C11 WSANtohs
84 41 0001B0A5 WSAPoll
85 42 00020B79 WSAProviderCompleteAsyncCall
86 43 0000C22E WSAProviderConfigChange
87 44 00007089 WSARecv
88 45 00019DBD WSARecvDisconnect
89 46 0000CBA6 WSARecvFrom
90 47 0001A362 WSARemoveServiceClass
91 48 0000CDC3 WSAResetEvent
92 49 00004406 WSASend
93 4A 0001B281 WSASendDisconnect
94 4B 0001B3CB WSASendMsg
95 4C 0001B30C WSASendTo
109 4D 0001543D WSASetBlockingHook
96 4E 0000CDD4 WSASetEvent
112 4F 000037D9 WSASetLastError
97 50 0001AA92 WSASetServiceA
98 51 0000F606 WSASetServiceW
99 52 0000C82A WSASocketA
100 53 00003CD3 WSASocketW
115 54 00003AB2 WSAStartup
117 55 0000ED31 WSAStringToAddressA
118 56 00006DDD WSAStringToAddressW
119 57 00020643 WSAUnadvertiseProvider
110 58 000154C1 WSAUnhookBlockingHook
120 59 0000650E WSAWaitForMultipleEvents
24 5A 0001E546 WSApSetPostRoutine
121 5B 0001D775 WSCDeinstallProvider
122 5C 000193AC WSCEnableNSProvider
123 5D 0000B8CF WSCEnumProtocols
124 5E 0001DF81 WSCGetApplicationCategory
125 5F 0001D961 WSCGetProviderInfo
126 60 0000C64E WSCGetProviderPath
127 61 000196A9 WSCInstallNameSpace
128 62 00019859 WSCInstallNameSpaceEx
129 63 0001D751 WSCInstallProvider
130 64 00018793 WSCInstallProviderAndChains
131 65 0001DB99 WSCSetApplicationCategory
132 66 0001D1D1 WSCSetProviderInfo
133 67 00019A11 WSCUnInstallNameSpace
134 68 0001CE2D WSCUpdateProvider
135 69 00019571 WSCWriteNameSpaceOrder
136 6A 0001D099 WSCWriteProviderOrder
137 6B 0000AA67 WahCloseApcHelper
138 6C 0002272D WahCloseHandleHelper
139 6D 00023261 WahCloseNotificationHandleHelper
140 6E 00022772 WahCloseSocketHandle
141 6F 000032C4 WahCloseThread
142 70 000227C1 WahCompleteRequest
143 71 00007E65 WahCreateHandleContextTable
144 72 0000C3CB WahCreateNotificationHandle
145 73 00023080 WahCreateSocketHandle
146 74 0000F268 WahDestroyHandleContextTable
147 75 000229FD WahDisableNonIFSHandleSupport
148 76 0002284F WahEnableNonIFSHandleSupport
149 77 0000AA97 WahEnumerateHandleContexts
150 78 0000412B WahInsertHandleContext
152 79 000232C3 WahNotifyAllProcesses
153 7A 00008483 WahOpenApcHelper
154 7B 000036A7 WahOpenCurrentThread
155 7C 00022CB2 WahOpenHandleHelper
156 7D 0000C1FA WahOpenNotificationHandleHelper
157 7E 00022096 WahQueueUserApc
158 7F 00002F20 WahReferenceContextByHandle
159 80 000039B0 WahRemoveHandleContext
160 81 0000C2F0 WahWaitForNotification
161 82 00023665 WahWriteLSPEvent
151 83 00006A8A __WSAFDIsSet
1 84 000068B6 accept
2 85 00004582 bind
3 86 00003918 closesocket
4 87 00006BDD connect
162 88 00004B1B freeaddrinfo
163 89 00004296 getaddrinfo
51 8A 00016C01 gethostbyaddr
52 8B 00017673 gethostbyname
57 8C 0000A05B gethostname
164 8D 000067B7 getnameinfo
5 8E 00007147 getpeername
53 8F 000168B3 getprotobyname
54 90 000167C4 getprotobynumber
55 91 00016EF3 getservbyname
56 92 00016D62 getservbyport
6 93 000030AF getsockname
7 94 0000737D getsockopt
8 95 00002D57 htonl
9 96 00002D8B htons
11 97 0000311B inet_addr
12 98 0000B131 inet_ntoa
165 99 00013A5A inet_ntop
166 9A 00013969 inet_pton
10 9B 00003084 ioctlsocket
13 9C 0000B001 listen
14 9D 00002D57 ntohl
15 9E 00002D8B ntohs
16 9F 00006B0E recv
17 A0 0000B6DC recvfrom
18 A1 00006989 select
19 A2 00006F01 send
20 A3 000034B5 sendto
21 A4 000041B6 setsockopt
22 A5 0000449D shutdown
23 A6 00003EB8 socket
Summary
1000 .data
2000 .reloc
B000 .rsrc
26000 .text