@@ -16,70 +16,30 @@ type ImportDirectory struct {
16
16
DllName string
17
17
}
18
18
19
- // IAT returns the DataDirectory for the IAT
20
- func (f * File ) IAT () * DataDirectory {
21
- pe64 := f .Machine == IMAGE_FILE_MACHINE_AMD64
22
-
23
- // grab the number of data directory entries
24
- var ddLength uint32
25
- if pe64 {
26
- ddLength = f .OptionalHeader .(* OptionalHeader64 ).NumberOfRvaAndSizes
27
- } else {
28
- ddLength = f .OptionalHeader .(* OptionalHeader32 ).NumberOfRvaAndSizes
29
- }
19
+ // ImgDelayDescr entry for delayloaded libraries
20
+ type ImgDelayDescr struct {
21
+ GrAttrs ,
22
+ RVADLLName ,
23
+ RVAHmod ,
24
+ RVAIAT ,
25
+ RVAINT ,
26
+ RVABoundIAT ,
27
+ RVAUnloadIAT ,
28
+ DwTimeStamp uint32
30
29
31
- // check that the length of data directory entries is large
32
- // enough to include the imports directory.
33
- if ddLength < IMAGE_DIRECTORY_ENTRY_IAT + 1 {
34
- return nil
35
- }
30
+ DllName string
31
+ }
36
32
37
- // grab the IAT entry
38
- var idd DataDirectory
39
- if pe64 {
40
- idd = f .OptionalHeader .(* OptionalHeader64 ).DataDirectory [IMAGE_DIRECTORY_ENTRY_IAT ]
41
- } else {
42
- idd = f .OptionalHeader .(* OptionalHeader32 ).DataDirectory [IMAGE_DIRECTORY_ENTRY_IAT ]
43
- }
33
+ // IAT returns the DataDirectory for the IAT
34
+ func (f * File ) IAT () * DataDirectory {
35
+ _ , idd := f .sectionFromDirectoryEntry (IMAGE_DIRECTORY_ENTRY_IAT )
44
36
return & idd
45
37
}
46
38
47
39
// ImportDirectoryTable - returns the Import Directory Table, a pointer to the section, and the section raw data
48
40
func (f * File ) ImportDirectoryTable () ([]ImportDirectory , * Section , * []byte , error ) {
49
41
50
- pe64 := f .Machine == IMAGE_FILE_MACHINE_AMD64
51
-
52
- // grab the number of data directory entries
53
- var ddLength uint32
54
- if pe64 {
55
- ddLength = f .OptionalHeader .(* OptionalHeader64 ).NumberOfRvaAndSizes
56
- } else {
57
- ddLength = f .OptionalHeader .(* OptionalHeader32 ).NumberOfRvaAndSizes
58
- }
59
-
60
- // check that the length of data directory entries is large
61
- // enough to include the imports directory.
62
- if ddLength < IMAGE_DIRECTORY_ENTRY_IMPORT + 1 {
63
- return nil , nil , nil , nil
64
- }
65
-
66
- // grab the import data directory entry
67
- var idd DataDirectory
68
- if pe64 {
69
- idd = f .OptionalHeader .(* OptionalHeader64 ).DataDirectory [IMAGE_DIRECTORY_ENTRY_IMPORT ]
70
- } else {
71
- idd = f .OptionalHeader .(* OptionalHeader32 ).DataDirectory [IMAGE_DIRECTORY_ENTRY_IMPORT ]
72
- }
73
-
74
- // figure out which section contains the import directory table
75
- var ds * Section
76
- ds = nil
77
- for _ , s := range f .Sections {
78
- if s .VirtualAddress <= idd .VirtualAddress && idd .VirtualAddress < s .VirtualAddress + s .VirtualSize {
79
- ds = s
80
- break
81
- }
82
- }
42
+ ds , idd := f .sectionFromDirectoryEntry (IMAGE_DIRECTORY_ENTRY_IMPORT )
83
43
84
44
// didn't find a section, so no import libraries were found
85
45
if ds == nil {
@@ -180,3 +140,106 @@ func (f *File) ImportedLibraries() ([]string, error) {
180
140
}
181
141
return all , nil
182
142
}
143
+
144
+ func (f File ) sectionFromDirectoryEntry (directory uint32 ) (* Section , DataDirectory ) {
145
+ pe64 := f .Machine == IMAGE_FILE_MACHINE_AMD64
146
+
147
+ // grab the number of data directory entries
148
+ var ddLength uint32
149
+ if pe64 {
150
+ ddLength = f .OptionalHeader .(* OptionalHeader64 ).NumberOfRvaAndSizes
151
+ } else {
152
+ ddLength = f .OptionalHeader .(* OptionalHeader32 ).NumberOfRvaAndSizes
153
+ }
154
+
155
+ // check that the length of data directory entries is large
156
+ // enough to include the directory.
157
+ if ddLength < directory + 1 {
158
+ return nil , DataDirectory {}
159
+ }
160
+
161
+ // grab the directory entry
162
+ var idd DataDirectory
163
+ if pe64 {
164
+ idd = f .OptionalHeader .(* OptionalHeader64 ).DataDirectory [directory ]
165
+ } else {
166
+ idd = f .OptionalHeader .(* OptionalHeader32 ).DataDirectory [directory ]
167
+ }
168
+
169
+ // figure out which section contains the directory table
170
+ var ds * Section
171
+ for _ , s := range f .Sections {
172
+ if s .VirtualAddress <= idd .VirtualAddress && idd .VirtualAddress < s .VirtualAddress + s .VirtualSize {
173
+ ds = s
174
+ break
175
+ }
176
+ }
177
+ return ds , idd
178
+ }
179
+
180
+ // ImportDelayDirectoryTable - returns the Import Directory Table, a pointer to the section, and the section raw data
181
+ func (f * File ) ImportDelayDirectoryTable () ([]ImgDelayDescr , * Section , * []byte , error ) {
182
+
183
+ ds , idd := f .sectionFromDirectoryEntry (IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT )
184
+
185
+ // didn't find a section, so no import libraries were found
186
+ if ds == nil {
187
+ return nil , nil , nil , nil
188
+ }
189
+
190
+ sectionData , err := ds .Data ()
191
+ if err != nil {
192
+ return nil , nil , nil , err
193
+ }
194
+
195
+ // seek to the virtual address specified in the import data directory
196
+ d := sectionData [idd .VirtualAddress - ds .VirtualAddress :]
197
+ var dida []ImgDelayDescr
198
+ for len (d ) > 0 {
199
+ var dt ImgDelayDescr
200
+ idx := 0
201
+ dt .GrAttrs = binary .LittleEndian .Uint32 (d [idx * 4 : (idx * 4 )+ 4 ])
202
+ idx ++
203
+ dt .RVADLLName = binary .LittleEndian .Uint32 (d [idx * 4 : (idx * 4 )+ 4 ])
204
+ idx ++
205
+ dt .RVAHmod = binary .LittleEndian .Uint32 (d [idx * 4 : (idx * 4 )+ 4 ])
206
+ idx ++
207
+ dt .RVAIAT = binary .LittleEndian .Uint32 (d [idx * 4 : (idx * 4 )+ 4 ])
208
+ idx ++
209
+ dt .RVAINT = binary .LittleEndian .Uint32 (d [idx * 4 : (idx * 4 )+ 4 ])
210
+ idx ++
211
+ dt .RVABoundIAT = binary .LittleEndian .Uint32 (d [idx * 4 : (idx * 4 )+ 4 ])
212
+ idx ++
213
+ dt .RVAUnloadIAT = binary .LittleEndian .Uint32 (d [idx * 4 : (idx * 4 )+ 4 ])
214
+ idx ++
215
+ dt .DwTimeStamp = binary .LittleEndian .Uint32 (d [idx * 4 : (idx * 4 )+ 4 ])
216
+ idx ++
217
+
218
+ //check for nulls (termination entry) https://github.com/VirusTotal/yara/blob/master/libyara/modules/pe/pe.c#L1163
219
+ if dt .DwTimeStamp | dt .GrAttrs | dt .RVADLLName | dt .RVAHmod | dt .RVAIAT | dt .RVAINT | dt .RVABoundIAT | dt .RVAUnloadIAT | dt .DwTimeStamp == 0 {
220
+ break
221
+ }
222
+ if s , ok := getString (sectionData , int (dt .RVADLLName - ds .VirtualAddress )); ok {
223
+ dt .DllName = s
224
+ }
225
+ d = d [32 :]
226
+ dida = append (dida , dt )
227
+ }
228
+
229
+ return dida , ds , & sectionData , nil
230
+ }
231
+
232
+ // ImportedDelayLibraries returns the names of all libraries referred to by the binary f
233
+ // that are added to the delay imports directory. These libraries are not loaded at initialisation,
234
+ // but may be loaded during runtime.
235
+ func (f * File ) ImportedDelayLibraries () ([]string , error ) {
236
+ ida , _ , _ , err := f .ImportDelayDirectoryTable ()
237
+ if err != nil {
238
+ return nil , err
239
+ }
240
+ var all []string
241
+ for _ , dt := range ida {
242
+ all = append (all , dt .DllName )
243
+ }
244
+ return all , nil
245
+ }
0 commit comments