#define WIN32_LEAN_AND_MEAN #include #include #include #include #include static unsigned char *client; static const char *clientPath="WoW.exe"; static HMODULE WINAPI TestGetModuleHandleA(LPCSTR name) { return name ? GetModuleHandleA(name) : (HMODULE)client; } static DWORD WINAPI TestGetModuleFileNameA(HMODULE module, LPSTR dest, DWORD length) { if (module) return GetModuleFileNameA(module,dest,length); if(strlen(clientPath)+1>length)return 0; strcpy(dest,clientPath); return (DWORD)strlen(dest); } #define GetModuleHandleA TestGetModuleHandleA #define GetModuleFileNameA TestGetModuleFileNameA #include "../native/LockPort.c" #undef GetModuleHandleA #undef GetModuleFileNameA static LuaFunction versionAPI, summonAPI; static int registrations, originalCalls, executions, booleanValue, topRestores; static const char *inputUnit; static char versionValue[32]; static void __stdcall FakeOriginal(void) { originalCalls++; } static void __fastcall FakeRegister(const char *name,LuaFunction fn) { if(!strcmp(name,"GetLockPortVersion"))versionAPI=fn; else if(!strcmp(name,"LockPortNativeSummon"))summonAPI=fn; else assert(0); registrations++; } static const char *__fastcall FakeToString(void *s,int index) { (void)s;assert(index==1);return inputUnit; } static void __fastcall FakePushString(void *s,const char *text) { (void)s;strcpy(versionValue,text); } static void __fastcall FakePushBoolean(void *s,int b) { (void)s;booleanValue=b; } static int __fastcall FakeGetTop(void *s) { (void)s;return 1; } static void __fastcall FakeSetTop(void *s,int top) { (void)s;assert(top==1);topRestores++; } static uint64_t __fastcall FakeGuid(const char *unit) { assert(!strcmp(unit,"raid2") || !strcmp(unit,"party4")); return UINT64_C(0x1122334455667788); } static int32_t __fastcall FakeSlot(const char *spell, uint32_t *book) { assert(!strcmp(spell,"Ritual of Summoning")); *book=0;return 7; } static void __fastcall FakeBookCast(uint32_t slot,uint32_t book,uint64_t guid) { assert(slot==7&&book==0&&guid==UINT64_C(0x1122334455667788)); // Model the real action gate: a frame-script context refuses the cast. if (*(uintptr_t *)0xCEEAC0 || *(uint32_t *)0xCEEAC4) return; executions++; } static void redirect(uintptr_t address, void *fn) { relativeJump((unsigned char *)address,fn); } static void loadClient(void) { // Reserve only the handful of code regions used by these tests. // A full low-address image can overlap the test process's CRT heap. const uintptr_t regions[]={0x400000,0x420000,0x490000,0x4b0000,0x510000,0x6f0000,0x700000,0xce0000}; for(unsigned i=0;ie_lfanew); memcpy(client,raw,nt->OptionalHeader.SizeOfHeaders); IMAGE_SECTION_HEADER *sections=IMAGE_FIRST_SECTION(nt); for(unsigned j=1;jFileHeader.NumberOfSections;i++){ IMAGE_SECTION_HEADER *s=sections+i; if(rva>=s->VirtualAddress && rva+0x10000<=s->VirtualAddress+s->SizeOfRawData) memcpy((void *)regions[j],raw+s->PointerToRawData+rva-s->VirtualAddress,0x10000); } } free(raw); } static void stubFunctions(void) { redirect(0x704120,(void *)(uintptr_t)&FakeRegister); redirect(0x6f3690,(void *)(uintptr_t)&FakeToString); redirect(0x6f3890,(void *)(uintptr_t)&FakePushString); redirect(0x6f39f0,(void *)(uintptr_t)&FakePushBoolean); redirect(0x6f3070,(void *)(uintptr_t)&FakeGetTop); redirect(0x6f3080,(void *)(uintptr_t)&FakeSetTop); redirect(0x515970,(void *)(uintptr_t)&FakeGuid); redirect(0x4b3950,(void *)(uintptr_t)&FakeSlot); redirect(0x4b3300,(void *)(uintptr_t)&FakeBookCast); } int main(int argc, char **argv) { if (argc > 1) clientPath = argv[1]; loadClient(); // The actual built DLL must reject this unrelated host executable. const char *dllPath = argc > 2 ? argv[2] : "LockPort.dll"; assert(GetFileAttributesA(dllPath) != INVALID_FILE_ATTRIBUTES); HMODULE dll=LoadLibraryA(dllPath); DWORD loadError=GetLastError(); assert(!dll && loadError==ERROR_DLL_INIT_FAILED); puts("PASS DLL rejects an unsupported host"); assert(matchesClient()); puts("PASS inspected client function signatures"); assert(validUnit("raid1")&&validUnit("raid40")&&validUnit("party1")&&validUnit("party4")); const char *invalid[]={"player","party0","party5","party01","party1x","raid0","raid41","raid01","raid2x","raid2\");print(1)--","raid",NULL}; for(unsigned i=0;i