他人の空似自作物置場

print_dll_info.zip/print_dll_info/main.cpp


#include <iostream>

#include <Windows.h>

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp>
#include <boost/range/irange.hpp>

const IMAGE_DOS_HEADER *getMz(const unsigned char * const data) {
  return reinterpret_cast<const IMAGE_DOS_HEADER *>(data);
}

const IMAGE_NT_HEADERS32 *getPe(const unsigned char * const data, const IMAGE_DOS_HEADER &mz) {
  return reinterpret_cast<const IMAGE_NT_HEADERS32 *>(data + mz.e_lfanew);
}

const IMAGE_SECTION_HEADER *getSectionHeader(const unsigned char * const data, const IMAGE_DOS_HEADER &mz, const IMAGE_NT_HEADERS32 &pe) {
  return reinterpret_cast<const IMAGE_SECTION_HEADER *>(
    data
    + mz.e_lfanew
    + sizeof(IMAGE_NT_HEADERS32) - sizeof(IMAGE_OPTIONAL_HEADER32)
    + pe.FileHeader.SizeOfOptionalHeader);
}

bool LoadImage(const boost::filesystem::path &path, std::vector<unsigned char> &out) {
  if (!boost::filesystem::exists(path)) {
    return false;
  }
  boost::filesystem::ifstream ifs(path, std::ios::binary);
  if (!ifs.is_open()) {
    return false;
  }

  // MZヘッダーの読み込み
  out.resize(sizeof(IMAGE_DOS_HEADER));
  ifs.read(reinterpret_cast<char*>(&out.front()), out.size());
  const IMAGE_DOS_HEADER *mz = getMz(&out.front());
  if (!ifs.good() || mz->e_magic != 0x5A4D) {
    return false;
  }

  // PEヘッダーの読み込み
  out.resize(mz->e_lfanew + sizeof(IMAGE_NT_HEADERS32) - sizeof(IMAGE_OPTIONAL_HEADER32));
  mz = getMz(&out.front());
  ifs.seekg(0, std::ios::beg);
  ifs.read(reinterpret_cast<char*>(&out.front()), out.size());
  const IMAGE_NT_HEADERS32 *pe = getPe(&out.front(), *mz);
  if (!ifs.good() || pe->Signature != 0x00004550) {
    return false;
  }

  // PEオプショナルヘッダーからセクションリストまでの読み込み
  out.resize(
    mz->e_lfanew
    + sizeof(IMAGE_NT_HEADERS32) - sizeof(IMAGE_OPTIONAL_HEADER32)
    + pe->FileHeader.SizeOfOptionalHeader
    + sizeof(IMAGE_SECTION_HEADER) * pe->FileHeader.NumberOfSections);
  mz = getMz(&out.front());
  pe = getPe(&out.front(), *mz);
  ifs.seekg(0, std::ios::beg);
  ifs.read(reinterpret_cast<char*>(&out.front()), out.size());
  if (!ifs.good()) {
    return false;
  }

  // セクションの読み込み
  const IMAGE_SECTION_HEADER *sectionList = getSectionHeader(&out.front(), *mz, *pe);
  for (unsigned int i = 0; i < pe->FileHeader.NumberOfSections; i++) {
    if (sectionList[i].Misc.VirtualSize == 0) {
      continue;
    }
    if (out.size() < sectionList[i].VirtualAddress + sectionList[i].Misc.VirtualSize) {
      out.resize(sectionList[i].VirtualAddress + sectionList[i].Misc.VirtualSize);
      mz = getMz(&out.front());
      pe = getPe(&out.front(), *mz);
      sectionList = getSectionHeader(&out.front(), *mz, *pe);
    }
    ifs.seekg(sectionList[i].PointerToRawData, std::ios::beg);
    ifs.read(reinterpret_cast<char*>(&out[sectionList[i].VirtualAddress]), (std::min)(sectionList[i].Misc.VirtualSize, sectionList[i].SizeOfRawData));
    if (!ifs.good()) {
      return false;
    }
  }
  return true;
}

