ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/Daodan/src/Daodan_Patch.c
(Generate patch)

Comparing Daodan/src/Daodan_Patch.c (file contents):
Revision 689 by alloc, Mon Mar 4 15:52:19 2013 UTC vs.
Revision 995 by alloc, Wed Apr 9 00:10:18 2014 UTC

# Line 1 | Line 1
1   #include "Daodan_Patch.h"
2 + #include "Patches/Utility.h"
3 + #include <beaengine/BeaEngine.h>
4 +
5   #include <windows.h>
6   #include <stdlib.h>
7   #include <string.h>
# Line 35 | Line 38 | bool DDrPatch_MakeCall(void* from, void*
38                  return false;
39   }
40  
41 + void* DDrPatch_MakeDetour(void* from, void* to)
42 + {
43 +        int len = 0;
44 +
45 + /*
46 +        STARTUPMESSAGE("Orig before", 0);
47 +        DDrPatch_PrintDisasm(from, 10, 0);
48 + */
49 +        DISASM disasm;
50 +        memset(&disasm, 0, sizeof(DISASM));
51 +        disasm.EIP = (UIntPtr) from;
52 +
53 +        char* trampoline = malloc(40);
54 +        DDrPatch_NOOP(trampoline, 40);
55 +        int pos = 0;
56 +        int branches = 0;
57 +
58 +        while (((void*)disasm.EIP - from) < 5) {
59 +                len = Disasm(&disasm);
60 +                if (len != UNKNOWN_OPCODE) {
61 +                        if ((disasm.Instruction.Category & 0xffff) == CONTROL_TRANSFER) {
62 +                                if (disasm.Prefix.Number > 0) {
63 +                                                STARTUPMESSAGE("Detour: Branch in trampoline area from address 0x%08x with prefixes", from);
64 +                                                return (void*)-1;
65 +                                }
66 +                                branches++;
67 +                                int target = disasm.Instruction.AddrValue;
68 +                                bool targetInTrampoline = ((void*)disasm.Instruction.AddrValue - from) < 5;
69 +                                switch (disasm.Instruction.BranchType) {
70 +                                        case JmpType:
71 +                                        case CallType:
72 +                                                if (targetInTrampoline) {
73 +                                                        int offset = disasm.Instruction.AddrValue - disasm.EIP;
74 +                                                        if (disasm.Instruction.BranchType == JmpType)
75 +                                                                DDrPatch_MakeJump(&trampoline[pos], &trampoline[pos]+offset);
76 +                                                        else
77 +                                                                DDrPatch_MakeCall(&trampoline[pos], &trampoline[pos]+offset);
78 +                                                } else {
79 +                                                        if (disasm.Instruction.BranchType == JmpType)
80 +                                                                DDrPatch_MakeJump(&trampoline[pos], (void*)target);
81 +                                                        else
82 +                                                                DDrPatch_MakeCall(&trampoline[pos], (void*)target);
83 +                                                }
84 +                                                pos += 5;
85 +                                                break;
86 +                                        case RetType:
87 +                                        case JECXZ:
88 +                                                memcpy(&trampoline[pos], (void*)disasm.EIP, len);
89 +                                                pos += len;
90 +                                                break;
91 +                                        // Opcode +1
92 +                                        case JO:
93 +                                        case JC:
94 +                                        case JE:
95 +                                        case JNA:
96 +                                        case JS:
97 +                                        case JP:
98 +                                        case JL:
99 +                                        case JNG:
100 +                                                if (targetInTrampoline) {
101 +                                                        memcpy(&trampoline[pos], (void*)disasm.EIP, len);
102 +                                                        pos += len;
103 +                                                } else {
104 +                                                        trampoline[pos++] = disasm.Instruction.Opcode + 1;
105 +                                                        trampoline[pos++] = 5;
106 +                                                        DDrPatch_MakeJump(&trampoline[pos], (void*)target);
107 +                                                        pos += 5;
108 +                                                }
109 +                                                break;
110 +                                        // Opcode -1
111 +                                        case JNO:
112 +                                        case JNC:
113 +                                        case JNE:
114 +                                        case JA:
115 +                                        case JNS:
116 +                                        case JNP:
117 +                                        case JNL:
118 +                                        case JG:
119 +                                                if (targetInTrampoline) {
120 +                                                        memcpy(&trampoline[pos], (void*)disasm.EIP, len);
121 +                                                        pos += len;
122 +                                                } else {
123 +                                                        trampoline[pos++] = disasm.Instruction.Opcode - 1;
124 +                                                        trampoline[pos++] = 5;
125 +                                                        DDrPatch_MakeJump(&trampoline[pos], (void*)target);
126 +                                                        pos += 5;
127 +                                                }
128 +                                                break;
129 +                                        default:
130 +                                                STARTUPMESSAGE("Detour: Unknown branch in trampoline area from address 0x%08x", from);
131 +                                                return (void*)-1;
132 +                                }
133 +                        } else {
134 +                                memcpy(&trampoline[pos], (void*)disasm.EIP, len);
135 +                                pos += len;
136 +                        }
137 +                        disasm.EIP += (UIntPtr)len;
138 +                }
139 +                else {
140 +                        STARTUPMESSAGE("Detour: Unknown opcode in trampoline area from address 0x%08x", from);
141 +                        return (void*)-1;
142 +                }
143 +        }
144 +
145 +        if (branches > 1) {
146 +                STARTUPMESSAGE("Detour: Too many branches in trampoline'd code from address 0x%08x: %d", from, branches);
147 +                return (void*)-1;
148 +        }
149 +
150 +
151 +        DDrPatch_MakeJump(&trampoline[pos], (void*)disasm.EIP);
152 +        DDrPatch_NOOP(from, (void*)disasm.EIP - from);
153 +
154 +        DWORD oldp;
155 +        if (!VirtualProtect(trampoline, 40, PAGE_EXECUTE_READWRITE, &oldp)) {
156 +                STARTUPMESSAGE("Detour: Could not mark page for trampoline as executable: from address 0x%08x", from);
157 +                return (void*)-1;
158 +        }
159 +        DDrPatch_MakeJump(from, to);
160 +
161 + /*
162 +        STARTUPMESSAGE("Trampoline", 0);
163 +        DDrPatch_PrintDisasm(trampoline, 10, 6);
164 +
165 +        STARTUPMESSAGE("Orig after", 0);
166 +        DDrPatch_PrintDisasm(disasm.EIP, 7, 0);
167 +
168 +        STARTUPMESSAGE("Orig start after", 0);
169 +        DDrPatch_PrintDisasm(from, 3, 6);
170 + */
171 +        return trampoline;
172 + }
173 +
174   bool DDrPatch_String(char* dest, const unsigned char* string, int length)
175   {
176          DWORD oldp;
# Line 91 | Line 227 | bool DDrPatch_Int16(short* dest, unsigne
227                  return false;
228   }
229  
94 bool DDrPatch__strdup(int* dest, const char* value)
95 {
96        DWORD oldp;
97        
98        if (VirtualProtect(dest, 4, PAGE_EXECUTE_READWRITE, &oldp))
99        {
100                *dest = (int)_strdup(value);
101                VirtualProtect(dest, 4, oldp, &oldp);
102                return true;
103        }
104        else
105                return false;
106 }
107
230   bool DDrPatch_NOOP(char* dest, unsigned int length)
231   {
232          DWORD oldp;
# Line 118 | Line 240 | bool DDrPatch_NOOP(char* dest, unsigned
240          else
241                  return false;
242   }
243 +
244 +
245 + void DDrPatch_PrintDisasm(void* addr, int instLimit, int sizeLimit)
246 + {
247 +        DISASM MyDisasm;
248 +        int len = 0;
249 +        int size = 0;
250 +        int i = 0;
251 +
252 +        memset(&MyDisasm, 0, sizeof(DISASM));
253 +
254 +        MyDisasm.EIP = (UIntPtr) addr;
255 +
256 +        STARTUPMESSAGE("", 0);
257 +        STARTUPMESSAGE("Disassembly @ 0x%06x", addr);
258 +
259 +        if (sizeLimit <= 0)
260 +                sizeLimit = 20 * instLimit;
261 +
262 +        while ((i < instLimit) && (size < sizeLimit)) {
263 +                len = Disasm(&MyDisasm);
264 +                if (len != UNKNOWN_OPCODE) {
265 +                        size += len;
266 +                        STARTUPMESSAGE("    %s, Opcode: 0x%x, len: %d, branch: %d, to: 0x%06x", MyDisasm.CompleteInstr, MyDisasm.Instruction.Opcode, len, MyDisasm.Instruction.BranchType, MyDisasm.Instruction.AddrValue);
267 +                        STARTUPMESSAGE("          Cat: 0x%04x, prefix count: %d", MyDisasm.Instruction.Category & 0xffff, MyDisasm.Prefix.Number );
268 +
269 +                        MyDisasm.EIP += (UIntPtr)len;
270 +                        i++;
271 +                }
272 +        };
273 +
274 +        STARTUPMESSAGE("", 0);
275 + }
276 +

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)