Skip to content

Commit 26db732

Browse files
authored
Merge pull request #25 from C-Sto/moreexports
add delay imports functions, refactor section retrieval
2 parents febe44e + 6b69dda commit 26db732

File tree

1 file changed

+119
-56
lines changed

1 file changed

+119
-56
lines changed

pe/imports.go

+119-56
Original file line numberDiff line numberDiff line change
@@ -16,70 +16,30 @@ type ImportDirectory struct {
1616
DllName string
1717
}
1818

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
3029

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+
}
3632

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)
4436
return &idd
4537
}
4638

4739
// ImportDirectoryTable - returns the Import Directory Table, a pointer to the section, and the section raw data
4840
func (f *File) ImportDirectoryTable() ([]ImportDirectory, *Section, *[]byte, error) {
4941

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)
8343

8444
// didn't find a section, so no import libraries were found
8545
if ds == nil {
@@ -180,3 +140,106 @@ func (f *File) ImportedLibraries() ([]string, error) {
180140
}
181141
return all, nil
182142
}
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

Comments
 (0)