Esempio n. 1
0
void DumpStrings(hadesmem::Process const& process,
                 hadesmem::PeFile const& pe_file)
{
  std::wostream& out = GetOutputStreamW();

  std::uint8_t* const file_beg = static_cast<std::uint8_t*>(pe_file.GetBase());
  void* const file_end = file_beg + pe_file.GetSize();

  // TODO: Fix to not require multiple passes.

  WriteNewline(out);
  WriteNormal(out, L"Narrow Strings:", 1);
  WriteNewline(out);
  DumpStringsImpl(process, pe_file, file_beg, file_end, false);

  WriteNewline(out);
  WriteNormal(out, L"Wide Strings (Pass 1):", 1);
  WriteNewline(out);
  DumpStringsImpl(process, pe_file, file_beg, file_end, true);

  WriteNewline(out);
  WriteNormal(out, L"Wide Strings (Pass 2):", 1);
  WriteNewline(out);
  DumpStringsImpl(process, pe_file, file_beg + 1, file_end, true);
}
Esempio n. 2
0
void DumpPeFile(hadesmem::Process const& process,
                hadesmem::PeFile const& pe_file,
                std::wstring const& path)
{
  std::wostream& out = GetOutputStreamW();

  ClearWarnForCurrentFile();

  WriteNewline(out);
  std::wstring const architecture_str{pe_file.Is64() ? L"64-Bit File: Yes"
                                                     : L"64-Bit File: No"};
  WriteNormal(out, architecture_str, 1);

  std::uint32_t const k1MB = (1U << 20);
  std::uint32_t const k100MB = k1MB * 100;
  if (pe_file.GetSize() > k100MB)
  {
    // Not actually unsupported, just want to flag large files for use in perf
    // testing.
    WriteNewline(out);
    WriteNormal(out, L"WARNING! File is over 100MB.", 0);
    // WarnForCurrentFile(WarningType::kUnsupported);
  }

  DumpHeaders(process, pe_file);

  DumpSections(process, pe_file);

  DumpOverlay(process, pe_file);

  DumpTls(process, pe_file);

  DumpExports(process, pe_file);

  bool has_new_bound_imports_any = false;
  DumpImports(process, pe_file, has_new_bound_imports_any);

  DumpBoundImports(process, pe_file, has_new_bound_imports_any);

  DumpRelocations(process, pe_file);

  if (!g_quiet && g_strings)
  {
    DumpStrings(process, pe_file);
  }

  HandleWarnings(path);
}
Esempio n. 3
0
void DisassembleEp(hadesmem::Process const& process,
                   hadesmem::PeFile const& pe_file,
                   std::uintptr_t ep_rva,
                   void* ep_va,
                   std::size_t tabs)
{
  if (!ep_va)
  {
    return;
  }

  std::wostream& out = GetOutputStreamW();

  // Get the number of bytes from the EP to the end of the file.
  std::size_t max_buffer_size = GetBytesToEndOfFile(pe_file, ep_va);
  // Clamp the amount of data read to the theoretical maximum.
  std::size_t const kMaxInstructions = 10U;
  std::size_t const kMaxInstructionLen = 15U;
  std::size_t const kMaxInstructionsBytes =
    kMaxInstructions * kMaxInstructionLen;
  max_buffer_size = (std::min)(max_buffer_size, kMaxInstructionsBytes);
  auto const disasm_buf =
    hadesmem::ReadVector<std::uint8_t>(process, ep_va, max_buffer_size);
  std::uint64_t const ip = hadesmem::GetRuntimeBase(process, pe_file) + ep_rva;

  ud_t ud_obj;
  ud_init(&ud_obj);
  ud_set_input_buffer(&ud_obj, disasm_buf.data(), max_buffer_size);
  ud_set_syntax(&ud_obj, UD_SYN_INTEL);
  ud_set_pc(&ud_obj, ip);
  ud_set_mode(&ud_obj, pe_file.Is64() ? 64 : 32);

  // Be pessimistic. Use the minimum theoretical amount of instrutions we could
  // fit in our buffer.
  std::size_t const instruction_count = max_buffer_size / kMaxInstructionLen;
  for (std::size_t i = 0U; i < instruction_count; ++i)
  {
    std::uint32_t const len = ud_disassemble(&ud_obj);
    if (len == 0)
    {
      WriteNormal(out, L"WARNING! Disassembly failed.", tabs);
      // If we can't disassemble at least 5 instructions there's probably
      // something strange about the function. Even in the case of a nullsub
      // there is typically some INT3 or NOP padding after it...
      WarnForCurrentFile(i < 5U ? WarningType::kUnsupported
                                : WarningType::kSuspicious);
      break;
    }

    char const* const asm_str = ud_insn_asm(&ud_obj);
    HADESMEM_DETAIL_ASSERT(asm_str);
    char const* const asm_bytes_str = ud_insn_hex(&ud_obj);
    HADESMEM_DETAIL_ASSERT(asm_bytes_str);
    auto const diasm_line =
      hadesmem::detail::MultiByteToWideChar(asm_str) + L" (" +
      hadesmem::detail::MultiByteToWideChar(asm_bytes_str) + L")";
    WriteNormal(out, diasm_line, tabs);
  }
}
Esempio n. 4
0
void DumpPeFile(hadesmem::Process const& process,
                hadesmem::PeFile const& pe_file,
                std::wstring const& path)
{
  std::wostream& out = std::wcout;

  ClearWarnForCurrentFile();

  std::uint32_t const k1MB = (1U << 20);
  std::uint32_t const k100MB = k1MB * 100;
  if (pe_file.GetSize() > k100MB)
  {
    // Not actually unsupported, just want to flag large files.
    WriteNewline(out);
    WriteNormal(out, L"WARNING! File is over 100MB.", 0);
    WarnForCurrentFile(WarningType::kUnsupported);
  }

  DumpHeaders(process, pe_file);

  DumpSections(process, pe_file);

  DumpTls(process, pe_file);

  DumpExports(process, pe_file);

  bool has_new_bound_imports_any = false;
  DumpImports(process, pe_file, has_new_bound_imports_any);

  DumpBoundImports(process, pe_file, has_new_bound_imports_any);

  DumpRelocations(process, pe_file);

  DumpStrings(process, pe_file);

  HandleWarnings(path);
}
Esempio n. 5
0
void TestDosHeader()
{
  hadesmem::Process const process(::GetCurrentProcessId());

  hadesmem::PeFile pe_file_1(
    process, ::GetModuleHandleW(nullptr), hadesmem::PeFileType::Image, 0);

  hadesmem::DosHeader dos_header_1(process, pe_file_1);

  hadesmem::DosHeader dos_header_2(dos_header_1);
  BOOST_TEST_EQ(dos_header_1, dos_header_2);
  dos_header_1 = dos_header_2;
  BOOST_TEST_EQ(dos_header_1, dos_header_2);
  hadesmem::DosHeader dos_header_3(std::move(dos_header_2));
  BOOST_TEST_EQ(dos_header_3, dos_header_1);
  dos_header_2 = std::move(dos_header_3);
  BOOST_TEST_EQ(dos_header_1, dos_header_2);

  hadesmem::ModuleList modules(process);
  for (auto const& mod : modules)
  {
    hadesmem::PeFile const cur_pe_file(
      process, mod.GetHandle(), hadesmem::PeFileType::Image, 0);

    hadesmem::DosHeader cur_dos_header(process, cur_pe_file);

    auto const dos_header_raw =
      hadesmem::Read<IMAGE_DOS_HEADER>(process, cur_dos_header.GetBase());

    BOOST_TEST_EQ(cur_dos_header.IsValid(), true);
    cur_dos_header.EnsureValid();
    cur_dos_header.SetMagic(cur_dos_header.GetMagic());
    cur_dos_header.SetBytesOnLastPage(cur_dos_header.GetBytesOnLastPage());
    cur_dos_header.SetPagesInFile(cur_dos_header.GetPagesInFile());
    cur_dos_header.SetRelocations(cur_dos_header.GetRelocations());
    cur_dos_header.SetSizeOfHeaderInParagraphs(
      cur_dos_header.GetSizeOfHeaderInParagraphs());
    cur_dos_header.SetMinExtraParagraphs(
      cur_dos_header.GetMinExtraParagraphs());
    cur_dos_header.SetMaxExtraParagraphs(
      cur_dos_header.GetMaxExtraParagraphs());
    cur_dos_header.SetInitialSS(cur_dos_header.GetInitialSS());
    cur_dos_header.SetInitialSP(cur_dos_header.GetInitialSP());
    cur_dos_header.SetChecksum(cur_dos_header.GetChecksum());
    cur_dos_header.SetInitialIP(cur_dos_header.GetInitialIP());
    cur_dos_header.SetInitialCS(cur_dos_header.GetInitialCS());
    cur_dos_header.SetRelocTableFileAddr(
      cur_dos_header.GetRelocTableFileAddr());
    cur_dos_header.SetOverlayNum(cur_dos_header.GetOverlayNum());
    cur_dos_header.SetReservedWords1(cur_dos_header.GetReservedWords1());
    cur_dos_header.SetOEMID(cur_dos_header.GetOEMID());
    cur_dos_header.SetOEMInfo(cur_dos_header.GetOEMInfo());
    cur_dos_header.SetReservedWords2(cur_dos_header.GetReservedWords2());
    cur_dos_header.SetNewHeaderOffset(cur_dos_header.GetNewHeaderOffset());
    cur_dos_header.UpdateWrite();
    cur_dos_header.UpdateRead();

    auto const dos_header_raw_new =
      hadesmem::Read<IMAGE_DOS_HEADER>(process, cur_pe_file.GetBase());

    BOOST_TEST_EQ(
      std::memcmp(&dos_header_raw, &dos_header_raw_new, sizeof(dos_header_raw)),
      0);

    std::stringstream test_str_1;
    test_str_1.imbue(std::locale::classic());
    test_str_1 << cur_dos_header;
    std::stringstream test_str_2;
    test_str_2.imbue(std::locale::classic());
    test_str_2 << cur_dos_header.GetBase();
    BOOST_TEST_EQ(test_str_1.str(), test_str_2.str());
    if (mod.GetHandle() != ::GetModuleHandleW(L"ntdll"))
    {
      hadesmem::PeFile const pe_file_ntdll(
        process, ::GetModuleHandleW(L"ntdll"), hadesmem::PeFileType::Image, 0);
      hadesmem::DosHeader const dos_header_ntdll(process, pe_file_ntdll);
      std::stringstream test_str_3;
      test_str_3.imbue(std::locale::classic());
      test_str_3 << dos_header_ntdll.GetBase();
      BOOST_TEST_NE(test_str_1.str(), test_str_3.str());
    }
  }
}