他人の空似自作物置場

dll_import_list.zip/dll_import_list/main.cpp


#include <iostream>

#include <Windows.h>

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

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

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

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

template<typename NT_HEADER, WORD MAGIC>
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()) {
      return false;
   }

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

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

   if (pe->OptionalHeader.Magic != MAGIC) {
      return false;
   }

   // セクションの読み込み
   const IMAGE_SECTION_HEADER *sectionList = getSectionHeader<NT_HEADER>(&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<NT_HEADER>(&out.front(), *mz);
         sectionList = getSectionHeader<NT_HEADER>(&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;
}

template<typename NT_HEADER, WORD MAGIC>
bool ExeParse(const boost::filesystem::path &path) {
   if (!boost::filesystem::exists(path)) {
      return false;
   }

   std::vector<unsigned char> image;
   if (!LoadImage<NT_HEADER, MAGIC>(path, image)) {
      return false;
   }
   const unsigned char * const baseAddr = &image.front();


   const IMAGE_DOS_HEADER &mz = *getMz(baseAddr);
   const NT_HEADER &pe = *getPe<NT_HEADER>(baseAddr, mz);
   const IMAGE_DATA_DIRECTORY &dir = pe.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
   if (dir.Size == 0) {
      return false;
   }

   const IMAGE_IMPORT_DESCRIPTOR *desc = reinterpret_cast<const IMAGE_IMPORT_DESCRIPTOR *>(baseAddr + dir.VirtualAddress);
   for (; desc->FirstThunk != NULL; desc++) {
      const char * const dllName = reinterpret_cast<const char *>(baseAddr + desc->Name);
      std::cout << boost::format("%s\n") % dllName;
      const unsigned int *thunk = reinterpret_cast<const unsigned int *>(baseAddr + desc->FirstThunk);
      for (; *thunk != NULL; thunk++) {
         if ((*thunk & 0x80000000) != 0) {
            std::cout << boost::format("\t@%d\n") % (*thunk - 0x80000000);
            continue;
         }
         const char * const funcName = reinterpret_cast<const char *>(baseAddr + *thunk + 2);
         std::cout << boost::format("\t%s\n") % funcName;
      }
   }
   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;
   }
   if (!ExeParse<IMAGE_NT_HEADERS32, IMAGE_NT_OPTIONAL_HDR32_MAGIC>(argv[1]) && !ExeParse<IMAGE_NT_HEADERS64, IMAGE_NT_OPTIONAL_HDR64_MAGIC>(argv[1])) {
      std::cout << "ファイルを開けないか、実行可能形式ファイルではありません\n";
      return 1;
   }
   return 0;
}