他人の空似自作物置場

ExportAddressFiltering.zip/NoGuard/main.cpp


#include <string>
#include <map>

#include <Windows.h>

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

// Pretending to be unauthorized access
unsigned int readDWORD(const void * const addr) {
   unsigned char code[] = {
      0x3E, 0x8B, 0x44, 0x24, 0x04, // MOV EAX, DWORD PTR DS:[ESP+4]
      0x8B, 0x00,                   // MOV EAX, DWORD PTR DS:[EAX]
      0xC2, 0x04, 0x00              // RETN 4
   };
   DWORD oldProtect;
   ::VirtualProtect(code, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtect);
   const unsigned int result = reinterpret_cast<unsigned int (__stdcall *)(const void *)>(&code)(addr);
   ::VirtualProtect(code, sizeof(code), oldProtect, &oldProtect);
   return result;
}
unsigned short readWORD(const void * const addr) {
   unsigned char code[] = {
      0x3E, 0x8B, 0x44, 0x24, 0x04, // MOV EAX, DWORD PTR DS:[ESP+4]
      0x66, 0x8B, 0x00,             // MOV AX, WORD PTR DS:[EAX]
      0xC2, 0x04, 0x00              // RETN 4
   };
   DWORD oldProtect;
   ::VirtualProtect(code, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtect);
   const unsigned short result = reinterpret_cast<unsigned short (__stdcall *)(const void *)>(&code)(addr);
   ::VirtualProtect(code, sizeof(code), oldProtect, &oldProtect);
   return result;
}
unsigned char readBYTE(const void * const addr) {
   unsigned char code[] = {
      0x3E, 0x8B, 0x44, 0x24, 0x04, // MOV EAX, DWORD PTR DS:[ESP+4]
      0x8A, 0x00,                   // MOV AL, BYTE PTR DS:[EAX]
      0xC2, 0x04, 0x00              // RETN 4
   };
   DWORD oldProtect;
   ::VirtualProtect(code, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtect);
   const unsigned char result = reinterpret_cast<unsigned char (__stdcall *)(const void *)>(&code)(addr);
   ::VirtualProtect(code, sizeof(code), oldProtect, &oldProtect);
   return result;
}
std::string readString(const void * const addr) {
   char buf[256];
   buf[_countof(buf) - 1] = '\0';
   for (unsigned int i = 0; i < _countof(buf) - 1; i++) {
      buf[i] = readBYTE(reinterpret_cast<const unsigned char *>(addr) + i);
      if (buf[i] == '\0') {
         break;
      }
   }
   return buf;
}

std::map<std::string, unsigned int> ParseEAT(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 + readDWORD(&mz.e_lfanew));
   const IMAGE_EXPORT_DIRECTORY& dir = *reinterpret_cast<const IMAGE_EXPORT_DIRECTORY*>(
      baseAddr
      + readDWORD(&pe.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
   const unsigned int * const funcs = reinterpret_cast<const unsigned int *>(baseAddr + readDWORD(&dir.AddressOfFunctions));
   const unsigned int * const names = reinterpret_cast<const unsigned int *>(baseAddr + readDWORD(&dir.AddressOfNames));
   const unsigned short * const ordinals = reinterpret_cast<const unsigned short *>(baseAddr + readDWORD(&dir.AddressOfNameOrdinals));
   std::map<unsigned int, std::string> ordinalNameMap;
   for (unsigned int index = 0; index < readDWORD(&dir.NumberOfNames); index++) {
      const unsigned int ordinal = readWORD(&ordinals[index]);
      ordinalNameMap[ordinal] = readString(reinterpret_cast<const char *>(baseAddr + readDWORD(&names[index])));
   }
   std::map<std::string, unsigned int> result;
   for (unsigned int index = 0; index < readDWORD(&dir.NumberOfFunctions); index++) {
      const unsigned int func = reinterpret_cast<unsigned int>(baseAddr) + readDWORD(&funcs[index]);
      if (!ordinalNameMap.contains(index)) {
         continue;
      }
      result[ordinalNameMap[index]] = func;
   }
   return result;
}

int main() {
   const auto WinExec = reinterpret_cast<UINT (__stdcall *)(LPCSTR, UINT)>(ParseEAT(::GetModuleHandleA("kernel32.dll"))["WinExec"]);
   WinExec("calc.exe", SW_SHOW);
   return 0;
}