他人の空似自作物置場

CallerCheck_SimExec.zip/Tools/SearchROPSensitiveFunctions/main.cpp


#include <iostream>
#include <string>
#include <map>
#include <utility>

#include <Windows.h>

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

#pragma comment(lib, "OneCore_downlevel.lib")

std::vector<std::pair<std::string, unsigned int> > LoadEAT(HMODULE module) {
   const unsigned char* const baseAddr = reinterpret_cast<unsigned char*>(module == NULL ? ::GetModuleHandleW(NULL) : module);
   const IMAGE_DOS_HEADER& mz = *reinterpret_cast<const IMAGE_DOS_HEADER*>(baseAddr);
   const IMAGE_NT_HEADERS32& pe = *reinterpret_cast<const IMAGE_NT_HEADERS32*>(baseAddr + mz.e_lfanew);
   const IMAGE_EXPORT_DIRECTORY& dir = *reinterpret_cast<const IMAGE_EXPORT_DIRECTORY*>(baseAddr + pe.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
   const unsigned int * const funcs = reinterpret_cast<const unsigned int *>(baseAddr + dir.AddressOfFunctions);
   const unsigned int * const names = reinterpret_cast<const unsigned int *>(baseAddr + dir.AddressOfNames);
   const unsigned short * const ordinals = reinterpret_cast<const unsigned short *>(baseAddr + dir.AddressOfNameOrdinals);
   std::map<unsigned int, std::string> ordinalNameMap;
   for (const unsigned int index : boost::irange(0U, static_cast<unsigned int>(dir.NumberOfNames))) {
      const unsigned int ordinal = ordinals[index];
      const std::string name = reinterpret_cast<const char *>(baseAddr + names[index]);
      ordinalNameMap[ordinal] = name;
   }
   std::vector<std::pair<std::string, unsigned int> > result;
   for (const unsigned int index : boost::irange(0U, static_cast<unsigned int>(dir.NumberOfFunctions))) {
      const unsigned int func = reinterpret_cast<unsigned int>(baseAddr) + funcs[index];
      std::string name;
      if (!ordinalNameMap.contains(index)) {
         name = (boost::format("@%d") % index).str();
      } else {
         name = ordinalNameMap[index];
      }
      result.push_back(std::make_pair(name, func));
   }
   return result;
}

std::pair<unsigned int, unsigned int> getTextArea(HMODULE module) {
   const unsigned char* const baseAddr = reinterpret_cast<unsigned char*>(module == NULL ? ::GetModuleHandleW(NULL) : module);
   const IMAGE_DOS_HEADER &mz = *reinterpret_cast<const IMAGE_DOS_HEADER*>(baseAddr);
   const IMAGE_NT_HEADERS32 &pe = *reinterpret_cast<const IMAGE_NT_HEADERS32*>(baseAddr + mz.e_lfanew);
   const IMAGE_SECTION_HEADER * const sectionHeaders = reinterpret_cast<const IMAGE_SECTION_HEADER *>(pe.FileHeader.SizeOfOptionalHeader + reinterpret_cast<unsigned int>(&pe.OptionalHeader));
   for (const unsigned int i : boost::irange(0U, static_cast<unsigned int>(pe.FileHeader.NumberOfSections))) {
      const IMAGE_SECTION_HEADER &section = sectionHeaders[i];
      if (reinterpret_cast<const char *>(section.Name) == std::string(".text")) {
         return std::make_pair(
            reinterpret_cast<unsigned int>(baseAddr + section.VirtualAddress),
            reinterpret_cast<unsigned int>(baseAddr + section.VirtualAddress + section.SizeOfRawData));
      }
   }
   return {};
}

void search(const char * const name) {
   const HMODULE module = ::GetModuleHandleA(name);
   const std::pair<unsigned int, unsigned int> area = getTextArea(module);
   std::cout << boost::format("%s:\n") % name;
   for (const auto item : LoadEAT(module)) {
      if (0xE9 != *reinterpret_cast<const unsigned char *>(item.second)) {
         continue;
      }
      const unsigned int addr = item.second + 5 + *reinterpret_cast<const unsigned int *>(item.second + 1);
      if (area.first <= addr && addr < area.second) {
         continue;
      }
      std::cout << boost::format("   %s\n") % item.first;
   }
}

int main() {
   search("ntdll.dll");
   search("kernel32.dll");
   search("kernelbase.dll");
   std::cin.get();
   return 0;
}