source: Daodan/src/Daodan_Patch.c@ 990

Last change on this file since 990 was 990, checked in by alloc, 11 years ago

Daodan 3.7:

File size: 7.8 KB
Line 
1#include "Daodan_Patch.h"
2#include "Daodan_Utility.h"
3#include <beaengine/BeaEngine.h>
4
5#include <windows.h>
6#include <stdlib.h>
7#include <string.h>
8
9bool DDrPatch_MakeJump(void* from, void* to)
10{
11 DWORD oldp;
12
13 if (VirtualProtect(from, 5, PAGE_EXECUTE_READWRITE, &oldp))
14 {
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;
20 }
21 else
22 return false;
23}
24
25bool DDrPatch_MakeCall(void* from, void* to)
26{
27 DWORD oldp;
28
29 if (VirtualProtect(from, 5, PAGE_EXECUTE_READWRITE, &oldp))
30 {
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;
36 }
37 else
38 return false;
39}
40
41void* DDrPatch_MakeDetour(void* from, void* to)
42{
43 int len = 0;
44/*
45 DISASM MyDisasm;
46 int i = 0;
47 DDrStartupMessage("");
48 DDrStartupMessage("");
49
50 memset (&MyDisasm, 0, sizeof(DISASM));
51 MyDisasm.EIP = (UIntPtr) from;
52 i = 0;
53 DDrStartupMessage("Orig before @ 0x%06x", from);
54 while (i<10){
55 len = Disasm(&MyDisasm);
56 if (len != UNKNOWN_OPCODE) {
57 DDrStartupMessage("%s, Opcode: 0x%x, len: %d, branch: %d, to: 0x%06x", MyDisasm.CompleteInstr, MyDisasm.Instruction.Opcode, len, MyDisasm.Instruction.BranchType, MyDisasm.Instruction.AddrValue);
58 DDrStartupMessage(" Cat: 0x%04x, prefix count: %d", MyDisasm.Instruction.Category & 0xffff, MyDisasm.Prefix.Number );
59 MyDisasm.EIP += (UIntPtr)len;
60 i++;
61 }
62 };
63 DDrStartupMessage("");
64*/
65
66 DISASM disasm;
67 memset(&disasm, 0, sizeof(DISASM));
68 disasm.EIP = (UIntPtr) from;
69
70 char* trampoline = malloc(40);
71 DDrPatch_NOOP(trampoline, 40);
72 int pos = 0;
73 int branches = 0;
74
75 while (((void*)disasm.EIP - from) < 5) {
76 len = Disasm(&disasm);
77 if (len != UNKNOWN_OPCODE) {
78 if ((disasm.Instruction.Category & 0xffff) == CONTROL_TRANSFER) {
79 if (disasm.Prefix.Number > 0) {
80 DDrStartupMessage("Daodan: Detour: Branch in trampoline area from address 0x%08x with prefixes", from);
81 return (void*)-1;
82 }
83 branches++;
84 int target = disasm.Instruction.AddrValue;
85 bool targetInTrampoline = ((void*)disasm.Instruction.AddrValue - from) < 5;
86 switch (disasm.Instruction.BranchType) {
87 case JmpType:
88 case CallType:
89 if (targetInTrampoline) {
90 int offset = disasm.Instruction.AddrValue - disasm.EIP;
91 if (disasm.Instruction.BranchType == JmpType)
92 DDrPatch_MakeJump(&trampoline[pos], &trampoline[pos]+offset);
93 else
94 DDrPatch_MakeCall(&trampoline[pos], &trampoline[pos]+offset);
95 } else {
96 if (disasm.Instruction.BranchType == JmpType)
97 DDrPatch_MakeJump(&trampoline[pos], (void*)target);
98 else
99 DDrPatch_MakeCall(&trampoline[pos], (void*)target);
100 }
101 pos += 5;
102 break;
103 case RetType:
104 case JECXZ:
105 memcpy(&trampoline[pos], (void*)disasm.EIP, len);
106 pos += len;
107 break;
108 // Opcode +1
109 case JO:
110 case JC:
111 case JE:
112 case JNA:
113 case JS:
114 case JP:
115 case JL:
116 case JNG:
117 if (targetInTrampoline) {
118 memcpy(&trampoline[pos], (void*)disasm.EIP, len);
119 pos += len;
120 } else {
121 trampoline[pos++] = disasm.Instruction.Opcode + 1;
122 trampoline[pos++] = 5;
123 DDrPatch_MakeJump(&trampoline[pos], (void*)target);
124 pos += 5;
125 }
126 break;
127 // Opcode -1
128 case JNO:
129 case JNC:
130 case JNE:
131 case JA:
132 case JNS:
133 case JNP:
134 case JNL:
135 case JG:
136 if (targetInTrampoline) {
137 memcpy(&trampoline[pos], (void*)disasm.EIP, len);
138 pos += len;
139 } else {
140 trampoline[pos++] = disasm.Instruction.Opcode - 1;
141 trampoline[pos++] = 5;
142 DDrPatch_MakeJump(&trampoline[pos], (void*)target);
143 pos += 5;
144 }
145 break;
146 default:
147 DDrStartupMessage("Daodan: Detour: Unknown branch in trampoline area from address 0x%08x", from);
148 return (void*)-1;
149 }
150 } else {
151 memcpy(&trampoline[pos], (void*)disasm.EIP, len);
152 pos += len;
153 }
154 disasm.EIP += (UIntPtr)len;
155 }
156 else {
157 DDrStartupMessage("Daodan: Detour: Unknown opcode in trampoline area from address 0x%08x", from);
158 return (void*)-1;
159 }
160 }
161
162 if (branches > 1) {
163 DDrStartupMessage("Daodan: Detour: Too many branches in trampoline'd code from address 0x%08x: %d", from, branches);
164 return (void*)-1;
165 }
166
167
168 DDrPatch_MakeJump(&trampoline[pos], (void*)disasm.EIP);
169 DDrPatch_NOOP(from, (void*)disasm.EIP - from);
170
171 DWORD oldp;
172 if (!VirtualProtect(trampoline, 40, PAGE_EXECUTE_READWRITE, &oldp)) {
173 DDrStartupMessage("Daodan: Detour: Could not mark page for trampoline as executable: from address 0x%08x", from);
174 return (void*)-1;
175 }
176 DDrPatch_MakeJump(from, to);
177/*
178 memset (&MyDisasm, 0, sizeof(DISASM));
179 MyDisasm.EIP = (UIntPtr) trampoline;
180 i = 0;
181 DDrStartupMessage("Trampoline @ 0x%06x", trampoline);
182 while (i<10){
183 len = Disasm(&MyDisasm);
184 if (len != UNKNOWN_OPCODE) {
185 DDrStartupMessage(MyDisasm.CompleteInstr);
186 MyDisasm.EIP += (UIntPtr)len;
187 i++;
188 }
189 };
190 DDrStartupMessage("");
191
192 memset (&MyDisasm, 0, sizeof(DISASM));
193 MyDisasm.EIP = disasm.EIP;
194 i = 0;
195 DDrStartupMessage("Orig after @ 0x%06x", disasm.EIP);
196 while (i<7){
197 len = Disasm(&MyDisasm);
198 if (len != UNKNOWN_OPCODE) {
199 DDrStartupMessage(MyDisasm.CompleteInstr);
200 MyDisasm.EIP += (UIntPtr)len;
201 i++;
202 }
203 };
204 DDrStartupMessage("");
205
206 memset (&MyDisasm, 0, sizeof(DISASM));
207 MyDisasm.EIP = (UIntPtr) from;
208 i = 0;
209 DDrStartupMessage("Orig start after @ 0x%06x", from);
210 while (i<3){
211 len = Disasm(&MyDisasm);
212 if (len != UNKNOWN_OPCODE) {
213 DDrStartupMessage(MyDisasm.CompleteInstr);
214 MyDisasm.EIP += (UIntPtr)len;
215 i++;
216 }
217 };
218 DDrStartupMessage("");
219 DDrStartupMessage("");
220 DDrStartupMessage("");
221*/
222
223 return trampoline;
224}
225
226bool DDrPatch_String(char* dest, const unsigned char* string, int length)
227{
228 DWORD oldp;
229
230 if (VirtualProtect(dest, length, PAGE_EXECUTE_READWRITE, &oldp))
231 {
232 memcpy(dest, string, length);
233 VirtualProtect(dest, length, oldp, &oldp);
234 return true;
235 }
236 else
237 return false;
238}
239
240bool DDrPatch_Byte(char* dest, unsigned char value)
241{
242 DWORD oldp;
243
244 if (VirtualProtect(dest, 1, PAGE_EXECUTE_READWRITE, &oldp))
245 {
246 *dest = value;
247 VirtualProtect(dest, 1, oldp, &oldp);
248 return true;
249 }
250 else
251 return false;
252}
253
254bool DDrPatch_Int32(int* dest, unsigned int value)
255{
256 DWORD oldp;
257
258 if (VirtualProtect(dest, 4, PAGE_EXECUTE_READWRITE, &oldp))
259 {
260 *dest = value;
261 VirtualProtect(dest, 4, oldp, &oldp);
262 return true;
263 }
264 else
265 return false;
266}
267
268bool DDrPatch_Int16(short* dest, unsigned short value)
269{
270 DWORD oldp;
271
272 if (VirtualProtect(dest, 2, PAGE_EXECUTE_READWRITE, &oldp))
273 {
274 *dest = value;
275 VirtualProtect(dest, 2, oldp, &oldp);
276 return true;
277 }
278 else
279 return false;
280}
281
282bool DDrPatch__strdup(int* dest, const char* value)
283{
284 DWORD oldp;
285
286 if (VirtualProtect(dest, 4, PAGE_EXECUTE_READWRITE, &oldp))
287 {
288 *dest = (int)_strdup(value);
289 VirtualProtect(dest, 4, oldp, &oldp);
290 return true;
291 }
292 else
293 return false;
294}
295
296bool DDrPatch_NOOP(char* dest, unsigned int length)
297{
298 DWORD oldp;
299
300 if (VirtualProtect(dest, length, PAGE_EXECUTE_READWRITE, &oldp))
301 {
302 memset(dest, 0x90, length);
303 VirtualProtect(dest, length, oldp, &oldp);
304 return true;
305 }
306 else
307 return false;
308}
Note: See TracBrowser for help on using the repository browser.