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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
|
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
// Copyright 2015 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
#define BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#include <boost/cstdint.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/dll/detail/x_info_interface.hpp>
namespace boost { namespace dll { namespace detail {
// reference:
// http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/
// http://msdn.microsoft.com/en-us/magazine/ms809762.aspx
// http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
//
// Basic Windows typedefs. We can not use <boost/winapi/basic_types.hpp> header
// because that header must be included only on Windows platform
typedef unsigned char BYTE_;
typedef unsigned short WORD_;
typedef boost::uint32_t DWORD_;
typedef boost::int32_t LONG_;
typedef boost::uint32_t ULONG_;
typedef boost::int64_t LONGLONG_;
typedef boost::uint64_t ULONGLONG_;
struct IMAGE_DOS_HEADER_ { // 32/64 independent header
boost::dll::detail::WORD_ e_magic; // Magic number
boost::dll::detail::WORD_ e_cblp; // Bytes on last page of file
boost::dll::detail::WORD_ e_cp; // Pages in file
boost::dll::detail::WORD_ e_crlc; // Relocations
boost::dll::detail::WORD_ e_cparhdr; // Size of header in paragraphs
boost::dll::detail::WORD_ e_minalloc; // Minimum extra paragraphs needed
boost::dll::detail::WORD_ e_maxalloc; // Maximum extra paragraphs needed
boost::dll::detail::WORD_ e_ss; // Initial (relative) SS value
boost::dll::detail::WORD_ e_sp; // Initial SP value
boost::dll::detail::WORD_ e_csum; // Checksum
boost::dll::detail::WORD_ e_ip; // Initial IP value
boost::dll::detail::WORD_ e_cs; // Initial (relative) CS value
boost::dll::detail::WORD_ e_lfarlc; // File address of relocation table
boost::dll::detail::WORD_ e_ovno; // Overlay number
boost::dll::detail::WORD_ e_res[4]; // Reserved words
boost::dll::detail::WORD_ e_oemid; // OEM identifier (for e_oeminfo)
boost::dll::detail::WORD_ e_oeminfo; // OEM information; e_oemid specific
boost::dll::detail::WORD_ e_res2[10]; // Reserved words
boost::dll::detail::LONG_ e_lfanew; // File address of new exe header
};
struct IMAGE_FILE_HEADER_ { // 32/64 independent header
boost::dll::detail::WORD_ Machine;
boost::dll::detail::WORD_ NumberOfSections;
boost::dll::detail::DWORD_ TimeDateStamp;
boost::dll::detail::DWORD_ PointerToSymbolTable;
boost::dll::detail::DWORD_ NumberOfSymbols;
boost::dll::detail::WORD_ SizeOfOptionalHeader;
boost::dll::detail::WORD_ Characteristics;
};
struct IMAGE_DATA_DIRECTORY_ { // 32/64 independent header
boost::dll::detail::DWORD_ VirtualAddress;
boost::dll::detail::DWORD_ Size;
};
struct IMAGE_EXPORT_DIRECTORY_ { // 32/64 independent header
boost::dll::detail::DWORD_ Characteristics;
boost::dll::detail::DWORD_ TimeDateStamp;
boost::dll::detail::WORD_ MajorVersion;
boost::dll::detail::WORD_ MinorVersion;
boost::dll::detail::DWORD_ Name;
boost::dll::detail::DWORD_ Base;
boost::dll::detail::DWORD_ NumberOfFunctions;
boost::dll::detail::DWORD_ NumberOfNames;
boost::dll::detail::DWORD_ AddressOfFunctions;
boost::dll::detail::DWORD_ AddressOfNames;
boost::dll::detail::DWORD_ AddressOfNameOrdinals;
};
struct IMAGE_SECTION_HEADER_ { // 32/64 independent header
static const std::size_t IMAGE_SIZEOF_SHORT_NAME_ = 8;
boost::dll::detail::BYTE_ Name[IMAGE_SIZEOF_SHORT_NAME_];
union {
boost::dll::detail::DWORD_ PhysicalAddress;
boost::dll::detail::DWORD_ VirtualSize;
} Misc;
boost::dll::detail::DWORD_ VirtualAddress;
boost::dll::detail::DWORD_ SizeOfRawData;
boost::dll::detail::DWORD_ PointerToRawData;
boost::dll::detail::DWORD_ PointerToRelocations;
boost::dll::detail::DWORD_ PointerToLinenumbers;
boost::dll::detail::WORD_ NumberOfRelocations;
boost::dll::detail::WORD_ NumberOfLinenumbers;
boost::dll::detail::DWORD_ Characteristics;
};
template <class AddressOffsetT>
struct IMAGE_OPTIONAL_HEADER_template {
static const std::size_t IMAGE_NUMBEROF_DIRECTORY_ENTRIES_ = 16;
boost::dll::detail::WORD_ Magic;
boost::dll::detail::BYTE_ MajorLinkerVersion;
boost::dll::detail::BYTE_ MinorLinkerVersion;
boost::dll::detail::DWORD_ SizeOfCode;
boost::dll::detail::DWORD_ SizeOfInitializedData;
boost::dll::detail::DWORD_ SizeOfUninitializedData;
boost::dll::detail::DWORD_ AddressOfEntryPoint;
union {
boost::dll::detail::DWORD_ BaseOfCode;
unsigned char padding_[sizeof(AddressOffsetT) == 8 ? 4 : 8]; // in x64 version BaseOfData does not exist
} BaseOfCode_and_BaseOfData;
AddressOffsetT ImageBase;
boost::dll::detail::DWORD_ SectionAlignment;
boost::dll::detail::DWORD_ FileAlignment;
boost::dll::detail::WORD_ MajorOperatingSystemVersion;
boost::dll::detail::WORD_ MinorOperatingSystemVersion;
boost::dll::detail::WORD_ MajorImageVersion;
boost::dll::detail::WORD_ MinorImageVersion;
boost::dll::detail::WORD_ MajorSubsystemVersion;
boost::dll::detail::WORD_ MinorSubsystemVersion;
boost::dll::detail::DWORD_ Win32VersionValue;
boost::dll::detail::DWORD_ SizeOfImage;
boost::dll::detail::DWORD_ SizeOfHeaders;
boost::dll::detail::DWORD_ CheckSum;
boost::dll::detail::WORD_ Subsystem;
boost::dll::detail::WORD_ DllCharacteristics;
AddressOffsetT SizeOfStackReserve;
AddressOffsetT SizeOfStackCommit;
AddressOffsetT SizeOfHeapReserve;
AddressOffsetT SizeOfHeapCommit;
boost::dll::detail::DWORD_ LoaderFlags;
boost::dll::detail::DWORD_ NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY_ DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES_];
};
typedef IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::DWORD_> IMAGE_OPTIONAL_HEADER32_;
typedef IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::ULONGLONG_> IMAGE_OPTIONAL_HEADER64_;
template <class AddressOffsetT>
struct IMAGE_NT_HEADERS_template {
boost::dll::detail::DWORD_ Signature;
IMAGE_FILE_HEADER_ FileHeader;
IMAGE_OPTIONAL_HEADER_template<AddressOffsetT> OptionalHeader;
};
typedef IMAGE_NT_HEADERS_template<boost::dll::detail::DWORD_> IMAGE_NT_HEADERS32_;
typedef IMAGE_NT_HEADERS_template<boost::dll::detail::ULONGLONG_> IMAGE_NT_HEADERS64_;
template <class AddressOffsetT>
class pe_info: public x_info_interface {
boost::filesystem::ifstream& f_;
typedef IMAGE_NT_HEADERS_template<AddressOffsetT> header_t;
typedef IMAGE_EXPORT_DIRECTORY_ exports_t;
typedef IMAGE_SECTION_HEADER_ section_t;
typedef IMAGE_DOS_HEADER_ dos_t;
template <class T>
inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
f_.read(reinterpret_cast<char*>(&value), size);
}
public:
static bool parsing_supported(boost::filesystem::ifstream& f) {
dos_t dos;
f.seekg(0);
f.read(reinterpret_cast<char*>(&dos), sizeof(dos));
// 'MZ' and 'ZM' according to Wikipedia
if (dos.e_magic != 0x4D5A && dos.e_magic != 0x5A4D) {
return false;
}
header_t h;
f.seekg(dos.e_lfanew);
f.read(reinterpret_cast<char*>(&h), sizeof(h));
return h.Signature == 0x00004550 // 'PE00'
&& h.OptionalHeader.Magic == (sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 0x10B : 0x20B);
}
explicit pe_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
: f_(f)
{}
private:
inline header_t header() {
header_t h;
dos_t dos;
f_.seekg(0);
read_raw(dos);
f_.seekg(dos.e_lfanew);
read_raw(h);
return h;
}
inline exports_t exports(const header_t& h) {
exports_t exports;
static const unsigned int IMAGE_DIRECTORY_ENTRY_EXPORT_ = 0;
const std::size_t exp_virtual_address = h.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT_].VirtualAddress;
const std::size_t real_offset = get_file_offset(exp_virtual_address, h);
BOOST_ASSERT(real_offset);
f_.seekg(real_offset);
read_raw(exports);
return exports;
}
std::size_t get_file_offset(std::size_t virtual_address, const header_t& h) {
section_t image_section_header;
{ // f_.seekg to the beginning on section headers
dos_t dos;
f_.seekg(0);
read_raw(dos);
f_.seekg(dos.e_lfanew + sizeof(header_t));
}
for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
read_raw(image_section_header);
if (virtual_address >= image_section_header.VirtualAddress
&& virtual_address < image_section_header.VirtualAddress + image_section_header.SizeOfRawData)
{
return image_section_header.PointerToRawData + virtual_address - image_section_header.VirtualAddress;
}
}
return 0;
}
public:
std::vector<std::string> sections() {
std::vector<std::string> ret;
const header_t h = header();
ret.reserve(h.FileHeader.NumberOfSections);
// get names, e.g: .text .rdata .data .rsrc .reloc
section_t image_section_header;
char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1];
std::memset(name_helper, 0, sizeof(name_helper));
for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
// There is no terminating null character if the string is exactly eight characters long
read_raw(image_section_header);
std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
if (name_helper[0] != '/') {
ret.push_back(name_helper);
} else {
// For longer names, image_section_header.Name contains a slash (/) followed by ASCII representation of a decimal number.
// this number is an offset into the string table.
// TODO: fixme
ret.push_back(name_helper);
}
}
return ret;
}
std::vector<std::string> symbols() {
std::vector<std::string> ret;
const header_t h = header();
const exports_t exprt = exports(h);
const std::size_t exported_symbols = exprt.NumberOfNames;
const std::size_t fixed_names_addr = get_file_offset(exprt.AddressOfNames, h);
ret.reserve(exported_symbols);
boost::dll::detail::DWORD_ name_offset;
std::string symbol_name;
for (std::size_t i = 0;i < exported_symbols;++i) {
f_.seekg(fixed_names_addr + i * sizeof(name_offset));
read_raw(name_offset);
f_.seekg(get_file_offset(name_offset, h));
getline(f_, symbol_name, '\0');
ret.push_back(symbol_name);
}
return ret;
}
std::vector<std::string> symbols(const char* section_name) {
std::vector<std::string> ret;
const header_t h = header();
std::size_t section_begin_addr = 0;
std::size_t section_end_addr = 0;
{ // getting address range for the section
section_t image_section_header;
char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1];
std::memset(name_helper, 0, sizeof(name_helper));
for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
// There is no terminating null character if the string is exactly eight characters long
read_raw(image_section_header);
std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
if (!std::strcmp(section_name, name_helper)) {
section_begin_addr = image_section_header.PointerToRawData;
section_end_addr = section_begin_addr + image_section_header.SizeOfRawData;
}
}
// returning empty result if section was not found
if(section_begin_addr == 0 || section_end_addr == 0)
return ret;
}
const exports_t exprt = exports(h);
const std::size_t exported_symbols = exprt.NumberOfFunctions;
const std::size_t fixed_names_addr = get_file_offset(exprt.AddressOfNames, h);
const std::size_t fixed_ordinals_addr = get_file_offset(exprt.AddressOfNameOrdinals, h);
const std::size_t fixed_functions_addr = get_file_offset(exprt.AddressOfFunctions, h);
ret.reserve(exported_symbols);
boost::dll::detail::DWORD_ ptr;
boost::dll::detail::WORD_ ordinal;
std::string symbol_name;
for (std::size_t i = 0;i < exported_symbols;++i) {
// getting ordinal
f_.seekg(fixed_ordinals_addr + i * sizeof(ordinal));
read_raw(ordinal);
// getting function addr
f_.seekg(fixed_functions_addr + ordinal * sizeof(ptr));
read_raw(ptr);
ptr = static_cast<boost::dll::detail::DWORD_>( get_file_offset(ptr, h) );
if (ptr >= section_end_addr || ptr < section_begin_addr) {
continue;
}
f_.seekg(fixed_names_addr + i * sizeof(ptr));
read_raw(ptr);
f_.seekg(get_file_offset(ptr, h));
getline(f_, symbol_name, '\0');
ret.push_back(symbol_name);
}
return ret;
}
// a test method to get dependents modules,
// who my plugin imports (1st level only)
/*
e.g. for myself I get:
KERNEL32.dll
MSVCP110D.dll
boost_system-vc-mt-gd-1_56.dll
MSVCR110D.dll
*/
/*
std::vector<std::string> depend_of(boost::system::error_code &ec) BOOST_NOEXCEPT {
std::vector<std::string> ret;
IMAGE_DOS_HEADER* image_dos_header = (IMAGE_DOS_HEADER*)native();
if(!image_dos_header) {
// ERROR_BAD_EXE_FORMAT
ec = boost::system::error_code(
boost::system::errc::executable_format_error,
boost::system::generic_category()
);
return ret;
}
IMAGE_OPTIONAL_HEADER* image_optional_header = (IMAGE_OPTIONAL_HEADER*)((boost::dll::detail::BYTE_*)native() + image_dos_header->e_lfanew + 24);
if(!image_optional_header) {
// ERROR_BAD_EXE_FORMAT
ec = boost::system::error_code(
boost::system::errc::executable_format_error,
boost::system::generic_category()
);
return ret;
}
IMAGE_IMPORT_DESCRIPTOR* image_import_descriptor = (IMAGE_IMPORT_DESCRIPTOR*)((boost::dll::detail::BYTE_*)native() + image_optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if(!image_import_descriptor) {
// ERROR_BAD_EXE_FORMAT
ec = boost::system::error_code(
boost::system::errc::executable_format_error,
boost::system::generic_category()
);
return ret;
}
while(image_import_descriptor->FirstThunk) {
std::string module_name = reinterpret_cast<char*>((boost::dll::detail::BYTE_*)native() + image_import_descriptor->Name);
if(module_name.size()) {
ret.push_back(module_name);
}
image_import_descriptor++;
}
return ret;
}
*/
};
typedef pe_info<boost::dll::detail::DWORD_> pe_info32;
typedef pe_info<boost::dll::detail::ULONGLONG_> pe_info64;
}}} // namespace boost::dll::detail
#endif // BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
|