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 1008 by alloc, Mon Aug 25 23:21:09 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  
230 < bool DDrPatch__strdup(int* dest, const char* value)
230 > bool DDrPatch_NOOP(char* dest, unsigned int length)
231   {
232          DWORD oldp;
233          
234 <        if (VirtualProtect(dest, 4, PAGE_EXECUTE_READWRITE, &oldp))
234 >        if (VirtualProtect(dest, length, PAGE_EXECUTE_READWRITE, &oldp))
235          {
236 <                *dest = (int)_strdup(value);
237 <                VirtualProtect(dest, 4, oldp, &oldp);
236 >                memset(dest, 0x90, length);
237 >                VirtualProtect(dest, length, oldp, &oldp);
238                  return true;
239          }
240          else
241                  return false;
242   }
243  
244 < bool DDrPatch_NOOP(char* dest, unsigned int length)
244 > void* DDrPatch_ExecutableASM(char* from, char* nextInst, const unsigned char* code, int length)
245   {
246 +        char* newCode = malloc(length+5);
247 +        if (!DDrPatch_NOOP(newCode, length+5))
248 +                return (void*)-1;
249 +
250 +        memcpy(newCode, code, length);
251 +        if (!DDrPatch_MakeJump(&newCode[length], nextInst))
252 +                return (void*)-1;
253 +
254          DWORD oldp;
255 <        
256 <        if (VirtualProtect(dest, length, PAGE_EXECUTE_READWRITE, &oldp))
257 <        {
114 <                memset(dest, 0x90, length);
115 <                VirtualProtect(dest, length, oldp, &oldp);
116 <                return true;
255 >        if (!VirtualProtect(newCode, length+5, PAGE_EXECUTE_READWRITE, &oldp)) {
256 >                STARTUPMESSAGE("ExecASM: Could not mark page for new code as executable: from address 0x%08x", from);
257 >                return (void*)-1;
258          }
259 <        else
260 <                return false;
259 >        
260 >        if (!DDrPatch_MakeJump(from, newCode))
261 >                return (void*)-1;
262 >
263 >        return newCode;
264 > }
265 >
266 > void DDrPatch_PrintDisasm(void* addr, int instLimit, int sizeLimit)
267 > {
268 >        DISASM MyDisasm;
269 >        int len = 0;
270 >        int size = 0;
271 >        int i = 0;
272 >
273 >        memset(&MyDisasm, 0, sizeof(DISASM));
274 >
275 >        MyDisasm.EIP = (UIntPtr) addr;
276 >
277 >        STARTUPMESSAGE("", 0);
278 >        STARTUPMESSAGE("Disassembly @ 0x%06x", addr);
279 >
280 >        if (sizeLimit <= 0)
281 >                sizeLimit = 20 * instLimit;
282 >
283 >        while ((i < instLimit) && (size < sizeLimit)) {
284 >                len = Disasm(&MyDisasm);
285 >                if (len != UNKNOWN_OPCODE) {
286 >                        size += len;
287 >                        STARTUPMESSAGE("    %s, Opcode: 0x%x, len: %d, branch: %d, to: 0x%06x", MyDisasm.CompleteInstr, MyDisasm.Instruction.Opcode, len, MyDisasm.Instruction.BranchType, MyDisasm.Instruction.AddrValue);
288 >                        STARTUPMESSAGE("          Cat: 0x%04x, prefix count: %d", MyDisasm.Instruction.Category & 0xffff, MyDisasm.Prefix.Number );
289 >
290 >                        MyDisasm.EIP += (UIntPtr)len;
291 >                        i++;
292 >                }
293 >        };
294 >
295 >        STARTUPMESSAGE("", 0);
296   }
297 +

Diff Legend

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