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;
}