source: Daodan/src/Daodan_Patch.c@ 986

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

Daodan:

File size: 7.5 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 DDrPatch_MakeJump(from, to);
171/*
172 memset (&MyDisasm, 0, sizeof(DISASM));
173 MyDisasm.EIP = (UIntPtr) trampoline;
174 i = 0;
175 DDrStartupMessage("Trampoline @ 0x%06x", trampoline);
176 while (i<10){
177 len = Disasm(&MyDisasm);
178 if (len != UNKNOWN_OPCODE) {
179 DDrStartupMessage(MyDisasm.CompleteInstr);
180 MyDisasm.EIP += (UIntPtr)len;
181 i++;
182 }
183 };
184 DDrStartupMessage("");
185
186 memset (&MyDisasm, 0, sizeof(DISASM));
187 MyDisasm.EIP = disasm.EIP;
188 i = 0;
189 DDrStartupMessage("Orig after @ 0x%06x", disasm.EIP);
190 while (i<7){
191 len = Disasm(&MyDisasm);
192 if (len != UNKNOWN_OPCODE) {
193 DDrStartupMessage(MyDisasm.CompleteInstr);
194 MyDisasm.EIP += (UIntPtr)len;
195 i++;
196 }
197 };
198 DDrStartupMessage("");
199
200 memset (&MyDisasm, 0, sizeof(DISASM));
201 MyDisasm.EIP = (UIntPtr) from;
202 i = 0;
203 DDrStartupMessage("Orig start after @ 0x%06x", from);
204 while (i<3){
205 len = Disasm(&MyDisasm);
206 if (len != UNKNOWN_OPCODE) {
207 DDrStartupMessage(MyDisasm.CompleteInstr);
208 MyDisasm.EIP += (UIntPtr)len;
209 i++;
210 }
211 };
212 DDrStartupMessage("");
213 DDrStartupMessage("");
214 DDrStartupMessage("");
215 */
216 return trampoline;
217}
218
219bool DDrPatch_String(char* dest, const unsigned char* string, int length)
220{
221 DWORD oldp;
222
223 if (VirtualProtect(dest, length, PAGE_EXECUTE_READWRITE, &oldp))
224 {
225 memcpy(dest, string, length);
226 VirtualProtect(dest, length, oldp, &oldp);
227 return true;
228 }
229 else
230 return false;
231}
232
233bool DDrPatch_Byte(char* dest, unsigned char value)
234{
235 DWORD oldp;
236
237 if (VirtualProtect(dest, 1, PAGE_EXECUTE_READWRITE, &oldp))
238 {
239 *dest = value;
240 VirtualProtect(dest, 1, oldp, &oldp);
241 return true;
242 }
243 else
244 return false;
245}
246
247bool DDrPatch_Int32(int* dest, unsigned int value)
248{
249 DWORD oldp;
250
251 if (VirtualProtect(dest, 4, PAGE_EXECUTE_READWRITE, &oldp))
252 {
253 *dest = value;
254 VirtualProtect(dest, 4, oldp, &oldp);
255 return true;
256 }
257 else
258 return false;
259}
260
261bool DDrPatch_Int16(short* dest, unsigned short value)
262{
263 DWORD oldp;
264
265 if (VirtualProtect(dest, 2, PAGE_EXECUTE_READWRITE, &oldp))
266 {
267 *dest = value;
268 VirtualProtect(dest, 2, oldp, &oldp);
269 return true;
270 }
271 else
272 return false;
273}
274
275bool DDrPatch__strdup(int* dest, const char* value)
276{
277 DWORD oldp;
278
279 if (VirtualProtect(dest, 4, PAGE_EXECUTE_READWRITE, &oldp))
280 {
281 *dest = (int)_strdup(value);
282 VirtualProtect(dest, 4, oldp, &oldp);
283 return true;
284 }
285 else
286 return false;
287}
288
289bool DDrPatch_NOOP(char* dest, unsigned int length)
290{
291 DWORD oldp;
292
293 if (VirtualProtect(dest, length, PAGE_EXECUTE_READWRITE, &oldp))
294 {
295 memset(dest, 0x90, length);
296 VirtualProtect(dest, length, oldp, &oldp);
297 return true;
298 }
299 else
300 return false;
301}
Note: See TracBrowser for help on using the repository browser.