std::wstring getDataDirectoryName(const unsigned int index) {
  switch (index) {
#define MACRO(NAME) case NAME: return L#NAME
  MACRO(IMAGE_DIRECTORY_ENTRY_EXPORT);
  MACRO(IMAGE_DIRECTORY_ENTRY_IMPORT);
  MACRO(IMAGE_DIRECTORY_ENTRY_RESOURCE);
  MACRO(IMAGE_DIRECTORY_ENTRY_EXCEPTION);
  MACRO(IMAGE_DIRECTORY_ENTRY_SECURITY);
  MACRO(IMAGE_DIRECTORY_ENTRY_BASERELOC);
  MACRO(IMAGE_DIRECTORY_ENTRY_DEBUG);
  MACRO(IMAGE_DIRECTORY_ENTRY_ARCHITECTURE);
  MACRO(IMAGE_DIRECTORY_ENTRY_GLOBALPTR);
  MACRO(IMAGE_DIRECTORY_ENTRY_TLS);
  MACRO(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
  MACRO(IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT);
  MACRO(IMAGE_DIRECTORY_ENTRY_IAT);
  MACRO(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
  MACRO(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
#undef MACRO
  default:
    return (boost::wformat(L"UNKNOWN_%d") % index).str();
  }
}

bool ExeParse(const boost::filesystem::path &path) {
  if (!boost::filesystem::exists(path)) {
    std::cout << "ファイルが見つかりませんでした\n";
    return false;
  }

  std::vector<unsigned char> image;
  if (!LoadImage(path, image)) {
    std::cout << "ファイルを開けないか、実行可能形式ファイルではありません\n";
    return false;
  }
  const unsigned char * const baseAddr = &image.front();
  const IMAGE_DOS_HEADER &mz = *getMz(baseAddr);
  const IMAGE_NT_HEADERS32 &pe = *getPe(baseAddr, mz);

  std::wcout << boost::wformat(L"ImageBase: %08x\n") % pe.OptionalHeader.ImageBase;

  const unsigned int dataDirectoriesCount =
    (
    pe.FileHeader.SizeOfOptionalHeader
    - (sizeof(IMAGE_OPTIONAL_HEADER32) - sizeof(IMAGE_DATA_DIRECTORY) * _countof(IMAGE_OPTIONAL_HEADER32::DataDirectory))
    ) / sizeof(IMAGE_DATA_DIRECTORY);
  std::wcout << boost::wformat(L"data directories count: %d\n") % dataDirectoriesCount;
  for (const unsigned int i : boost::irange(0U, dataDirectoriesCount)) {
    const IMAGE_DATA_DIRECTORY &dir = pe.OptionalHeader.DataDirectory[i];
    std::wcout << boost::wformat(L"%2$08x %3$08x %1$s\n") % getDataDirectoryName(i) % dir.VirtualAddress % dir.Size;
  }

  const unsigned int sectionCount = static_cast<unsigned int>(pe.FileHeader.NumberOfSections);
  std::wcout << boost::wformat(L"section count: %d\n") % sectionCount;
  const IMAGE_SECTION_HEADER * const sectionList = getSectionHeader(baseAddr, mz, pe);
  for (const unsigned int i : boost::irange(0U, sectionCount)) {
    const IMAGE_SECTION_HEADER &section = sectionList[i];
    std::cout << boost::format("%2$08x %3$08x %1$s\n")
      % std::string(&section.Name[0], &section.Name[_countof(section.Name)])
      % section.VirtualAddress
      % section.SizeOfRawData;
  }

  if (pe.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size != 0) {
    const IMAGE_DATA_DIRECTORY &loadConfigDir = pe.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
    const IMAGE_LOAD_CONFIG_DIRECTORY32 &loadConfig = *reinterpret_cast<const IMAGE_LOAD_CONFIG_DIRECTORY32 *>(baseAddr + loadConfigDir.VirtualAddress);
    std::wcout << boost::wformat(L"load config size: %d\n") % loadConfig.Size;
    if (loadConfig.Size >= 0x5C) {
      std::wcout << boost::wformat(L"  ptr:   %08x\n") % loadConfig.GuardCFCheckFunctionPointer;
      std::wcout << boost::wformat(L"  table: %08x\n") % loadConfig.GuardCFFunctionTable;
      std::wcout << boost::wformat(L"  count: %08x\n") % loadConfig.GuardCFFunctionCount;
      std::wcout << boost::wformat(L"  flag:  %08x\n") % loadConfig.GuardFlags;
      if ((loadConfig.GuardFlags & IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT) != 0) {
        std::wcout << boost::wformat(L"  dump table:\n");
        const unsigned int * const funcPtr = reinterpret_cast<const unsigned int *>(baseAddr + loadConfig.GuardCFFunctionTable - pe.OptionalHeader.ImageBase);
        for (const unsigned int i : boost::irange(0U, static_cast<unsigned int>(loadConfig.GuardCFFunctionCount))) {
          std::wcout << boost::wformat(L"%08x ") % funcPtr[i];
        }
      }
    }
  }
  return true;
}

int main(const unsigned int argc, const char * const * argv) {
  if (argc != 2) {
    std::wcout << boost::wformat(L"usage: %s path") % boost::filesystem::path(argv[0]).filename().wstring();
    return 1;
  }
  return ExeParse(argv[1]) ? 0 : 1;
}