1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : #include "syzygy/pe/pe_file.h"
15 :
16 : #include "base/file_util.h"
17 : #include "base/logging.h"
18 :
19 : namespace {
20 :
21 E : bool ReadAt(FILE* file, size_t pos, void* buf, size_t len) {
22 E : if (fseek(file, pos, SEEK_SET) != 0)
23 i : return false;
24 :
25 E : size_t read = fread(buf, 1, len, file);
26 E : if (read != len)
27 i : return false;
28 :
29 E : return true;
30 E : }
31 :
32 : } // namespace
33 :
34 : namespace pe {
35 :
36 : const size_t kInvalidSection = -1;
37 :
38 : using core::AbsoluteAddress;
39 : using core::FileOffsetAddress;
40 : using core::RelativeAddress;
41 :
42 : PEFile::PEFile()
43 : : dos_header_(NULL),
44 : nt_headers_(NULL),
45 E : section_headers_(NULL) {
46 E : }
47 :
48 E : PEFile::~PEFile() {
49 E : }
50 :
51 E : bool PEFile::Init(const base::FilePath& path) {
52 E : path_ = path;
53 E : FILE* file = file_util::OpenFile(path, "rb");
54 E : if (file == NULL) {
55 E : LOG(ERROR) << "Failed to open file " << path.value();
56 E : return false;
57 : }
58 :
59 E : bool success = ReadHeaders(file);
60 E : if (success)
61 E : success = ReadSections(file);
62 :
63 E : file_util::CloseFile(file);
64 :
65 E : return success;
66 E : }
67 :
68 E : void PEFile::GetSignature(Signature* signature) const {
69 E : DCHECK(signature != NULL);
70 E : DCHECK(nt_headers_ != NULL);
71 :
72 : // TODO(chrisha): Make GetSignature return a bool, and update all calling
73 : // sites.
74 E : base::FilePath abs_path(base::MakeAbsoluteFilePath(path_));
75 E : CHECK(!abs_path.empty());
76 :
77 E : signature->path = abs_path.value();
78 : signature->base_address =
79 E : AbsoluteAddress(nt_headers_->OptionalHeader.ImageBase);
80 E : signature->module_size = nt_headers_->OptionalHeader.SizeOfImage;
81 E : signature->module_time_date_stamp = nt_headers_->FileHeader.TimeDateStamp;
82 E : signature->module_checksum = nt_headers_->OptionalHeader.CheckSum;
83 E : }
84 :
85 E : bool PEFile::Contains(RelativeAddress rel, size_t len) const {
86 E : const ImageAddressSpace::Range range(rel, len);
87 E : return image_data_.FindContaining(range) != image_data_.ranges().end();
88 E : }
89 :
90 E : bool PEFile::Contains(AbsoluteAddress abs, size_t len) const {
91 E : RelativeAddress rel;
92 E : return Translate(abs, &rel) && Contains(rel, len);
93 E : }
94 :
95 E : size_t PEFile::GetSectionIndex(RelativeAddress rel, size_t len) const {
96 E : const ImageAddressSpace::Range range(rel, len);
97 : ImageAddressSpace::RangeMap::const_iterator it =
98 E : image_data_.FindContaining(range);
99 E : if (it == image_data_.ranges().end())
100 E : return kInvalidSection;
101 E : return it->second.id;
102 E : }
103 :
104 E : size_t PEFile::GetSectionIndex(AbsoluteAddress abs, size_t len) const {
105 E : RelativeAddress rel;
106 E : if (!Translate(abs, &rel))
107 E : return kInvalidSection;
108 E : return GetSectionIndex(rel, len);
109 E : }
110 :
111 : const IMAGE_SECTION_HEADER* PEFile::GetSectionHeader(
112 E : RelativeAddress rel, size_t len) const {
113 E : size_t id = GetSectionIndex(rel, len);
114 E : if (id == kInvalidSection)
115 E : return NULL;
116 E : DCHECK(id < nt_headers_->FileHeader.NumberOfSections);
117 E : return section_headers_ + id;
118 E : }
119 :
120 : const IMAGE_SECTION_HEADER* PEFile::GetSectionHeader(
121 E : AbsoluteAddress abs, size_t len) const {
122 E : RelativeAddress rel;
123 E : if (!Translate(abs, &rel))
124 i : return NULL;
125 E : return GetSectionHeader(rel, len);
126 E : }
127 :
128 E : size_t PEFile::GetSectionIndex(const char* name) const {
129 E : size_t section_count = nt_headers_->FileHeader.NumberOfSections;
130 E : for (size_t i = 0; i < section_count; ++i) {
131 E : const IMAGE_SECTION_HEADER* header = section_headers_ + i;
132 : if (strncmp(reinterpret_cast<const char*>(header->Name), name,
133 E : IMAGE_SIZEOF_SHORT_NAME) == 0)
134 E : return i;
135 E : }
136 E : return kInvalidSection;
137 E : }
138 :
139 : std::string PEFile::GetSectionName(
140 E : const IMAGE_SECTION_HEADER& section) {
141 E : const char* name = reinterpret_cast<const char*>(section.Name);
142 E : return std::string(name, strnlen(name, arraysize(section.Name)));
143 E : }
144 :
145 E : std::string PEFile::GetSectionName(size_t section_index) const {
146 E : DCHECK_LT(section_index, nt_headers_->FileHeader.NumberOfSections);
147 :
148 E : const IMAGE_SECTION_HEADER* section = section_headers_ + section_index;
149 E : return GetSectionName(*section);
150 E : }
151 :
152 E : const IMAGE_SECTION_HEADER* PEFile::GetSectionHeader(const char* name) const {
153 E : size_t id = GetSectionIndex(name);
154 E : if (id == kInvalidSection)
155 E : return NULL;
156 E : return section_headers_ + id;
157 E : }
158 :
159 E : bool PEFile::ReadHeaders(FILE* file) {
160 : // Read the DOS header.
161 E : IMAGE_DOS_HEADER dos_header = {};
162 E : if (!ReadAt(file, 0, &dos_header, sizeof(dos_header))) {
163 i : LOG(ERROR) << "Unable to read DOS header";
164 i : return false;
165 : }
166 :
167 : // And the NT headers.
168 E : IMAGE_NT_HEADERS nt_headers = {};
169 E : size_t pos = dos_header.e_lfanew;
170 E : if (!ReadAt(file, pos, &nt_headers, sizeof(nt_headers))) {
171 i : LOG(ERROR) << "Unable to read NT headers";
172 i : return false;
173 : }
174 :
175 : // We now know how large the headers are, so create a range for them.
176 E : size_t header_size = nt_headers.OptionalHeader.SizeOfHeaders;
177 E : ImageAddressSpace::Range header_range(RelativeAddress(0), header_size);
178 E : ImageAddressSpace::RangeMap::iterator it;
179 E : bool inserted = image_data_.Insert(header_range, SectionInfo(), &it);
180 E : DCHECK(inserted);
181 E : if (!inserted) {
182 i : LOG(ERROR) << "Unable to create header range";
183 i : return false;
184 : }
185 :
186 E : SectionBuffer& header = it->second.buffer;
187 E : header.resize(header_size);
188 E : if (!ReadAt(file, 0, &header[0], header_size)) {
189 i : LOG(ERROR) << "Unable to read header data";
190 i : return false;
191 : }
192 :
193 : // TODO(siggi): Validate these pointers!
194 E : dos_header_ = reinterpret_cast<IMAGE_DOS_HEADER*>(&header.at(0));
195 : nt_headers_ =
196 E : reinterpret_cast<IMAGE_NT_HEADERS*>(&header.at(dos_header_->e_lfanew));
197 E : section_headers_ = IMAGE_FIRST_SECTION(nt_headers_);
198 :
199 E : return true;
200 E : }
201 :
202 E : bool PEFile::ReadSections(FILE* file) {
203 E : DCHECK(nt_headers_ != NULL);
204 E : DCHECK(section_headers_ != NULL);
205 :
206 E : size_t num_sections = nt_headers_->FileHeader.NumberOfSections;
207 E : for (size_t i = 0; i < num_sections; ++i) {
208 E : const IMAGE_SECTION_HEADER* hdr = section_headers_ + i;
209 : // Insert the range for the new section.
210 : ImageAddressSpace::Range section_range(RelativeAddress(hdr->VirtualAddress),
211 E : hdr->Misc.VirtualSize);
212 E : ImageAddressSpace::RangeMap::iterator it;
213 E : if (!image_data_.Insert(section_range, SectionInfo(), &it)) {
214 i : LOG(ERROR) << "Unable to insert range for section " << hdr->Name;
215 i : return false;
216 : }
217 :
218 E : it->second.id = i;
219 E : SectionBuffer& buf = it->second.buffer;
220 E : if (hdr->SizeOfRawData == 0)
221 i : continue;
222 :
223 E : buf.resize(hdr->SizeOfRawData);
224 E : if (!ReadAt(file, hdr->PointerToRawData, &buf.at(0), hdr->SizeOfRawData)) {
225 i : LOG(ERROR) << "Unable to read data for section " << hdr->Name;
226 i : return false;
227 : }
228 E : }
229 :
230 E : return true;
231 E : }
232 :
233 E : bool PEFile::Translate(RelativeAddress rel, AbsoluteAddress* abs) const {
234 E : DCHECK(abs != NULL);
235 E : if (rel.value() >= nt_headers_->OptionalHeader.SizeOfImage)
236 E : return false;
237 E : abs->set_value(rel.value() + nt_headers_->OptionalHeader.ImageBase);
238 E : return true;
239 E : }
240 :
241 E : bool PEFile::Translate(AbsoluteAddress abs, RelativeAddress* rel) const {
242 E : DCHECK(rel != NULL);
243 E : uint32 rel_addr = AbsToRelDisplacement(abs.value());
244 E : if (rel_addr >= nt_headers_->OptionalHeader.SizeOfImage)
245 E : return false;
246 E : rel->set_value(rel_addr);
247 E : return true;
248 E : }
249 :
250 E : bool PEFile::Translate(FileOffsetAddress offs, RelativeAddress* rel) const {
251 E : DCHECK(rel != NULL);
252 :
253 : // The first "previous section" is the headers.
254 E : RelativeAddress previous_section_start(0);
255 E : FileOffsetAddress previous_section_file_start(0);
256 E : const IMAGE_SECTION_HEADER* previous_section = NULL;
257 E : for (size_t i = 0; i < nt_headers_->FileHeader.NumberOfSections; ++i) {
258 E : if (offs.value() < section_headers_[i].PointerToRawData)
259 E : break;
260 :
261 E : previous_section_start.set_value(section_headers_[i].VirtualAddress);
262 E : previous_section_file_start.set_value(section_headers_[i].PointerToRawData);
263 E : previous_section = section_headers_ + i;
264 E : }
265 :
266 E : size_t section_offset = offs - previous_section_file_start;
267 : if (previous_section != NULL &&
268 E : section_offset >= previous_section->SizeOfRawData) {
269 E : return false;
270 : }
271 :
272 E : *rel = previous_section_start + section_offset;
273 :
274 E : return true;
275 E : }
276 :
277 E : bool PEFile::Translate(RelativeAddress rel, FileOffsetAddress* offs) const {
278 E : DCHECK(offs != NULL);
279 :
280 : // In the headers?
281 E : if (rel.value() < section_header(0)->VirtualAddress) {
282 E : offs->set_value(rel.value());
283 E : return true;
284 : }
285 :
286 : // Find the section in which this address lies.
287 E : const IMAGE_SECTION_HEADER* section = GetSectionHeader(rel, 1);
288 E : if (section == NULL)
289 E : return false;
290 :
291 : // Calculate the offset of this address and ensure it can be expressed as
292 : // a file offset (lies in the explicit data part of the section, not the
293 : // implicit virtual data at the end).
294 E : size_t section_offset = rel.value() - section->VirtualAddress;
295 E : if (section_offset >= section->SizeOfRawData)
296 E : return false;
297 :
298 E : offs->set_value(section->PointerToRawData + section_offset);
299 :
300 E : return true;
301 E : }
302 :
303 E : const uint8* PEFile::GetImageData(RelativeAddress rel, size_t len) const {
304 E : DCHECK(nt_headers_ != NULL);
305 :
306 E : ImageAddressSpace::Range range(rel, len);
307 : ImageAddressSpace::RangeMap::const_iterator it(
308 E : image_data_.FindContaining(range));
309 :
310 E : if (it != image_data_.ranges().end()) {
311 E : ptrdiff_t offs = rel - it->first.start();
312 E : DCHECK_GE(offs, 0);
313 :
314 E : const SectionBuffer& buf = it->second.buffer;
315 E : if (offs + len <= buf.size())
316 E : return &buf.at(offs);
317 : }
318 :
319 E : return NULL;
320 E : }
321 :
322 E : const uint8* PEFile::GetImageData(AbsoluteAddress abs, size_t len) const {
323 E : RelativeAddress rel;
324 E : if (Translate(abs, &rel))
325 E : return GetImageData(rel, len);
326 :
327 i : return NULL;
328 E : }
329 :
330 E : uint8* PEFile::GetImageData(RelativeAddress rel, size_t len) {
331 : return const_cast<uint8*>(
332 E : static_cast<const PEFile*>(this)->GetImageData(rel, len));
333 E : }
334 :
335 E : uint8* PEFile::GetImageData(AbsoluteAddress abs, size_t len) {
336 : return const_cast<uint8*>(
337 E : static_cast<const PEFile*>(this)->GetImageData(abs, len));
338 E : }
339 :
340 E : bool PEFile::ReadImage(RelativeAddress rel, void* data, size_t len) const {
341 E : DCHECK(data != NULL);
342 E : const uint8* buf = GetImageData(rel, len);
343 E : if (buf == NULL)
344 i : return false;
345 :
346 E : memcpy(data, buf, len);
347 E : return true;
348 E : }
349 :
350 E : bool PEFile::ReadImage(AbsoluteAddress abs, void* data, size_t len) const {
351 E : RelativeAddress rel;
352 E : if (!Translate(abs, &rel))
353 i : return false;
354 :
355 E : return ReadImage(rel, data, len);
356 E : }
357 :
358 E : bool PEFile::ReadImageString(RelativeAddress rel, std::string* str) const {
359 E : DCHECK(nt_headers_ != NULL);
360 E : str->clear();
361 :
362 : // Locate the range that contains the first byte of the string.
363 E : ImageAddressSpace::Range range(rel, 1);
364 : ImageAddressSpace::RangeMap::const_iterator it(
365 E : image_data_.FindContaining(range));
366 :
367 E : if (it != image_data_.ranges().end()) {
368 E : ptrdiff_t offs = rel - it->first.start();
369 E : DCHECK_GE(offs, 0);
370 : // Stash the start position.
371 E : const SectionBuffer& buf = it->second.buffer;
372 E : const char* begin = reinterpret_cast<const char*>(&buf.at(offs));
373 : // And loop through until we find a zero-terminating byte,
374 : // or run off the end.
375 E : for (; static_cast<size_t>(offs) < buf.size() && buf.at(offs); ++offs) {
376 : // Intentionally empty.
377 E : }
378 :
379 E : if (static_cast<size_t>(offs) == buf.size())
380 i : return false;
381 :
382 E : str->assign(begin);
383 E : return true;
384 : }
385 :
386 i : return false;
387 E : }
388 :
389 E : bool PEFile::ReadImageString(AbsoluteAddress abs, std::string* str) const {
390 E : RelativeAddress rel;
391 E : if (!Translate(abs, &rel))
392 i : return false;
393 :
394 E : return ReadImageString(rel, str);
395 E : }
396 :
397 E : bool PEFile::DecodeRelocs(RelocSet* relocs) const {
398 E : DCHECK(nt_headers_ != NULL);
399 E : DCHECK(relocs != NULL);
400 :
401 : // Walk the relocs.
402 : IMAGE_DATA_DIRECTORY dir =
403 : nt_headers_->OptionalHeader.DataDirectory[
404 E : IMAGE_DIRECTORY_ENTRY_BASERELOC];
405 E : RelativeAddress offs(dir.VirtualAddress);
406 E : RelativeAddress end(offs + dir.Size);
407 :
408 E : const IMAGE_BASE_RELOCATION* hdr = NULL;
409 E : for (; offs < end; offs += hdr->SizeOfBlock) {
410 : // Read the next header.
411 : hdr = reinterpret_cast<const IMAGE_BASE_RELOCATION*>(
412 E : GetImageData(offs, sizeof(hdr)));
413 E : if (hdr == NULL) {
414 i : LOG(ERROR) << "Failed to read relocation block header.";
415 i : return false;
416 : }
417 :
418 : // Read the entries.
419 E : size_t num_relocs = (hdr->SizeOfBlock - sizeof(*hdr)) / sizeof(WORD);
420 : const WORD* reloc_block = reinterpret_cast<const WORD*>(
421 E : GetImageData(offs + sizeof(*hdr), sizeof(*reloc_block) * num_relocs));
422 E : if (reloc_block == NULL) {
423 i : LOG(ERROR) << "Failed to read relocation entries.";
424 i : return false;
425 : }
426 :
427 : // Walk the entries.
428 E : for (size_t i = 0; i < num_relocs; ++i) {
429 E : uint8 type = reloc_block[i] >> 12;
430 E : uint16 offs = reloc_block[i] & 0xFFF;
431 : DCHECK(type == IMAGE_REL_BASED_HIGHLOW ||
432 E : type == IMAGE_REL_BASED_ABSOLUTE);
433 :
434 E : if (type == IMAGE_REL_BASED_HIGHLOW) {
435 : // Record the entry.
436 E : relocs->insert(RelativeAddress(hdr->VirtualAddress) + offs);
437 : }
438 E : }
439 E : }
440 :
441 E : DCHECK(offs == end);
442 E : return true;
443 E : }
444 :
445 E : bool PEFile::ReadRelocs(const RelocSet& relocs, RelocMap* reloc_values) const {
446 E : RelocSet::const_iterator it(relocs.begin());
447 E : for (; it != relocs.end(); ++it) {
448 : const AbsoluteAddress* abs = reinterpret_cast<const AbsoluteAddress*>(
449 E : GetImageData(*it, sizeof(*abs)));
450 E : if (abs == NULL) {
451 i : LOG(ERROR) << "Failed to read reloc at " << it->value();
452 i : return false;
453 : }
454 :
455 E : reloc_values->insert(std::make_pair(*it, *abs));
456 E : }
457 :
458 E : return true;
459 E : }
460 :
461 E : bool PEFile::DecodeExports(ExportInfoVector* exports) const {
462 E : DCHECK(exports != NULL);
463 :
464 : IMAGE_DATA_DIRECTORY dir = nt_headers_->OptionalHeader.
465 E : DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
466 E : RelativeAddress addr(dir.VirtualAddress);
467 E : RelativeAddress end(addr + dir.Size);
468 :
469 E : if (addr.value() == 0)
470 i : return true;
471 :
472 : const IMAGE_EXPORT_DIRECTORY* export_dir =
473 : reinterpret_cast<const IMAGE_EXPORT_DIRECTORY*>(
474 E : GetImageData(addr, sizeof(export_dir)));
475 E : if (export_dir == NULL) {
476 i : LOG(ERROR) << "Unable to read export directory";
477 i : return false;
478 : }
479 :
480 : const RelativeAddress* functions =
481 : reinterpret_cast<const RelativeAddress*>(
482 : GetImageData(RelativeAddress(export_dir->AddressOfFunctions),
483 E : sizeof(*functions) * export_dir->NumberOfFunctions));
484 E : if (functions == NULL) {
485 i : LOG(ERROR) << "Unable to read export functions.";
486 i : return false;
487 : }
488 :
489 : const RelativeAddress* names =
490 : reinterpret_cast<const RelativeAddress*>(
491 : GetImageData(RelativeAddress(export_dir->AddressOfNames),
492 E : sizeof(*functions) * export_dir->NumberOfNames));
493 E : if (names == NULL) {
494 i : LOG(ERROR) << "Unable to read export names.";
495 i : return false;
496 : }
497 :
498 : const WORD* name_ordinals =
499 : reinterpret_cast<const WORD*>(
500 : GetImageData(RelativeAddress(export_dir->AddressOfNameOrdinals),
501 E : sizeof(*functions) * export_dir->NumberOfNames));
502 E : if (names == NULL) {
503 i : LOG(ERROR) << "Unable to read name ordinals.";
504 i : return false;
505 : }
506 :
507 E : for (size_t index = 0; index < export_dir->NumberOfFunctions; ++index) {
508 : // Is it a blank entry?
509 E : if (functions[index] != RelativeAddress(0)) {
510 E : ExportInfo info;
511 E : info.ordinal = index + 1;
512 :
513 E : RelativeAddress function = functions[index];
514 : // Is it a forward?
515 E : if (function >= addr && function < end) {
516 E : if (!ReadImageString(function, &info.forward)) {
517 i : LOG(ERROR) << "Unable to read export forward string";
518 i : return false;
519 : }
520 E : } else {
521 E : info.function = function;
522 : }
523 :
524 : // Does it have a name?
525 E : for (size_t i = 0; i < export_dir->NumberOfNames; ++i) {
526 E : if (name_ordinals[i] == index) {
527 E : if (!ReadImageString(names[i], &info.name)) {
528 i : LOG(ERROR) << "Unable to read export name";
529 i : return false;
530 : }
531 E : break;
532 : }
533 E : }
534 :
535 E : exports->push_back(info);
536 E : }
537 E : }
538 :
539 E : return true;
540 E : }
541 :
542 E : bool PEFile::DecodeImports(ImportDllVector* imports) const {
543 E : DCHECK(imports != NULL);
544 :
545 : // Walk the import thunks.
546 : IMAGE_DATA_DIRECTORY dir = nt_headers_->OptionalHeader.
547 E : DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
548 E : RelativeAddress offs(dir.VirtualAddress);
549 E : RelativeAddress end(offs + dir.Size);
550 :
551 E : const IMAGE_IMPORT_DESCRIPTOR* import_desc = NULL;
552 E : for (; offs < end; offs += sizeof(*import_desc)) {
553 : import_desc = reinterpret_cast<const IMAGE_IMPORT_DESCRIPTOR*>(
554 E : GetImageData(offs, sizeof(*import_desc)));
555 E : if (import_desc == NULL) {
556 i : LOG(ERROR) << "Unable to read import descriptor";
557 i : return false;
558 : }
559 :
560 E : if (import_desc->Characteristics == 0 && import_desc->FirstThunk == 0) {
561 : // This is the last chunk, bail the loop.
562 E : break;
563 : }
564 :
565 E : std::string dll_name;
566 E : if (!ReadImageString(RelativeAddress(import_desc->Name), &dll_name)) {
567 i : LOG(ERROR) << "Unable to read import descriptor name";
568 i : return false;
569 : }
570 :
571 : // Iterate the Import Name Table and the Import Address Table
572 : // concurrently. They will yield, respectively, the name of the
573 : // function and the address of the entry.
574 E : RelativeAddress int_offs(import_desc->OriginalFirstThunk);
575 E : RelativeAddress iat_offs(import_desc->FirstThunk);
576 :
577 E : imports->push_back(ImportDll());
578 E : ImportDll& dll = imports->back();
579 E : dll.name = dll_name;
580 E : dll.desc = *import_desc;
581 :
582 E : while (true) {
583 E : IMAGE_THUNK_DATA int_thunk = {};
584 E : IMAGE_THUNK_DATA iat_thunk = {};
585 :
586 : if (!ReadImage(int_offs, &int_thunk, sizeof(int_thunk)) ||
587 E : !ReadImage(iat_offs, &iat_thunk, sizeof(iat_thunk))) {
588 i : LOG(ERROR) << "Unable to read import name or address table thunk";
589 i : return false;
590 : }
591 :
592 : // Are we at the end of the table?
593 E : if (int_thunk.u1.Function == 0) {
594 E : DCHECK_EQ(0U, iat_thunk.u1.Function);
595 E : break;
596 : }
597 :
598 E : uint16 hint = 0;
599 E : uint16 ordinal = 0;
600 E : std::string function_name;
601 E : if (int_thunk.u1.AddressOfData & IMAGE_ORDINAL_FLAG32) {
602 : // It's an ordinal.
603 E : ordinal = IMAGE_ORDINAL32(int_thunk.u1.Ordinal);
604 E : } else {
605 : // Read the hint word, followed by the function name.
606 E : RelativeAddress import_name(int_thunk.u1.AddressOfData);
607 : if (!ReadImage(import_name, &hint, sizeof(hint)) ||
608 E : !ReadImageString(import_name + sizeof(hint), &function_name)) {
609 i : LOG(ERROR) << "Unable to read import function hint or name";
610 i : return false;
611 : }
612 : }
613 :
614 E : dll.functions.push_back(ImportInfo());
615 E : ImportInfo& info = dll.functions.back();
616 E : info.function = function_name;
617 E : info.ordinal = ordinal;
618 E : info.hint = hint;
619 :
620 E : int_offs += sizeof(int_thunk);
621 E : iat_offs += sizeof(iat_thunk);
622 E : }
623 E : }
624 :
625 E : return true;
626 E : }
627 :
628 E : bool PEFile::Signature::IsConsistent(const Signature& signature) const {
629 : return IsConsistentExceptForChecksum(signature) &&
630 E : module_checksum == signature.module_checksum;
631 E : }
632 :
633 : bool PEFile::Signature::IsConsistentExceptForChecksum(
634 E : const Signature& signature) const {
635 : return base_address == signature.base_address &&
636 : module_size == signature.module_size &&
637 E : module_time_date_stamp == signature.module_time_date_stamp;
638 E : }
639 :
640 E : bool PEFile::Signature::Save(core::OutArchive* out_archive) const {
641 : return out_archive->Save(path) &&
642 : out_archive->Save(base_address) &&
643 : out_archive->Save(module_size) &&
644 : out_archive->Save(module_time_date_stamp) &&
645 E : out_archive->Save(module_checksum);
646 E : }
647 :
648 E : bool PEFile::Signature::Load(core::InArchive* in_archive) {
649 : return in_archive->Load(&path) &&
650 : in_archive->Load(&base_address) &&
651 : in_archive->Load(&module_size) &&
652 : in_archive->Load(&module_time_date_stamp) &&
653 E : in_archive->Load(&module_checksum);
654 E : }
655 :
656 : } // namespace pe
|