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 §ion = 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;
}