| 394 | } |
| 395 | |
| 396 | MappedModule::MappedModule(Logger logger, const std::vector<std::byte>& peBytes) : _mappedPe(Pe::ImgType::module, nullptr), _logger(logger) { |
| 397 | |
| 398 | auto pe = Pe::PeNative::fromFile(peBytes.data()); |
| 399 | |
| 400 | if (!pe.valid()) { |
| 401 | throw std::runtime_error("PE file is not valid"); |
| 402 | } |
| 403 | |
| 404 | //We try to allocate at the preferred base, this will save relocation later |
| 405 | _mappedImage = VirtualAlloc((LPVOID)(pe.headers().opt()->ImageBase), pe.imageSize(), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); |
| 406 | |
| 407 | //Preferred base was not available, so just allocate at any available address |
| 408 | if (_mappedImage == nullptr) { |
| 409 | _mappedImage = VirtualAlloc(nullptr, pe.imageSize(), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); |
| 410 | } |
| 411 | |
| 412 | _logger("Allocated image @ 0x%p\n", _mappedImage); |
| 413 | |
| 414 | if (_mappedImage == nullptr) { |
| 415 | throw std::bad_alloc(); |
| 416 | } |
| 417 | |
| 418 | try { |
| 419 | |
| 420 | //Wipe the mapped image space and copy the Pe headers across |
| 421 | memset(_mappedImage, 0, pe.imageSize()); |
| 422 | memcpy(_mappedImage, pe.base(), pe.headers().nt()->OptionalHeader.SizeOfHeaders); |
| 423 | |
| 424 | //Now map each section into it's correct RVA location, ignoring the .discard section |
| 425 | for (auto section : pe.sections()) { |
| 426 | if (section.PointerToRawData && strncmp((const char*)section.Name, ".discard", 8) != 0) { |
| 427 | memcpy(reinterpret_cast<void*>(uintptr_t(_mappedImage) + section.VirtualAddress), pe.byOffset<void*>(section.PointerToRawData), section.SizeOfRawData); |
| 428 | _logger("Copied section %.8s @ 0x%p\n", section.Name, PVOID(uintptr_t(_mappedImage) + section.VirtualAddress)); |
| 429 | } |
| 430 | else { |
| 431 | _logger("Skipped .discard section @ 0x%p\n", PVOID(uintptr_t(_mappedImage) + section.VirtualAddress)); |
| 432 | } |
| 433 | } |
| 434 | |
| 435 | //Now that we have laid out the PE in mapped form, |
| 436 | //Parse the PE from memory |
| 437 | _mappedPe = std::move(Pe::PeNative::fromModule(_mappedImage)); |
| 438 | |
| 439 | //If our mapped base address doesn't match the preferred base |
| 440 | //then process the reloc section |
| 441 | if (uintptr_t(_mappedImage) != pe.headers().opt()->ImageBase) { |
| 442 | ProcessRelocations(_mappedPe, uintptr_t(_mappedImage) - uintptr_t(pe.headers().opt()->ImageBase)); |
| 443 | _logger("Processed relocations\n"); |
| 444 | } |
| 445 | else { |
| 446 | _logger("Skipped relocations\n"); |
| 447 | } |
| 448 | |
| 449 | //Now process our import table, paying special attention to imports |
| 450 | //from beacon.dll |
| 451 | ProcessImports(_mappedPe); |
| 452 | _logger("Processed imports\n"); |
| 453 |
nothing calls this directly
no test coverage detected