--- Daodan/src/Daodan_Patch.c 2009/06/09 12:00:41 346 +++ Daodan/src/Daodan_Patch.c 2014/04/07 10:33:27 994 @@ -1,5 +1,9 @@ #include "Daodan_Patch.h" +#include "Patches/Utility.h" +#include + #include +#include #include bool DDrPatch_MakeJump(void* from, void* to) @@ -8,7 +12,8 @@ bool DDrPatch_MakeJump(void* from, void* if (VirtualProtect(from, 5, PAGE_EXECUTE_READWRITE, &oldp)) { - *(char*)from++ = 0xe9; // jmp rel32 + *((unsigned char*)from) = 0xe9; // jmp rel32 + from = (char*)from + 1; *(int*)from = (unsigned int)to - (unsigned int)from - 4; VirtualProtect(from, 5, oldp, &oldp); return true; @@ -23,7 +28,8 @@ bool DDrPatch_MakeCall(void* from, void* if (VirtualProtect(from, 5, PAGE_EXECUTE_READWRITE, &oldp)) { - *(char*)from++ = 0xe8; // call rel32 + *((unsigned char*)from) = 0xe8; // call rel32 + from = (char*)from + 1; *(int*)from = (unsigned int)to - (unsigned int)from - 4; VirtualProtect(from, 5, oldp, &oldp); return true; @@ -32,7 +38,192 @@ bool DDrPatch_MakeCall(void* from, void* return false; } -bool DDrPatch_String(char* dest, const char* string, int length) +void* DDrPatch_MakeDetour(void* from, void* to) +{ + int len = 0; +/* + DISASM MyDisasm; + int i = 0; + STARTUPMESSAGE("", 0); + STARTUPMESSAGE("", 0); + + memset (&MyDisasm, 0, sizeof(DISASM)); + MyDisasm.EIP = (UIntPtr) from; + i = 0; + STARTUPMESSAGE("Orig before @ 0x%06x", from); + while (i<10){ + len = Disasm(&MyDisasm); + if (len != UNKNOWN_OPCODE) { + STARTUPMESSAGE("%s, Opcode: 0x%x, len: %d, branch: %d, to: 0x%06x", MyDisasm.CompleteInstr, MyDisasm.Instruction.Opcode, len, MyDisasm.Instruction.BranchType, MyDisasm.Instruction.AddrValue); + STARTUPMESSAGE(" Cat: 0x%04x, prefix count: %d", MyDisasm.Instruction.Category & 0xffff, MyDisasm.Prefix.Number ); + MyDisasm.EIP += (UIntPtr)len; + i++; + } + }; + STARTUPMESSAGE("", 0); +*/ + + DISASM disasm; + memset(&disasm, 0, sizeof(DISASM)); + disasm.EIP = (UIntPtr) from; + + char* trampoline = malloc(40); + DDrPatch_NOOP(trampoline, 40); + int pos = 0; + int branches = 0; + + while (((void*)disasm.EIP - from) < 5) { + len = Disasm(&disasm); + if (len != UNKNOWN_OPCODE) { + if ((disasm.Instruction.Category & 0xffff) == CONTROL_TRANSFER) { + if (disasm.Prefix.Number > 0) { + STARTUPMESSAGE("Detour: Branch in trampoline area from address 0x%08x with prefixes", from); + return (void*)-1; + } + branches++; + int target = disasm.Instruction.AddrValue; + bool targetInTrampoline = ((void*)disasm.Instruction.AddrValue - from) < 5; + switch (disasm.Instruction.BranchType) { + case JmpType: + case CallType: + if (targetInTrampoline) { + int offset = disasm.Instruction.AddrValue - disasm.EIP; + if (disasm.Instruction.BranchType == JmpType) + DDrPatch_MakeJump(&trampoline[pos], &trampoline[pos]+offset); + else + DDrPatch_MakeCall(&trampoline[pos], &trampoline[pos]+offset); + } else { + if (disasm.Instruction.BranchType == JmpType) + DDrPatch_MakeJump(&trampoline[pos], (void*)target); + else + DDrPatch_MakeCall(&trampoline[pos], (void*)target); + } + pos += 5; + break; + case RetType: + case JECXZ: + memcpy(&trampoline[pos], (void*)disasm.EIP, len); + pos += len; + break; + // Opcode +1 + case JO: + case JC: + case JE: + case JNA: + case JS: + case JP: + case JL: + case JNG: + if (targetInTrampoline) { + memcpy(&trampoline[pos], (void*)disasm.EIP, len); + pos += len; + } else { + trampoline[pos++] = disasm.Instruction.Opcode + 1; + trampoline[pos++] = 5; + DDrPatch_MakeJump(&trampoline[pos], (void*)target); + pos += 5; + } + break; + // Opcode -1 + case JNO: + case JNC: + case JNE: + case JA: + case JNS: + case JNP: + case JNL: + case JG: + if (targetInTrampoline) { + memcpy(&trampoline[pos], (void*)disasm.EIP, len); + pos += len; + } else { + trampoline[pos++] = disasm.Instruction.Opcode - 1; + trampoline[pos++] = 5; + DDrPatch_MakeJump(&trampoline[pos], (void*)target); + pos += 5; + } + break; + default: + STARTUPMESSAGE("Detour: Unknown branch in trampoline area from address 0x%08x", from); + return (void*)-1; + } + } else { + memcpy(&trampoline[pos], (void*)disasm.EIP, len); + pos += len; + } + disasm.EIP += (UIntPtr)len; + } + else { + STARTUPMESSAGE("Detour: Unknown opcode in trampoline area from address 0x%08x", from); + return (void*)-1; + } + } + + if (branches > 1) { + STARTUPMESSAGE("Detour: Too many branches in trampoline'd code from address 0x%08x: %d", from, branches); + return (void*)-1; + } + + + DDrPatch_MakeJump(&trampoline[pos], (void*)disasm.EIP); + DDrPatch_NOOP(from, (void*)disasm.EIP - from); + + DWORD oldp; + if (!VirtualProtect(trampoline, 40, PAGE_EXECUTE_READWRITE, &oldp)) { + STARTUPMESSAGE("Detour: Could not mark page for trampoline as executable: from address 0x%08x", from); + return (void*)-1; + } + DDrPatch_MakeJump(from, to); +/* + memset (&MyDisasm, 0, sizeof(DISASM)); + MyDisasm.EIP = (UIntPtr) trampoline; + i = 0; + STARTUPMESSAGE("Trampoline @ 0x%06x", trampoline); + while (i<10){ + len = Disasm(&MyDisasm); + if (len != UNKNOWN_OPCODE) { + STARTUPMESSAGE("%s", MyDisasm.CompleteInstr); + MyDisasm.EIP += (UIntPtr)len; + i++; + } + }; + STARTUPMESSAGE("", 0); + + memset (&MyDisasm, 0, sizeof(DISASM)); + MyDisasm.EIP = disasm.EIP; + i = 0; + STARTUPMESSAGE("Orig after @ 0x%06x", disasm.EIP); + while (i<7){ + len = Disasm(&MyDisasm); + if (len != UNKNOWN_OPCODE) { + STARTUPMESSAGE("%s", MyDisasm.CompleteInstr); + MyDisasm.EIP += (UIntPtr)len; + i++; + } + }; + STARTUPMESSAGE("", 0); + + memset (&MyDisasm, 0, sizeof(DISASM)); + MyDisasm.EIP = (UIntPtr) from; + i = 0; + STARTUPMESSAGE("Orig start after @ 0x%06x", from); + while (i<3){ + len = Disasm(&MyDisasm); + if (len != UNKNOWN_OPCODE) { + STARTUPMESSAGE("%s", MyDisasm.CompleteInstr); + MyDisasm.EIP += (UIntPtr)len; + i++; + } + }; + STARTUPMESSAGE("", 0); + STARTUPMESSAGE("", 0); + STARTUPMESSAGE("", 0); +*/ + + return trampoline; +} + +bool DDrPatch_String(char* dest, const unsigned char* string, int length) { DWORD oldp; @@ -46,7 +237,7 @@ bool DDrPatch_String(char* dest, const c return false; } -bool DDrPatch_Byte(char* dest, char value) +bool DDrPatch_Byte(char* dest, unsigned char value) { DWORD oldp; @@ -60,7 +251,7 @@ bool DDrPatch_Byte(char* dest, char valu return false; } -bool DDrPatch_Int32(int* dest, int value) +bool DDrPatch_Int32(int* dest, unsigned int value) { DWORD oldp; @@ -74,7 +265,7 @@ bool DDrPatch_Int32(int* dest, int value return false; } -bool DDrPatch_Int16(short* dest, short value) +bool DDrPatch_Int16(short* dest, unsigned short value) { DWORD oldp; @@ -88,16 +279,50 @@ bool DDrPatch_Int16(short* dest, short v return false; } -bool DDrPatch_StrDup(int* dest, const char* value) +bool DDrPatch_NOOP(char* dest, unsigned int length) { DWORD oldp; - if (VirtualProtect(dest, 4, PAGE_EXECUTE_READWRITE, &oldp)) + if (VirtualProtect(dest, length, PAGE_EXECUTE_READWRITE, &oldp)) { - *dest = (int)strdup(value); - VirtualProtect(dest, 4, oldp, &oldp); + memset(dest, 0x90, length); + VirtualProtect(dest, length, oldp, &oldp); return true; } else return false; } + + +void DDrPatch_PrintDisasm(void* addr, int instLimit, int sizeLimit) +{ + DISASM MyDisasm; + int len = 0; + int size = 0; + int i = 0; + + memset(&MyDisasm, 0, sizeof(DISASM)); + + MyDisasm.EIP = (UIntPtr) addr; + + STARTUPMESSAGE("", 0); + STARTUPMESSAGE("Disassembly @ 0x%06x", addr); + + if (sizeLimit <= 0) + sizeLimit = 20 * instLimit; + + while ((i < instLimit) && (size < sizeLimit)) { + len = Disasm(&MyDisasm); + if (len != UNKNOWN_OPCODE) { + size += len; + STARTUPMESSAGE(" %s, Opcode: 0x%x, len: %d, branch: %d, to: 0x%06x", MyDisasm.CompleteInstr, MyDisasm.Instruction.Opcode, len, MyDisasm.Instruction.BranchType, MyDisasm.Instruction.AddrValue); + STARTUPMESSAGE(" Cat: 0x%04x, prefix count: %d", MyDisasm.Instruction.Category & 0xffff, MyDisasm.Prefix.Number ); + + MyDisasm.EIP += (UIntPtr)len; + i++; + } + }; + + STARTUPMESSAGE("", 0); +} +