From 6be6f76ee0141d6d1cef1f7103889c9e5a88778c Mon Sep 17 00:00:00 2001 From: Calvin Balke Date: Sun, 28 Jun 2015 21:14:08 -0700 Subject: [PATCH 1/5] Added a new TS evaluate shell --- .../Watchdog/Watchdog/source/dllmain.cpp | 66 ++++++++++++++++--- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp b/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp index c92a2db..6a9219e 100644 --- a/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp +++ b/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp @@ -25,16 +25,44 @@ BOOL APIENTRY DllMain( HMODULE hModule, static bool sDogPetted = false; static DWORD mainthreadid=0; +static bool evaldone=1; +void overridegets(char * string) { + int counter=0; + char outstr[3]=""; + while (1) { + if (_kbhit()) { + string[counter]=_getch(); + _putch(string[counter]); + if (string[counter]=='\n' || string[counter]=='\r') { + string[counter]=0x0; + break; + } else { + counter++; + } + } else { + Sleep(4); + } + } +} +DWORD WINAPI WatchDogEvalThread(LPVOID lpParam) +{ + Con::evaluate((char *) lpParam,true,0,0); + Con::printf ("Finished executing\n"); + evaldone=1; + return 0; +} DWORD WINAPI WatchDogThread(LPVOID lpParam) { time_t lastPet = time(0); CONTEXT hamburger; HANDLE mainThread = OpenThread(THREAD_ALL_ACCESS,false,mainthreadid); + char inputchar=0; + char evalcode[5000]=""; while (true) { time_t now = time(0); double seconds = difftime(now,lastPet); -#ifdef SLOWSERVER +#ifdef SLOWSERVERa if (!sDogPetted && seconds > 15) // Wait 15 seconds to be extra safe #else if (!sDogPetted && seconds > 8) // Wait 8 seconds to be safe @@ -50,13 +78,35 @@ DWORD WINAPI WatchDogThread(LPVOID lpParam) fprintf (wlog,"EIP: %08X EAX: %08X EBX: %08X ECX: %08X \nEDX: %08X ESI: %08X EDI: %08X\nEBP:%08X ESP:%08X\n", hamburger.Eip, hamburger.Eax, hamburger.Ebx, hamburger.Ecx, hamburger.Edx, hamburger.Esi, hamburger.Edi, hamburger.Ebp, hamburger.Esp); fclose (wlog); Con::printf ("EIP: %08X EAX: %08X EBX: %08X ECX: %08X \nEDX: %08X ESI: %08X EDI: %08X\nEBP:%08X ESP:%08X\n", hamburger.Eip, hamburger.Eax, hamburger.Ebx, hamburger.Ecx, hamburger.Edx, hamburger.Esi, hamburger.Edi, hamburger.Ebp, hamburger.Esp); - Con::printf ("Please press enter to try to continue\n or wait for 30 more seconds to kill T2 and write log\n"); - Sleep(30000); - if (_kbhit()) { - sDogPetted=true; - _getch(); // make sure to clean the keyboard buffer - ResumeThread(mainThread); - } else { + Con::printf ("Please press enter to try to continue, press e to get a torquescript shell, or wait for 30 more seconds to kill T2 and write log\n"); + for (int secondcounter=0;secondcounter<120;secondcounter++) { + Sleep(250); + if (_kbhit()) { + sDogPetted=true; + inputchar=_getch(); // make sure to clean the keyboard buffer + if (inputchar=='e') { + Con::printf ("Torque script shell activated enter the code to evaluate on the next line to exit, just type exitshell and press enter\n"); + while (true) { + overridegets(evalcode); + if (strcmp(evalcode,"exitshell")==0) { + break; + } + DWORD threadID=0; + evaldone=0; + HANDLE thread = CreateThread(NULL, 0, WatchDogEvalThread, evalcode, 0, &threadID); + while (!evaldone) { + Sleep(256); + } + CloseHandle(thread); + } + + } + ResumeThread(mainThread); + break; + } + } + + if (!sDogPetted) { CloseHandle(mainThread); exit(0); } From 48f55541822494e6f12dd7f57c49b618e66d47e0 Mon Sep 17 00:00:00 2001 From: Calvin Balke Date: Mon, 29 Jun 2015 00:17:33 -0700 Subject: [PATCH 2/5] Added new code to fix the modulo opcode The memPatch is also included in a comment. --- ModLoader/Modloader/source/t2dll.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ModLoader/Modloader/source/t2dll.cpp b/ModLoader/Modloader/source/t2dll.cpp index 73b2176..1a7e1d1 100644 --- a/ModLoader/Modloader/source/t2dll.cpp +++ b/ModLoader/Modloader/source/t2dll.cpp @@ -20,7 +20,7 @@ BOOL APIENTRY DllMain( HMODULE hModule, { return true; } - +const unsigned char moduroutine[] = {0x8B, 0x3D, 0xEC, 0x82, 0x9E, 0x00, 0x89, 0xF8, 0x8B, 0x14, 0x85, 0xFC, 0xA5, 0x88, 0x00, 0x83, 0xFA, 0x00, 0x74, 0x30, 0x8B, 0x3D, 0xEC, 0x82, 0x9E, 0x00, 0x89, 0xF8, 0x31, 0xD2, 0x89, 0xF8, 0x8B, 0x04, 0x85, 0x00, 0xA6, 0x88, 0x00, 0xF7, 0x34, 0xBD, 0xFC, 0xA5, 0x88, 0x00, 0xFF, 0x0D, 0xEC, 0x82, 0x9E, 0x00, 0x89, 0xF8, 0x89, 0x14, 0x85, 0xFC, 0xA5, 0x88, 0x00, 0xB8, 0xC7, 0xCE, 0x42, 0x00, 0xFF, 0xE0, 0xFF, 0x0D, 0xEC, 0x82, 0x9E, 0x00, 0xC7, 0x04, 0x85, 0xFC, 0xA5, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xC7, 0xCE, 0x42, 0x00, 0xFF, 0xE0}; const char* congetServPAddr(Linker::SimObject *obj, S32 argc, const char *argv[]) { char test[256] = ""; @@ -38,6 +38,23 @@ const char* congetServPAddr(Linker::SimObject *obj, S32 argc, const char *argv[] test2[8]=0;*/ return test2; } +const char* congetModuAddr(Linker::SimObject *obj, S32 argc, const char *argv[]) +{ + char test[256] = ""; + char test2[256]=""; + int spr=(signed int)moduroutine; + sprintf(test2,"B8%08XFFE0",endian(spr)); + /*test2[0]=test[6]; + test2[1]=test[7]; + test2[2]=test[4]; + test2[3]=test[5]; + test2[4]=test[2]; + test2[5]=test[3]; + test2[6]=test[0]; + test2[7]=test[1]; + test2[8]=0;*/ + return test2; +} class CImmCompoundEffect @@ -54,11 +71,12 @@ class CImmDevice { Con::addVariable("$cpuspeed",TypeS32,reinterpret_cast(0x8477F8)); //1 - S32, this is so i can set my cpu speed to 31337 or osmething =P Con::addVariable("$GameBase::showBoundingBox",TypeBool,reinterpret_cast(0x9ECF24)); - + DWORD oldprotect=0; // Mod Loader Function Con::addMethodB(NULL, "loadMod", &conLoadMod, "Loads a C++ modification.",2,2); Con::addMethodS(NULL, "getServPAddr",&congetServPAddr,"Gets the memPatch data for ServerProcess",1,1); - + VirtualProtect( (LPVOID)moduroutine,sizeof(moduroutine),PAGE_EXECUTE_READWRITE,&oldprotect); + Con::addMethodS(NULL, "getModuAddr",&congetModuAddr,"Gets the memPatch data for the MODULO operator routine",1,1); // memPatch("42D89D",getModuAddr()); // Load the original TribesNext DLL if available typedef void (*LPINITT2DLL)(void); HINSTANCE hDLL = NULL; From 8f29130f6399661fa0e71ad20c2689f1e2b9a6c9 Mon Sep 17 00:00:00 2001 From: Calvin Balke Date: Mon, 29 Jun 2015 13:06:40 -0700 Subject: [PATCH 3/5] Updated the ModLoader This new code for the ModLoader allows the WatchDog to dump compiled script bytecode in the event of a crash, and even get the instruction pointer for the scripting language. Some comments were also removed to clean up the code. --- ModLoader/Modloader/source/t2dll.cpp | 30 +++++++++++----------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/ModLoader/Modloader/source/t2dll.cpp b/ModLoader/Modloader/source/t2dll.cpp index 1a7e1d1..77c7e0a 100644 --- a/ModLoader/Modloader/source/t2dll.cpp +++ b/ModLoader/Modloader/source/t2dll.cpp @@ -21,21 +21,13 @@ BOOL APIENTRY DllMain( HMODULE hModule, return true; } const unsigned char moduroutine[] = {0x8B, 0x3D, 0xEC, 0x82, 0x9E, 0x00, 0x89, 0xF8, 0x8B, 0x14, 0x85, 0xFC, 0xA5, 0x88, 0x00, 0x83, 0xFA, 0x00, 0x74, 0x30, 0x8B, 0x3D, 0xEC, 0x82, 0x9E, 0x00, 0x89, 0xF8, 0x31, 0xD2, 0x89, 0xF8, 0x8B, 0x04, 0x85, 0x00, 0xA6, 0x88, 0x00, 0xF7, 0x34, 0xBD, 0xFC, 0xA5, 0x88, 0x00, 0xFF, 0x0D, 0xEC, 0x82, 0x9E, 0x00, 0x89, 0xF8, 0x89, 0x14, 0x85, 0xFC, 0xA5, 0x88, 0x00, 0xB8, 0xC7, 0xCE, 0x42, 0x00, 0xFF, 0xE0, 0xFF, 0x0D, 0xEC, 0x82, 0x9E, 0x00, 0xC7, 0x04, 0x85, 0xFC, 0xA5, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xC7, 0xCE, 0x42, 0x00, 0xFF, 0xE0}; +const unsigned char interpreterRoutine[] = {0x8B ,0x56 ,0x18 ,0x89 ,0x15 ,0x10 ,0xB7 ,0xA3 ,0x00 ,0x89 ,0x1D ,0x14 ,0xB7 ,0xA3 ,0x00 ,0x8B ,0x55 ,0x80 ,0x89 ,0xD0 ,0xBF ,0xD9 ,0xCE ,0x42 ,0x00 ,0x3D ,0x55 ,0x00 ,0x00 ,0x00 ,0xFF ,0xE7}; const char* congetServPAddr(Linker::SimObject *obj, S32 argc, const char *argv[]) { char test[256] = ""; char test2[256]=""; int spr=(signed int)*serverProcessReplacement; sprintf(test2,"B8%08XFFD089EC5DC3",endian(spr)); - /*test2[0]=test[6]; - test2[1]=test[7]; - test2[2]=test[4]; - test2[3]=test[5]; - test2[4]=test[2]; - test2[5]=test[3]; - test2[6]=test[0]; - test2[7]=test[1]; - test2[8]=0;*/ return test2; } const char* congetModuAddr(Linker::SimObject *obj, S32 argc, const char *argv[]) @@ -44,15 +36,14 @@ const char* congetModuAddr(Linker::SimObject *obj, S32 argc, const char *argv[]) char test2[256]=""; int spr=(signed int)moduroutine; sprintf(test2,"B8%08XFFE0",endian(spr)); - /*test2[0]=test[6]; - test2[1]=test[7]; - test2[2]=test[4]; - test2[3]=test[5]; - test2[4]=test[2]; - test2[5]=test[3]; - test2[6]=test[0]; - test2[7]=test[1]; - test2[8]=0;*/ + return test2; +} +const char* congetInterpreterAddr(Linker::SimObject *obj, S32 argc, const char *argv[]) +{ + char test[256] = ""; + char test2[256]=""; + int spr=(signed int)interpreterRoutine; + sprintf(test2,"B8%08XFFE0",endian(spr)); return test2; } @@ -76,7 +67,10 @@ class CImmDevice Con::addMethodB(NULL, "loadMod", &conLoadMod, "Loads a C++ modification.",2,2); Con::addMethodS(NULL, "getServPAddr",&congetServPAddr,"Gets the memPatch data for ServerProcess",1,1); VirtualProtect( (LPVOID)moduroutine,sizeof(moduroutine),PAGE_EXECUTE_READWRITE,&oldprotect); + VirtualProtect( (LPVOID)interpreterRoutine,sizeof(interpreterRoutine),PAGE_EXECUTE_READWRITE,&oldprotect); Con::addMethodS(NULL, "getModuAddr",&congetModuAddr,"Gets the memPatch data for the MODULO operator routine",1,1); // memPatch("42D89D",getModuAddr()); + Con::addMethodS(NULL, "getInterAddr", &congetInterpreterAddr, "Gets the memPatch data for the interpreter switchtable",1,1); // memPatch("42CED1",getInterAddr()); + // Load the original TribesNext DLL if available typedef void (*LPINITT2DLL)(void); HINSTANCE hDLL = NULL; From d0224b4d9b5a90caa7f961277d23b7d839b88191 Mon Sep 17 00:00:00 2001 From: Calvin Balke Date: Mon, 29 Jun 2015 13:08:54 -0700 Subject: [PATCH 4/5] Updated the WatchDog Added code to the watchdog to allow dumping bytecode and getting the instruction pointer for the scripting language. --- .../Watchdog/Watchdog/source/dllmain.cpp | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp b/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp index 6a9219e..639454b 100644 --- a/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp +++ b/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp @@ -26,6 +26,16 @@ BOOL APIENTRY DllMain( HMODULE hModule, static bool sDogPetted = false; static DWORD mainthreadid=0; static bool evaldone=1; +void overrideputhex(unsigned char hex) { + char hexstr[40]=""; + char outchar=' '; + int counter=0; + sprintf (hexstr,"%02X",hex); + while (hexstr[counter] != 0x0) { + _putch(hexstr[counter]); + counter++; + } +} void overridegets(char * string) { int counter=0; char outstr[3]=""; @@ -78,7 +88,7 @@ DWORD WINAPI WatchDogThread(LPVOID lpParam) fprintf (wlog,"EIP: %08X EAX: %08X EBX: %08X ECX: %08X \nEDX: %08X ESI: %08X EDI: %08X\nEBP:%08X ESP:%08X\n", hamburger.Eip, hamburger.Eax, hamburger.Ebx, hamburger.Ecx, hamburger.Edx, hamburger.Esi, hamburger.Edi, hamburger.Ebp, hamburger.Esp); fclose (wlog); Con::printf ("EIP: %08X EAX: %08X EBX: %08X ECX: %08X \nEDX: %08X ESI: %08X EDI: %08X\nEBP:%08X ESP:%08X\n", hamburger.Eip, hamburger.Eax, hamburger.Ebx, hamburger.Ecx, hamburger.Edx, hamburger.Esi, hamburger.Edi, hamburger.Ebp, hamburger.Esp); - Con::printf ("Please press enter to try to continue, press e to get a torquescript shell, or wait for 30 more seconds to kill T2 and write log\n"); + Con::printf ("Please press enter to try to continue, press e to get a torquescript shell, press d to get a hexdump of the last bit of torquescript bytecode to search for in DSO files, or wait for 30 more seconds to kill T2 and write log\n"); for (int secondcounter=0;secondcounter<120;secondcounter++) { Sleep(250); if (_kbhit()) { @@ -100,6 +110,24 @@ DWORD WINAPI WatchDogThread(LPVOID lpParam) CloseHandle(thread); } + } else if (inputchar=='d') { + DWORD codeOffset=*(DWORD *)(0xa3b714); + DWORD codeBase=*(DWORD *)(0xa3b710); + if (codeBase!=0) { + unsigned char *basecodeptr=(unsigned char *)((codeBase+(codeOffset*4))); + Con::printf ("CodeOffset: %08X CodeAddr: %08X (Codeoffset-128 to CodeOffset+512 is on the next line)\n",codeOffset, (codeBase+(codeOffset*4))); + + + for (int codeOffsetCounter=-128; codeOffsetCounter<512; codeOffsetCounter++) { + overrideputhex(*(basecodeptr+codeOffsetCounter)); + _putch(' '); + } + _putch('\n'); + _putch('\r'); + Con::printf("Search for those hex bytes in a binary search utility to find the DSO file with the last executed opcodes\n"); + } else { + Con::printf ("you forgot to run this command: memPatch(\"42CED1\",getInterAddr());\n"); + } } ResumeThread(mainThread); break; @@ -124,6 +152,10 @@ extern "C" { __declspec(dllexport) void ModInitialize(void) { + DWORD *codeOffset=(DWORD *)(0xa3b714); + DWORD *codeBase=(DWORD *)(0xa3b710); + *codeOffset=0x0; + *codeBase=0x0; mainthreadid = GetThreadId(GetCurrentThread()); SECURITY_DESCRIPTOR secDescVar; DWORD threadID; From 8ec9674ea7fe0b580fad20e9f992879f29967337 Mon Sep 17 00:00:00 2001 From: Calvin Balke Date: Mon, 29 Jun 2015 14:26:17 -0700 Subject: [PATCH 5/5] Added an option to adjust hamburger delay Also removed a typo --- Mod Sources/Watchdog/Watchdog/source/dllmain.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp b/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp index 639454b..da749fb 100644 --- a/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp +++ b/Mod Sources/Watchdog/Watchdog/source/dllmain.cpp @@ -4,9 +4,10 @@ #include #include #include - #include +// #define LONGHAMBURGERROUTINE + BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved @@ -72,7 +73,7 @@ DWORD WINAPI WatchDogThread(LPVOID lpParam) { time_t now = time(0); double seconds = difftime(now,lastPet); -#ifdef SLOWSERVERa +#ifdef SLOWSERVER if (!sDogPetted && seconds > 15) // Wait 15 seconds to be extra safe #else if (!sDogPetted && seconds > 8) // Wait 8 seconds to be safe @@ -89,7 +90,11 @@ DWORD WINAPI WatchDogThread(LPVOID lpParam) fclose (wlog); Con::printf ("EIP: %08X EAX: %08X EBX: %08X ECX: %08X \nEDX: %08X ESI: %08X EDI: %08X\nEBP:%08X ESP:%08X\n", hamburger.Eip, hamburger.Eax, hamburger.Ebx, hamburger.Ecx, hamburger.Edx, hamburger.Esi, hamburger.Edi, hamburger.Ebp, hamburger.Esp); Con::printf ("Please press enter to try to continue, press e to get a torquescript shell, press d to get a hexdump of the last bit of torquescript bytecode to search for in DSO files, or wait for 30 more seconds to kill T2 and write log\n"); +#ifdef LONGHAMBURGERROUTINE for (int secondcounter=0;secondcounter<120;secondcounter++) { +#else + for (int secondcounter=0;secondcounter<8;secondcounter++) { +#endif Sleep(250); if (_kbhit()) { sDogPetted=true;