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 272 by rossy, Tue Mar 17 09:06:00 2009 UTC vs.
Revision 1045 by alloc, Sun Aug 28 16:01:38 2016 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>
8  
9   bool DDrPatch_MakeJump(void* from, void* to)
10   {
# Line 7 | Line 12 | bool DDrPatch_MakeJump(void* from, void*
12          
13          if (VirtualProtect(from, 5, PAGE_EXECUTE_READWRITE, &oldp))
14          {
15 <                *(char*)from++ = 0xe9; // jmp rel32
15 >                *((unsigned char*)from) = 0xe9; // jmp rel32
16 >                from = (char*)from + 1;
17                  *(int*)from = (unsigned int)to - (unsigned int)from - 4;
18                  VirtualProtect(from, 5, oldp, &oldp);
19                  return true;
# Line 22 | Line 28 | bool DDrPatch_MakeCall(void* from, void*
28          
29          if (VirtualProtect(from, 5, PAGE_EXECUTE_READWRITE, &oldp))
30          {
31 <                *(char*)from++ = 0xe8; // call rel32
31 >                *((unsigned char*)from) = 0xe8; // call rel32
32 >                from = (char*)from + 1;
33                  *(int*)from = (unsigned int)to - (unsigned int)from - 4;
34                  VirtualProtect(from, 5, oldp, &oldp);
35                  return true;
# Line 31 | Line 38 | bool DDrPatch_MakeCall(void* from, void*
38                  return false;
39   }
40  
41 < bool DDrPatch_String(char* dest, const char* string, int length)
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*)((int)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;
177          
# Line 45 | Line 185 | bool DDrPatch_String(char* dest, const c
185                  return false;
186   }
187  
188 < bool DDrPatch_Byte(char* dest, char value)
188 > bool DDrPatch_Byte(char* dest, unsigned char value)
189   {
190          DWORD oldp;
191          
# Line 59 | Line 199 | bool DDrPatch_Byte(char* dest, char valu
199                  return false;
200   }
201  
202 < bool DDrPatch_Int32(int* dest, int value)
202 > bool DDrPatch_Int32(int* dest, unsigned int value)
203   {
204          DWORD oldp;
205          
# Line 73 | Line 213 | bool DDrPatch_Int32(int* dest, int value
213                  return false;
214   }
215  
216 < bool DDrPatch_Int16(short* dest, short value)
216 > bool DDrPatch_Int16(short* dest, unsigned short value)
217   {
218          DWORD oldp;
219          
# Line 86 | Line 226 | bool DDrPatch_Int16(short* dest, short v
226          else
227                  return false;
228   }
229 +
230 + bool DDrPatch_NOOP(char* dest, unsigned int length)
231 + {
232 +        DWORD oldp;
233 +        
234 +        if (VirtualProtect(dest, length, PAGE_EXECUTE_READWRITE, &oldp))
235 +        {
236 +                memset(dest, 0x90, length);
237 +                VirtualProtect(dest, length, oldp, &oldp);
238 +                return true;
239 +        }
240 +        else
241 +                return false;
242 + }
243 +
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 +        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 +        
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)