-
Notifications
You must be signed in to change notification settings - Fork 0
/
Import.cpp
152 lines (124 loc) · 5.09 KB
/
Import.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "stdafx.h"
#include "Import.h"
#include "PeCommon.h"
#include "PeErrors.h"
#include "PeFile.h"
UINT Import::ReadImport(const PeFile& peFile, DWORD64 fileOffset)
{
UINT ret = PE_SUCCESS;
DataDirectoryEntry importDirectory = peFile.GetDataDirectories(DataDirectoryType::Import);
// If the data directory does not exist then we ignore processing further
if (importDirectory.VirtualAddress == 0 && importDirectory.Size == 0)
return ret;
fstream in(peFile.GetPeFilePath(), fstream::binary | fstream::in);
if (!in)
return PE_FILE_OPEN_ERROR;
// Store the file address of Import Directory Table entry
FileAddress = fileOffset;
// Move file pointer to Import Directory Table entry
in.seekg(FileAddress, ios_base::beg);
// Read the fields.
COPY_AND_CHECK_RETURN_STATUS(in, ImportLookupTableRVA);
COPY_AND_CHECK_RETURN_STATUS(in, TimeStamp);
COPY_AND_CHECK_RETURN_STATUS(in, ForwarderChain);
COPY_AND_CHECK_RETURN_STATUS(in, ImportModuleNameRVA);
COPY_AND_CHECK_RETURN_STATUS(in, ImportAddressTableRVA);
// Break on reaching a null entry
if (ImportLookupTableRVA == 0 &&
TimeStamp == 0 &&
ForwarderChain == 0 &&
ImportModuleNameRVA == 0 &&
ImportAddressTableRVA == 0)
return PE_REACHED_NULL_ENTRY;
ret = ReadImportModuleName(peFile, peFile.RvaToFa(ImportModuleNameRVA));
RETURN_ON_FAILURE(ret);
ret = ReadImportModuleFunctions(peFile, peFile.RvaToFa(ImportLookupTableRVA));
RETURN_ON_FAILURE(ret);
return PE_SUCCESS;
}
UINT Import::ReadImportModuleName(const PeFile& peFile, DWORD64 fileOffset)
{
UINT ret = PE_SUCCESS;
fstream in(peFile.GetPeFilePath(), fstream::binary | fstream::in);
// Seek to FA of ImportModuleNameRVA
in.seekg(fileOffset, ios_base::beg);
// Copy bytes until we encounter a null byte
// This becomes the module name
char c = 0;
while (in.read(&c, 1)) {
if (c == 0)
break;
ModuleName += c;
}
in.close();
return ret;
}
UINT Import::ReadImportModuleFunctions(const PeFile& peFile, DWORD64 fileOffset)
{
UINT ret = PE_SUCCESS;
fstream in(peFile.GetPeFilePath(), fstream::binary | fstream::in);
// Seek to Import Lookup Table
in.seekg(fileOffset, ios_base::beg);
// Import Lookup Table is also terminated by a null entry
while (true) {
DWORD64 importLookupEntry = 0;
COPY_WITH_SIZE_AND_CHECK_RETURN_STATUS(in, importLookupEntry, peFile.IsPe32() ? 4 : 8);
if (importLookupEntry == 0) // Reached end of the Import Lookup Table
break;
// Read Ordinal/Name bit from Import Lookup Table
bool isOrdinal = (importLookupEntry >> (peFile.IsPe32() ? 31 : 63)) & 1;
if (isOrdinal) {
// Function imported by Ordinal number
ModuleOrdinalNumbers.push_back(importLookupEntry & 0xffff);
}
else {
// 0 - 31 bits indicate the hint/function name table entry rva.
// It is the rva of an entry not the table address
DWORD64 hintNameTableFA = peFile.RvaToFa(importLookupEntry & 0x7fffffff);
// Backup current file position on 'in' and Seek to hint/name table entry
streampos beforeNameTable = in.tellg();
in.seekg(hintNameTableFA, ios_base::beg);
// Below are Hint/Name table fields
WORD hint = 0;
string functionName;
COPY_AND_CHECK_RETURN_STATUS(in, hint); // Skip over hint
while (true) {
char c = 0;
in.read(&c, 1);
if (c == 0)
break;
functionName += c;
}
//if (in.peek() == 0)
// in.get();
ModuleFunctionNames.push_back(functionName);
// Restore file pointer back to Import Lookup table entry
in.seekg(beforeNameTable, ios_base::beg);
}
}
in.close();
return ret;
}
void Import::DumpImport(const PeFile& peFile)
{
DataDirectoryEntry importDirectory = peFile.GetDataDirectories(DataDirectoryType::Import);
// If the data directory does not exist then we ignore processing further
if (importDirectory.VirtualAddress == 0 && importDirectory.Size == 0)
return;
cout << "Import Module Name: " << ModuleName << endl;
printf(" %-25s: %#.lx\n", "NameRVA", ImportModuleNameRVA);
printf(" %-25s: %lx\n", "TimeStamp", TimeStamp);
printf(" %-25s: %lx\n", "ForwarderChain", ForwarderChain);
printf(" %-25s: %#.lx\n", "ImportLookupTableRVA", ImportLookupTableRVA);
printf(" %-25s: %#.lx\n", "ImportAddressTableRVA", ImportAddressTableRVA);
if (ModuleFunctionNames.size() > 0) {
printf(" %-25s:\n", "Module Function Names");
for (auto& string : ModuleFunctionNames)
cout << " " << string << endl;
}
if (ModuleOrdinalNumbers.size() > 0) {
printf(" %-25s:\n", "Module Ordinals");
for (auto& ordinal : ModuleOrdinalNumbers)
cout << " " << ordinal << endl;
}
}