1 | ␉/*␊ |
2 | * Copyright (c) 2009-2010 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | #include "libsaio.h"␊ |
7 | #include "kernel_patcher.h"␊ |
8 | #include "platform.h"␊ |
9 | #include "modules.h"␊ |
10 | ␊ |
11 | long long symbol_handler(char* module, char* symbolName, long long addr, char is64);␊ |
12 | ␊ |
13 | patchRoutine_t* patches = NULL;␊ |
14 | kernSymbols_t* kernelSymbols = NULL;␊ |
15 | static void register_kernel_patch(void* patch, int arch, int cpus);␊ |
16 | static void register_kernel_symbol(int kernelType, const char* name);␊ |
17 | static kernSymbols_t* lookup_kernel_symbol(const char* name);␊ |
18 | static int determineKernelArchitecture(void* kernelData);␊ |
19 | static int locate_symbols(void* kernelData);␊ |
20 | ␊ |
21 | /*␊ |
22 | * Internal patches provided by this module.␊ |
23 | */␊ |
24 | static void patch_cpuid_set_info_all(void* kernelData);␊ |
25 | static void patch_cpuid_set_info_32(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel);␊ |
26 | static void patch_cpuid_set_info_64(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel);␊ |
27 | ␊ |
28 | //static void patch_pmCPUExitHaltToOff(void* kernelData);␊ |
29 | static void patch_lapic_init(void* kernelData);␊ |
30 | static void patch_commpage_stuff_routine(void* kernelData);␊ |
31 | static void patch_lapic_configure(void* kernelData);␊ |
32 | //static void patch_lapic_interrupt(void* kernelData);␊ |
33 | ␊ |
34 | void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4, void* arg5, void* arg6);␊ |
35 | void kernel_patcher_ignore_cache(void* arg1, void* arg2, void* arg3, void *arg4, void* arg5, void* arg6);␊ |
36 | void kernel_patcher_ignore_cache(void* arg1, void* arg2, void* arg3, void *arg4, void* arg5, void* arg6){}␊ |
37 | ␊ |
38 | void KernelPatcher_start(void);␊ |
39 | void KernelPatcher_start(void)␊ |
40 | {␊ |
41 | ␉register_kernel_patch(patch_cpuid_set_info_all, KERNEL_ANY, CPUID_MODEL_UNKNOWN); ␊ |
42 | ␊ |
43 | ␉register_kernel_patch(patch_commpage_stuff_routine, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
44 | ␉␊ |
45 | ␉register_kernel_patch(patch_lapic_init, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
46 | ␊ |
47 | ␉// NOTE: following is currently 32bit only␊ |
48 | ␉register_kernel_patch(patch_lapic_configure, KERNEL_32, CPUID_MODEL_ANY);␊ |
49 | ␊ |
50 | ␉register_kernel_symbol(KERNEL_ANY, "_panic");␊ |
51 | ␉register_kernel_symbol(KERNEL_ANY, "_cpuid_set_info");␊ |
52 | ␉register_kernel_symbol(KERNEL_ANY, "_pmCPUExitHaltToOff");␊ |
53 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_init");␊ |
54 | ␉register_kernel_symbol(KERNEL_ANY, "_commpage_stuff_routine");␊ |
55 | ␊ |
56 | ␉// lapic_configure symbols␊ |
57 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_configure");␊ |
58 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_start");␊ |
59 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt_base");␊ |
60 | ␊ |
61 | ␉// lapic_interrup symbols␊ |
62 | ␉//register_kernel_patch(patch_lapic_interrupt, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
63 | ␉//register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt");␊ |
64 | ␊ |
65 | ␉// TODO: register needed symbols␊ |
66 | ␊ |
67 | ␉register_hook_callback("ExecKernel", &patch_kernel); ␊ |
68 | ␉␊ |
69 | ␉replace_system_function("_getKernelCachePath", &kernel_patcher_ignore_cache);␊ |
70 | }␊ |
71 | ␊ |
72 | /*␊ |
73 | * Register a kernel patch␊ |
74 | */␊ |
75 | static void register_kernel_patch(void* patch, int arch, int cpus)␊ |
76 | {␊ |
77 | ␉// TODO: only insert valid patches based on current cpuid and architecture␊ |
78 | ␉// AKA, don't at 64bit patches if it's a 32bit only machine␊ |
79 | ␉patchRoutine_t* entry;␊ |
80 | ␉␊ |
81 | ␉// Check to ensure that the patch is valid on this machine␊ |
82 | ␉// If it is not, exit early form this function␊ |
83 | ␉if(cpus != get_env(envModel))␊ |
84 | ␉{␊ |
85 | ␉␉if(cpus != CPUID_MODEL_ANY)␊ |
86 | ␉␉{␊ |
87 | ␉␉␉if(cpus == CPUID_MODEL_UNKNOWN)␊ |
88 | ␉␉␉{␊ |
89 | ␉␉␉␉switch(get_env(envModel))␊ |
90 | ␉␉␉␉{␊ |
91 | ␉␉␉␉␉case 13:␊ |
92 | ␉␉␉␉␉case CPUID_MODEL_YONAH:␊ |
93 | ␉␉␉␉␉case CPUID_MODEL_MEROM:␊ |
94 | ␉␉␉␉␉case CPUID_MODEL_PENRYN:␊ |
95 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM:␊ |
96 | ␉␉␉␉␉case CPUID_MODEL_FIELDS:␊ |
97 | ␉␉␉␉␉case CPUID_MODEL_DALES:␊ |
98 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␊ |
99 | ␉␉␉␉␉␉// Known cpu's we don't want to add the patch␊ |
100 | ␉␉␉␉␉␉return;␊ |
101 | ␉␉␉␉␉␉break;␊ |
102 | ␊ |
103 | ␉␉␉␉␉default:␊ |
104 | ␉␉␉␉␉␉// CPU not in supported list, so we are going to add␊ |
105 | ␉␉␉␉␉␉// The patch will be applied␊ |
106 | ␉␉␉␉␉␉break;␊ |
107 | ␉␉␉␉}␊ |
108 | ␉␉␉}␊ |
109 | ␉␉␉else␊ |
110 | ␉␉␉{␊ |
111 | ␉␉␉␉// Invalid cpuid for current cpu. Ignoring patch␊ |
112 | ␉␉␉␉return;␊ |
113 | ␉␉␉}␊ |
114 | ␉␉}␊ |
115 | ␉}␊ |
116 | ␉␉␊ |
117 | ␉if(patches == NULL)␊ |
118 | ␉{␊ |
119 | ␉␉patches = entry = malloc(sizeof(patchRoutine_t));␊ |
120 | ␉}␊ |
121 | ␉else␊ |
122 | ␉{␊ |
123 | ␉␉entry = patches;␊ |
124 | ␉␉while(entry->next)␊ |
125 | ␉␉{␊ |
126 | ␉␉␉entry = entry->next;␊ |
127 | ␉␉}␊ |
128 | ␉␉␊ |
129 | ␉␉entry->next = malloc(sizeof(patchRoutine_t));␊ |
130 | ␉␉entry = entry->next;␊ |
131 | ␉}␊ |
132 | ␉␊ |
133 | ␉entry->next = NULL;␊ |
134 | ␉entry->patchRoutine = patch;␊ |
135 | ␉entry->validArchs = arch;␊ |
136 | ␉entry->validCpu = cpus;␊ |
137 | }␊ |
138 | ␊ |
139 | static void register_kernel_symbol(int kernelType, const char* name)␊ |
140 | {␊ |
141 | ␉if(kernelSymbols == NULL)␊ |
142 | ␉{␊ |
143 | ␉␉kernelSymbols = malloc(sizeof(kernSymbols_t));␊ |
144 | ␉␉kernelSymbols->next = NULL;␊ |
145 | ␉␉kernelSymbols->symbol = (char*)name;␊ |
146 | ␉␉kernelSymbols->addr = 0;␊ |
147 | ␉}␊ |
148 | ␉else␊ |
149 | ␉{␊ |
150 | ␉␉kernSymbols_t *symbol = kernelSymbols;␊ |
151 | ␉␉while(symbol->next != NULL)␊ |
152 | ␉␉{␊ |
153 | ␉␉␉symbol = symbol->next;␊ |
154 | ␉␉}␊ |
155 | ␉␉␊ |
156 | ␉␉symbol->next = malloc(sizeof(kernSymbols_t));␊ |
157 | ␉␉symbol = symbol->next;␊ |
158 | ␊ |
159 | ␉␉symbol->next = NULL;␊ |
160 | ␉␉symbol->symbol = (char*)name;␊ |
161 | ␉␉symbol->addr = 0;␊ |
162 | ␉}␊ |
163 | }␊ |
164 | ␊ |
165 | static kernSymbols_t* lookup_kernel_symbol(const char* name)␊ |
166 | {␊ |
167 | ␉kernSymbols_t *symbol = kernelSymbols;␊ |
168 | ␊ |
169 | ␉while(symbol && strcmp(symbol->symbol, name) !=0)␊ |
170 | ␉{␊ |
171 | ␉␉symbol = symbol->next;␊ |
172 | ␉}␊ |
173 | ␉␊ |
174 | ␉if(!symbol)␊ |
175 | ␉{␊ |
176 | ␉␉return NULL;␊ |
177 | ␉}␊ |
178 | ␉else␊ |
179 | ␉{␊ |
180 | ␉␉return symbol;␊ |
181 | ␉}␊ |
182 | }␊ |
183 | ␊ |
184 | void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4, void* arg5, void* arg6)␊ |
185 | {␊ |
186 | ␉patchRoutine_t* entry = patches;␊ |
187 | ␊ |
188 | ␉int arch = determineKernelArchitecture(kernelData);␊ |
189 | ␊ |
190 | ␉locate_symbols(kernelData);␊ |
191 | ␉␊ |
192 | ␉if(patches != NULL)␊ |
193 | ␉{␊ |
194 | ␉␉while(entry)␊ |
195 | ␉␉{␊ |
196 | ␉␉␉if(entry->validArchs == KERNEL_ANY || arch == entry->validArchs)␊ |
197 | ␉␉␉{␊ |
198 | ␉␉␉␉if(entry->patchRoutine) entry->patchRoutine(kernelData);␊ |
199 | ␉␉␉}␊ |
200 | ␉␉␉entry = entry->next;␊ |
201 | ␉␉}␊ |
202 | ␉}␊ |
203 | }␊ |
204 | ␊ |
205 | static int determineKernelArchitecture(void* kernelData)␊ |
206 | {␉␊ |
207 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC)␊ |
208 | ␉{␊ |
209 | ␉␉return KERNEL_32;␊ |
210 | ␉}␊ |
211 | ␊ |
212 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC_64)␊ |
213 | ␉{␊ |
214 | ␉␉return KERNEL_64;␊ |
215 | ␉}␊ |
216 | ␉else␊ |
217 | ␉{␊ |
218 | ␉␉return KERNEL_ERR;␊ |
219 | ␉}␊ |
220 | }␊ |
221 | ␊ |
222 | /**␊ |
223 | **␉␉This functions located the requested symbols in the mach-o file.␊ |
224 | **␉␉␉as well as determines the start of the __TEXT segment and __TEXT,__text sections␊ |
225 | **/␊ |
226 | static int locate_symbols(void* kernelData)␊ |
227 | {␊ |
228 | ␉char is64 = 1;␊ |
229 | ␉parse_mach("VirtualXnuSyms",kernelData, NULL, symbol_handler);␊ |
230 | ␉//handle_symtable((UInt32)kernelData, symtableData, &symbol_handler, determineKernelArchitecture(kernelData) == KERNEL_64);␊ |
231 | ␉return 1 << is64;␊ |
232 | }␊ |
233 | ␊ |
234 | long long symbol_handler(char* module, char* symbolName, long long addr, char is64)␊ |
235 | {␊ |
236 | ␉// Locate the symbol in the list, if it exists, update it's address␊ |
237 | ␉kernSymbols_t *symbol = lookup_kernel_symbol(symbolName);␊ |
238 | ␉␊ |
239 | ␉if(symbol)␊ |
240 | ␉{␊ |
241 | ␉␉symbol->addr = addr;␊ |
242 | ␉}␊ |
243 | ␉␊ |
244 | ␉return 0xFFFFFFFF; // fixme␊ |
245 | }␊ |
246 | ␊ |
247 | /**␊ |
248 | ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it␊ |
249 | ** Or replace it so that the cpuid is set to a valid value.␊ |
250 | **/␊ |
251 | static void patch_cpuid_set_info_all(void* kernelData)␊ |
252 | {␊ |
253 | ␉switch(get_env(envModel))␊ |
254 | ␉{␊ |
255 | ␉␉case CPUID_MODEL_ATOM:␊ |
256 | ␉␉␉if(determineKernelArchitecture(kernelData) == KERNEL_32)␊ |
257 | ␉␉␉{␊ |
258 | ␉␉␉␉patch_cpuid_set_info_32(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);␊ |
259 | ␉␉␉}␊ |
260 | ␉␉␉else ␊ |
261 | ␉␉␉{␊ |
262 | ␉␉␉␉patch_cpuid_set_info_64(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);␊ |
263 | ␉␉␉}␊ |
264 | ␊ |
265 | ␉␉␉break;␊ |
266 | ␊ |
267 | ␉␉default:␊ |
268 | ␉␉{␊ |
269 | ␉␉␉// AnV: Extra cpuid fix for spoofing Nehalem CPU for i5/i9␊ |
270 | ␉␉␉switch(get_env(envFamily))␊ |
271 | ␉␉␉{␊ |
272 | ␉␉␉␉case 0x1E: /* Intel i5 */␊ |
273 | ␉␉␉␉case 0x2C: /* Intel i9 */␊ |
274 | ␉␉␉␉␉if(determineKernelArchitecture(kernelData) == KERNEL_32)␊ |
275 | ␉␉␉␉␉{␊ |
276 | ␉␉␉␉␉␉patch_cpuid_set_info_32(kernelData, CPUFAMILY_INTEL_NEHALEM, CPUID_MODEL_NEHALEM);␊ |
277 | ␉␉␉␉␉}␊ |
278 | ␉␉␉␉␉else ␊ |
279 | ␉␉␉␉␉{␊ |
280 | ␉␉␉␉␉␉patch_cpuid_set_info_64(kernelData, CPUFAMILY_INTEL_NEHALEM, CPUID_MODEL_NEHALEM);␊ |
281 | ␉␉␉␉␉}␊ |
282 | ␉␉␉␉␉␊ |
283 | ␉␉␉␉␉break;␊ |
284 | ␉␉␉␉␊ |
285 | ␉␉␉␉default:␊ |
286 | ␉␉␉␉␉if(determineKernelArchitecture(kernelData) == KERNEL_32)␊ |
287 | ␉␉␉␉␉{␊ |
288 | ␉␉␉␉␉␉patch_cpuid_set_info_32(kernelData, 0, 0);␊ |
289 | ␉␉␉␉␉}␊ |
290 | ␉␉␉␉␉else␊ |
291 | ␉␉␉␉␉{␊ |
292 | ␉␉␉␉␉␉patch_cpuid_set_info_64(kernelData, 0, 0);␊ |
293 | ␉␉␉␉␉}␉␉␉␉␉␊ |
294 | ␉␉␉␉␉break;␊ |
295 | ␉␉␉}␊ |
296 | ␉␉␉break;␉␉␉␊ |
297 | ␉␉}␊ |
298 | ␉}␊ |
299 | }␊ |
300 | ␊ |
301 | static void patch_cpuid_set_info_64(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)␊ |
302 | {␊ |
303 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
304 | ␉␊ |
305 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");␊ |
306 | ␉␊ |
307 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //␉(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
308 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
309 | ␊ |
310 | ␉//UInt32 jumpLocation = 0;␊ |
311 | ␊ |
312 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
313 | ␉{␊ |
314 | ␉␉verbose("Unable to locate _cpuid_set_info\n");␊ |
315 | ␉␉return;␊ |
316 | ␉}␊ |
317 | ␉␊ |
318 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
319 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
320 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
321 | ␉{␊ |
322 | ␉␉printf("Unable to locate _panic\n");␊ |
323 | ␉␉return;␊ |
324 | ␉}␊ |
325 | ␉panicAddr -= (UInt32)kernelData;␊ |
326 | ␊ |
327 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
328 | ␉while( ␊ |
329 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
330 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
331 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
332 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
333 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
334 | ␉␉ )␊ |
335 | ␉{␊ |
336 | ␉␉patchLocation++;␊ |
337 | ␉}␊ |
338 | ␉patchLocation--;␊ |
339 | ␊ |
340 | ␉// Remove panic just in ca se␊ |
341 | ␉// The panic instruction is exactly 5 bytes long.␊ |
342 | ␉bytes[patchLocation + 0] = 0x90;␊ |
343 | ␉bytes[patchLocation + 1] = 0x90;␊ |
344 | ␉bytes[patchLocation + 2] = 0x90;␊ |
345 | ␉bytes[patchLocation + 3] = 0x90;␊ |
346 | ␉bytes[patchLocation + 4] = 0x90;␊ |
347 | ␊ |
348 | ␉// Check for a 10.2.0+ kernel␊ |
349 | ␉if(bytes[patchLocation - 19] == 0xC7 && bytes[patchLocation - 18] == 0x05)␊ |
350 | ␉{␊ |
351 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 17] << 0 |␊ |
352 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 16] << 8 |␊ |
353 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 15] << 16 |␊ |
354 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 14] << 24;␊ |
355 | ␉␉␊ |
356 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
357 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 310; ␊ |
358 | ␊ |
359 | ␉␉//ffffff8000228b3b -> 0x00490e8b␊ |
360 | ␉␉//ffffff8000228c28 -> -237 -> 0x490D9E -> -310␊ |
361 | ␊ |
362 | ␉␉// The mov is 10 bytes␊ |
363 | ␉␉/*␊ |
364 | ␉␉ bytes[patchLocation - 19] = 0x90;␉// c7␊ |
365 | ␉␉ bytes[patchLocation - 18] = 0x90;␉// 05␊ |
366 | ␉␉ bytes[patchLocation - 17] = 0x90;␉// family location␊ |
367 | ␉␉ bytes[patchLocation - 16] = 0x90;␉// family location␊ |
368 | ␉␉ bytes[patchLocation - 15] = 0x90;␉// family location␊ |
369 | ␉␉ bytes[patchLocation - 14] = 0x90;␉// family location␊ |
370 | ␉␉ */␊ |
371 | ␉␉bytes[patchLocation - 13] = (impersonateFamily & 0x000000FF) >> 0;␊ |
372 | ␉␉bytes[patchLocation - 12] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
373 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
374 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0xFF000000) >> 24;␊ |
375 | ␊ |
376 | ␉␉// The lea (%rip),%rip is 7 bytes␊ |
377 | ␉␉bytes[patchLocation - 9] = 0xC7;␊ |
378 | ␉␉bytes[patchLocation - 8] = 0x05;␊ |
379 | ␉␉bytes[patchLocation - 7] = ((cpuid_model_addr -10) & 0x000000FF) >> 0;␉// NOTE: this opcode is relative in 64bit mode, subtract offset␊ |
380 | ␉␉bytes[patchLocation - 6] = ((cpuid_model_addr -10) & 0x0000FF00) >> 8;␉␊ |
381 | ␉␉bytes[patchLocation - 5] = ((cpuid_model_addr -10) & 0x00FF0000) >> 16;␊ |
382 | ␉␉bytes[patchLocation - 4] = ((cpuid_model_addr -10) & 0xFF000000) >> 24;␊ |
383 | ␉␉bytes[patchLocation - 3] = impersonateModel;␉// cpuid_model␊ |
384 | ␊ |
385 | ␉␉// The xor eax eax is 2 bytes␊ |
386 | ␉␉bytes[patchLocation - 2] = 0x01;␉// cpuid_extmodel␊ |
387 | ␉␉bytes[patchLocation - 1] = 0x00;␉// cpuid_extfamily␊ |
388 | ␉␉␊ |
389 | ␉␉// The panic instruction is exactly 5 bytes long.␊ |
390 | ␉␉bytes[patchLocation - 0] = 0x02;␉// cpuid_stepping␊ |
391 | ␉␉/*bytes[patchLocation + 1] = 0x90;␊ |
392 | ␉␉bytes[patchLocation + 2] = 0x90;␊ |
393 | ␉␉bytes[patchLocation + 3] = 0x90;␊ |
394 | ␉␉bytes[patchLocation + 4] = 0x90;␊ |
395 | ␉␉*/␊ |
396 | ␉␉␊ |
397 | ␉␉// Panic call has been removed.␊ |
398 | ␉␉// Override the CPUID now. This requires ~ 10 bytes on 10.0.0 kernels␊ |
399 | ␉␉// On 10.2.0+ kernels, this requires ~16 bytes␊ |
400 | ␉␉␊ |
401 | ␉␉// Total: 24 bytes␊ |
402 | ␉␉printf("Running on a 10.2.0+ kernel\n");␊ |
403 | ␉␉getc();␊ |
404 | ␉}␊ |
405 | ␉else {␊ |
406 | ␉␉printf("Running on a 10.0.0 kernel, patch unsupported\n");␊ |
407 | ␉␉getc();␊ |
408 | ␉}␊ |
409 | }␊ |
410 | ␊ |
411 | static void patch_cpuid_set_info_32(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)␊ |
412 | {␉␊ |
413 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
414 | ␉␊ |
415 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");␊ |
416 | ␊ |
417 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //␉(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
418 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
419 | ␊ |
420 | ␉UInt32 jumpLocation = 0;␉␊ |
421 | ␊ |
422 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
423 | ␉{␊ |
424 | ␉␉verbose("Unable to locate _cpuid_set_info\n");␊ |
425 | ␉␉return;␊ |
426 | ␉}␊ |
427 | ␊ |
428 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
429 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
430 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
431 | ␉{␊ |
432 | ␉␉printf("Unable to locate _panic\n");␊ |
433 | ␉␉return;␊ |
434 | ␉}␊ |
435 | ␉panicAddr -= (UInt32)kernelData;␊ |
436 | ␊ |
437 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
438 | ␉while( ␊ |
439 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
440 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
441 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
442 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
443 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
444 | ␉␉ )␊ |
445 | ␉{␊ |
446 | ␉␉patchLocation++;␊ |
447 | ␉}␊ |
448 | ␉patchLocation--;␊ |
449 | ␉␊ |
450 | ␉// Remove panic call, just in case the following patch routines fail␊ |
451 | ␉bytes[patchLocation + 0] = 0x90;␊ |
452 | ␉bytes[patchLocation + 1] = 0x90;␊ |
453 | ␉bytes[patchLocation + 2] = 0x90;␊ |
454 | ␉bytes[patchLocation + 3] = 0x90;␊ |
455 | ␉bytes[patchLocation + 4] = 0x90;␊ |
456 | ␊ |
457 | ␉// Locate the jump call, so that 10 bytes can be reclamed.␊ |
458 | ␉// NOTE: This will *NOT* be located on pre 10.6.2 kernels␊ |
459 | ␉jumpLocation = patchLocation - 15;␊ |
460 | ␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
461 | ␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&␊ |
462 | ␉␉ (patchLocation - jumpLocation) < 0xF0)␊ |
463 | ␉{␊ |
464 | ␉␉jumpLocation--;␊ |
465 | ␉}␊ |
466 | ␉␊ |
467 | ␉// If found... AND we want to impersonate a specific cpumodel / family...␊ |
468 | ␉if(impersonateFamily &&␊ |
469 | ␉ impersonateModel &&␊ |
470 | ␉ ((patchLocation - jumpLocation) < 0xF0))␊ |
471 | ␉{␊ |
472 | ␉␉␊ |
473 | ␉␉bytes[jumpLocation] -= 10;␉␉// sizeof(movl␉$0x6b5a4cd2,0x00872eb4) = 10bytes␊ |
474 | ␉␉␊ |
475 | ␉␉/* ␊ |
476 | ␉␉ * Inpersonate the specified CPU FAMILY and CPU Model␊ |
477 | ␉␉ */␊ |
478 | ␉␉␊ |
479 | ␉␉// bytes[patchLocation - 17] = 0xC7;␉// already here... not needed to be done␊ |
480 | ␉␉// bytes[patchLocation - 16] = 0x05;␉// see above␊ |
481 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 15] << 0 |␊ |
482 | ␉␉bytes[patchLocation - 14] << 8 |␊ |
483 | ␉␉bytes[patchLocation - 13] << 16 |␊ |
484 | ␉␉bytes[patchLocation - 12] << 24;␊ |
485 | ␉␉␊ |
486 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
487 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299; ␊ |
488 | ␊ |
489 | ␉␉// cpufamily␊ |
490 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;␊ |
491 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
492 | ␉␉bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
493 | ␉␉bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;␊ |
494 | ␉␉␊ |
495 | ␉␉// NOPS, just in case if the jmp call wasn't patched, we'll jump to a␊ |
496 | ␉␉// nop and continue with the rest of the patch␊ |
497 | ␉␉// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few␊ |
498 | ␉␉// from the above code (only cpuid_model needs to be set.␊ |
499 | ␉␉bytes[patchLocation - 7] = 0x90;␊ |
500 | ␉␉bytes[patchLocation - 6] = 0x90;␊ |
501 | ␉␉␊ |
502 | ␉␉bytes[patchLocation - 5] = 0xC7;␊ |
503 | ␉␉bytes[patchLocation - 4] = 0x05;␊ |
504 | ␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
505 | ␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
506 | ␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
507 | ␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
508 | ␉␉␊ |
509 | ␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
510 | ␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
511 | ␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
512 | ␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
513 | ␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
514 | ␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
515 | ␉}␊ |
516 | ␉else if(impersonateFamily && impersonateModel)␊ |
517 | ␉{␊ |
518 | ␉␉// pre 10.6.2 kernel␊ |
519 | ␉␉// Locate the jump to directly *after* the panic call,␊ |
520 | ␉␉jumpLocation = patchLocation - 4;␊ |
521 | ␉␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
522 | ␉␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&␊ |
523 | ␉␉␉ (patchLocation - jumpLocation) < 0x20)␊ |
524 | ␉␉{␊ |
525 | ␉␉␉jumpLocation--;␊ |
526 | ␉␉}␊ |
527 | ␉␉// NOTE above isn't needed (I was going to use it, but I'm not, so instead,␊ |
528 | ␉␉// I'll just leave it to verify the binary stucture.␊ |
529 | ␉␉␊ |
530 | ␉␉// NOTE: the cpumodel_familt data is not set in _cpuid_set_info␊ |
531 | ␉␉// so we don't need to set it here, I'll get set later based on the model␊ |
532 | ␉␉// we set now.␊ |
533 | ␉␉␊ |
534 | ␉␉if((patchLocation - jumpLocation) < 0x20)␊ |
535 | ␉␉{␊ |
536 | ␉␉␉UInt32 cpuid_model_addr =␉(bytes[patchLocation - 14] << 0 |␊ |
537 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 13] << 8 |␊ |
538 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 12] << 16 |␊ |
539 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 11] << 24);␊ |
540 | ␉␉␉// Remove jump␊ |
541 | ␉␉␉bytes[patchLocation - 9] = 0x90;␉␉/// Was a jump if supported cpu␊ |
542 | ␉␉␉bytes[patchLocation - 8] = 0x90;␉␉// jumped past the panic call, we want to override the panic␊ |
543 | ␉␉␉␊ |
544 | ␉␉␉bytes[patchLocation - 7] = 0x90;␊ |
545 | ␉␉␉bytes[patchLocation - 6] = 0x90;␊ |
546 | ␉␉␉␊ |
547 | ␉␉␉bytes[patchLocation - 5] = 0xC7;␊ |
548 | ␉␉␉bytes[patchLocation - 4] = 0x05;␊ |
549 | ␉␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
550 | ␉␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
551 | ␉␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
552 | ␉␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
553 | ␉␉␉␊ |
554 | ␉␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
555 | ␉␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
556 | ␉␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
557 | ␉␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
558 | ␉␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
559 | ␉␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
560 | ␊ |
561 | ␉␉␉patchLocation = jumpLocation;␊ |
562 | ␉␉␉// We now have 14 bytes available for a patch␊ |
563 | ␉␉}␊ |
564 | ␉␉else ␊ |
565 | ␉␉{␊ |
566 | ␉␉␉// Patching failed, using NOP replacement done initialy␊ |
567 | ␉␉}␊ |
568 | ␉}␊ |
569 | ␉else ␊ |
570 | ␉{␊ |
571 | ␉␉// Either We were unable to change the jump call due to the function's sctructure␊ |
572 | ␉␉// changing, or the user did not request a patch. As such, resort to just ␊ |
573 | ␉␉// removing the panic call (using NOP replacement above). Note that the␊ |
574 | ␉␉// IntelCPUPM kext may still panic due to the cpu's Model ID not being patched␊ |
575 | ␉}␊ |
576 | }␊ |
577 | ␊ |
578 | /**␊ |
579 | ** SleepEnabler.kext replacement (for those that need it)␊ |
580 | ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS␊ |
581 | **/␊ |
582 | #if 0␊ |
583 | static void patch_pmCPUExitHaltToOff(void* kernelData)␊ |
584 | {␊ |
585 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
586 | ␊ |
587 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_PmCpuExitHaltToOff");␊ |
588 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0;␊ |
589 | ␉␊ |
590 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
591 | ␉{␊ |
592 | ␉␉printf("Unable to locate _pmCPUExitHaltToOff\n");␊ |
593 | ␉␉return;␊ |
594 | ␉}␊ |
595 | ␉␊ |
596 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
597 | ␊ |
598 | ␉while(bytes[patchLocation - 1]␉!= 0xB8 ||␊ |
599 | ␉␉ bytes[patchLocation]␉␉!= 0x04 ||␉// KERN_INVALID_ARGUMENT (0x00000004)␊ |
600 | ␉␉ bytes[patchLocation + 1]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
601 | ␉␉ bytes[patchLocation + 2]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
602 | ␉␉ bytes[patchLocation + 3]␉!= 0x00)␉// KERN_INVALID_ARGUMENT␊ |
603 | ␊ |
604 | ␉{␊ |
605 | ␉␉patchLocation++;␊ |
606 | ␉}␊ |
607 | ␉bytes[patchLocation] = 0x00;␉// KERN_SUCCESS;␊ |
608 | }␊ |
609 | #endif␊ |
610 | ␊ |
611 | static void patch_lapic_init(void* kernelData)␊ |
612 | {␊ |
613 | ␉UInt8 panicIndex = 0;␊ |
614 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
615 | ␉␊ |
616 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_init");␊ |
617 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; ␊ |
618 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
619 | ␉{␊ |
620 | ␉␉printf("Unable to locate %s\n", "_lapic_init");␊ |
621 | ␉␉return;␊ |
622 | ␉}␊ |
623 | ␉␊ |
624 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
625 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; ␊ |
626 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
627 | ␉{␊ |
628 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
629 | ␉␉return;␊ |
630 | ␉}␊ |
631 | ␉␊ |
632 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
633 | ␉panicAddr -= (UInt32)kernelData;␉// Remove offset␊ |
634 | ␊ |
635 | ␉// Locate the (panicIndex + 1) panic call␊ |
636 | ␉while(panicIndex < 3)␉// Find the third panic call␊ |
637 | ␉{␊ |
638 | ␉␉while( ␊ |
639 | ␉␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
640 | ␉␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
641 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
642 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
643 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
644 | ␉␉␉ )␊ |
645 | ␉␉{␊ |
646 | ␉␉␉patchLocation++;␊ |
647 | ␉␉}␊ |
648 | ␉␉patchLocation++;␊ |
649 | ␉␉panicIndex++;␊ |
650 | ␉}␊ |
651 | ␉patchLocation--;␉// Remove extra increment from the < 3 while loop␊ |
652 | ␉␊ |
653 | ␉bytes[--patchLocation] = 0x90;␉␊ |
654 | ␉bytes[++patchLocation] = 0x90;␊ |
655 | ␉bytes[++patchLocation] = 0x90;␊ |
656 | ␉bytes[++patchLocation] = 0x90;␊ |
657 | ␉bytes[++patchLocation] = 0x90;␊ |
658 | }␊ |
659 | ␊ |
660 | static void patch_commpage_stuff_routine(void* kernelData)␊ |
661 | {␊ |
662 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
663 | ␊ |
664 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_commpage_stuff_routine");␊ |
665 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
666 | ␉{␊ |
667 | ␉␉//printf("Unable to locate %s\n", "_commpage_stuff_routine");␊ |
668 | ␉␉return;␊ |
669 | ␉␉␊ |
670 | ␉}␊ |
671 | ␉␊ |
672 | ␉UInt32 patchLocation = symbol->addr - textAddress + textSection; ␊ |
673 | ␊ |
674 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
675 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
676 | ␉{␊ |
677 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
678 | ␉␉return;␊ |
679 | ␉}␊ |
680 | ␉UInt32 panicAddr = symbol->addr - textAddress; ␊ |
681 | ␊ |
682 | ␉patchLocation -= (UInt32)kernelData;␊ |
683 | ␉panicAddr -= (UInt32)kernelData;␊ |
684 | ␉␊ |
685 | ␉while( ␊ |
686 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
687 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
688 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
689 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
690 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
691 | ␉␉ )␊ |
692 | ␉{␊ |
693 | ␉␉patchLocation++;␊ |
694 | ␉}␊ |
695 | ␉patchLocation--;␊ |
696 | ␉␊ |
697 | ␉// Replace panic with nops␊ |
698 | ␉bytes[patchLocation + 0] = 0x90;␊ |
699 | ␉bytes[patchLocation + 1] = 0x90;␊ |
700 | ␉bytes[patchLocation + 2] = 0x90;␊ |
701 | ␉bytes[patchLocation + 3] = 0x90;␊ |
702 | ␉bytes[patchLocation + 4] = 0x90;␊ |
703 | }␊ |
704 | #if 0␊ |
705 | static void patch_lapic_interrupt(void* kernelData)␊ |
706 | {␊ |
707 | ␉// NOTE: this is a hack untill I finish patch_lapic_configure␊ |
708 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
709 | ␊ |
710 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_interrupt");␊ |
711 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
712 | ␉{␊ |
713 | ␉␉printf("Unable to locate %s\n", "_lapic_interrupt");␊ |
714 | ␉␉return;␊ |
715 | ␉}␊ |
716 | ␊ |
717 | ␉UInt32 patchLocation = symbol->addr - textAddress + textSection; ␊ |
718 | ␊ |
719 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
720 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
721 | ␉{␊ |
722 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
723 | ␉␉return;␊ |
724 | ␉}␊ |
725 | ␉UInt32 panicAddr = symbol->addr - textAddress; ␊ |
726 | ␉␊ |
727 | ␉patchLocation -= (UInt32)kernelData;␊ |
728 | ␉panicAddr -= (UInt32)kernelData;␊ |
729 | ␉␊ |
730 | ␉while( ␊ |
731 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
732 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
733 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
734 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
735 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
736 | ␉␉ )␊ |
737 | ␉{␊ |
738 | ␉␉patchLocation++;␊ |
739 | ␉}␊ |
740 | ␉patchLocation--;␊ |
741 | ␉␊ |
742 | ␉// Replace panic with nops␊ |
743 | ␉bytes[patchLocation + 0] = 0x90;␊ |
744 | ␉bytes[patchLocation + 1] = 0x90;␊ |
745 | ␉bytes[patchLocation + 2] = 0x90;␊ |
746 | ␉bytes[patchLocation + 3] = 0x90;␊ |
747 | ␉bytes[patchLocation + 4] = 0x90;␊ |
748 | }␊ |
749 | #endif␊ |
750 | static void patch_lapic_configure(void* kernelData)␊ |
751 | {␊ |
752 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
753 | ␉␊ |
754 | ␉UInt32 patchLocation;␊ |
755 | ␉UInt32 lapicStart;␊ |
756 | ␉UInt32 lapicInterruptBase;␊ |
757 | ␉␊ |
758 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_configure");␊ |
759 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
760 | ␉{␊ |
761 | ␉␉printf("Unable to locate %s\n", "_lapic_configure");␊ |
762 | ␉␉return;␊ |
763 | ␉}␊ |
764 | ␉patchLocation = symbol->addr - textAddress + textSection; ␊ |
765 | ␉␊ |
766 | ␉symbol = lookup_kernel_symbol("_lapic_start");␊ |
767 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
768 | ␉{␊ |
769 | ␉␉printf("Unable to locate %s\n", "_lapic_start");␊ |
770 | ␉␉return;␊ |
771 | ␉}␊ |
772 | ␉lapicStart = symbol->addr; ␊ |
773 | ␊ |
774 | ␉symbol = lookup_kernel_symbol("_lapic_interrupt_base");␊ |
775 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
776 | ␉{␊ |
777 | ␉␉printf("Unable to locate %s\n", "_lapic_interrupt_base");␊ |
778 | ␉␉return;␊ |
779 | ␉}␊ |
780 | ␉lapicInterruptBase = symbol->addr;␊ |
781 | ␉patchLocation -= (UInt32)kernelData;␊ |
782 | ␉lapicStart -= (UInt32)kernelData;␊ |
783 | ␉lapicInterruptBase -= (UInt32)kernelData;␊ |
784 | ␉␊ |
785 | ␉// Looking for the following:␊ |
786 | ␉//movl _lapic_start,%e_x␊ |
787 | ␉//addl $0x00000320,%e_x␊ |
788 | ␉// 8b 15 __ __ __ __ 81 c2 20 03 00 00␊ |
789 | ␉while( ␊ |
790 | ␉␉ (bytes[patchLocation - 2] != 0x8b) ||␊ |
791 | ␉␉ //bytes[patchLocation -1] != 0x15) ||␉// Register, we don't care what it is␊ |
792 | ␉␉ ( lapicStart != (UInt32)(␊ |
793 | ␉␉␉␉␉␉␉␉␉(bytes[patchLocation + 0] << 0 | ␊ |
794 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 1] << 8 | ␊ |
795 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 2] << 16 |␊ |
796 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 3] << 24␊ |
797 | ␉␉␉␉␉␉␉␉␉)␊ |
798 | ␉␉␉␉␉␉␉␉ )␊ |
799 | ␉␉ ) || ␊ |
800 | ␉␉ (bytes[patchLocation + 4 ] != 0x81) ||␊ |
801 | ␉␉ //(bytes[patchLocation + 5 ] != 0Cx2) ||␉// register␊ |
802 | ␉␉ (bytes[patchLocation + 6 ] != 0x20) ||␊ |
803 | ␉␉ (bytes[patchLocation + 7 ] != 0x03) ||␊ |
804 | ␉␉ (bytes[patchLocation + 8 ] != 0x00) ||␊ |
805 | ␉␉ (bytes[patchLocation + 9] != 0x00)␊ |
806 | ␊ |
807 | ␉␉ )␊ |
808 | ␉{␊ |
809 | ␉␉patchLocation++;␊ |
810 | ␉}␊ |
811 | ␉patchLocation-=2;␊ |
812 | ␊ |
813 | ␉// NOTE: this is currently hardcoded, change it to be more resilient to changes␊ |
814 | ␉// At a minimum, I should have this do a cheksup first and if not matching, remove the panic instead.␊ |
815 | ␉␊ |
816 | ␉// 8b 15 __ __ __ __ -> movl␉␉ _lapic_start,%edx (NOTE: this should already be here)␊ |
817 | ␉/*␊ |
818 | ␉bytes[patchLocation++] = 0x8B;␊ |
819 | ␉bytes[patchLocation++] = 0x15;␊ |
820 | ␉bytes[patchLocation++] = (lapicStart & 0x000000FF) >> 0;␊ |
821 | ␉bytes[patchLocation++] = (lapicStart & 0x0000FF00) >> 8;␊ |
822 | ␉bytes[patchLocation++] = (lapicStart & 0x00FF0000) >> 16;␊ |
823 | ␉bytes[patchLocation++] = (lapicStart & 0xFF000000) >> 24;␊ |
824 | ␉*/␊ |
825 | ␉patchLocation += 6;␊ |
826 | ␉␊ |
827 | ␉// 81 c2 60 03 00 00 -> addl␉␉ $0x00000320,%edx␊ |
828 | ␉/*␊ |
829 | ␉bytes[patchLocation++] = 0x81;␊ |
830 | ␉bytes[patchLocation++] = 0xC2;␊ |
831 | ␉*/␊ |
832 | ␉patchLocation += 2;␊ |
833 | ␉bytes[patchLocation++] = 0x60;␊ |
834 | ␉/*␊ |
835 | ␉bytes[patchLocation++];// = 0x03;␊ |
836 | ␉bytes[patchLocation++];// = 0x00;␊ |
837 | ␉bytes[patchLocation++];// = 0x00;␊ |
838 | ␉*/␊ |
839 | ␉patchLocation += 3;␊ |
840 | ␊ |
841 | ␉// c7 02 00 04 00 00 -> movl␉␉ $0x00000400,(%edx)␊ |
842 | ␉bytes[patchLocation++] = 0xC7;␊ |
843 | ␉bytes[patchLocation++] = 0x02;␊ |
844 | ␉bytes[patchLocation++] = 0x00;␊ |
845 | ␉bytes[patchLocation++] = 0x04;␊ |
846 | ␉bytes[patchLocation++] = 0x00;␊ |
847 | ␉bytes[patchLocation++] = 0x00;␊ |
848 | ␉␊ |
849 | ␉// 83 ea 40 -> subl␉␉ $0x40,edx␊ |
850 | ␉bytes[patchLocation++] = 0x83;␊ |
851 | ␉bytes[patchLocation++] = 0xEA;␊ |
852 | ␉bytes[patchLocation++] = 0x40;␊ |
853 | ␊ |
854 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
855 | ␉bytes[patchLocation++] = 0xA1;␊ |
856 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
857 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
858 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
859 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
860 | ␊ |
861 | ␉// 83 c0 0e -> addl␉␉ $0x0e,%eax␊ |
862 | ␉bytes[patchLocation++] = 0x83;␊ |
863 | ␉bytes[patchLocation++] = 0xC0;␊ |
864 | ␉bytes[patchLocation++] = 0x0E;␊ |
865 | ␊ |
866 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
867 | ␉bytes[patchLocation++] = 0x89;␊ |
868 | ␉bytes[patchLocation++] = 0x02;␊ |
869 | ␉␊ |
870 | ␉// 81c230030000␉␉ addl␉␉ $0x00000330,%edx␊ |
871 | ␉bytes[patchLocation++] = 0x81;␊ |
872 | ␉bytes[patchLocation++] = 0xC2;␊ |
873 | ␉bytes[patchLocation++] = 0x30;␊ |
874 | ␉bytes[patchLocation++] = 0x03;␊ |
875 | ␉bytes[patchLocation++] = 0x00;␊ |
876 | ␉bytes[patchLocation++] = 0x00;␊ |
877 | ␉␊ |
878 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
879 | ␉bytes[patchLocation++] = 0xA1;␊ |
880 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
881 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
882 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
883 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
884 | ␉␊ |
885 | ␉// 83 c0 0f -> addl␉␉ $0x0f,%eax␊ |
886 | ␉bytes[patchLocation++] = 0x83;␊ |
887 | ␉bytes[patchLocation++] = 0xC0;␊ |
888 | ␉bytes[patchLocation++] = 0x0F;␊ |
889 | ␉␊ |
890 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
891 | ␉bytes[patchLocation++] = 0x89;␊ |
892 | ␉bytes[patchLocation++] = 0x02;␊ |
893 | ␉␊ |
894 | ␉// 83 ea 10 -> subl␉␉ $0x10,edx␊ |
895 | ␉bytes[patchLocation++] = 0x83;␊ |
896 | ␉bytes[patchLocation++] = 0xEA;␊ |
897 | ␉bytes[patchLocation++] = 0x10;␊ |
898 | ␊ |
899 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
900 | ␉bytes[patchLocation++] = 0xA1;␊ |
901 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
902 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
903 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
904 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
905 | ␉␊ |
906 | ␉// 83 c0 0c -> addl␉␉ $0x0c,%eax␊ |
907 | ␉bytes[patchLocation++] = 0x83;␊ |
908 | ␉bytes[patchLocation++] = 0xC0;␊ |
909 | ␉bytes[patchLocation++] = 0x0C;␊ |
910 | ␊ |
911 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
912 | ␉bytes[patchLocation++] = 0x89;␊ |
913 | ␉bytes[patchLocation++] = 0x02;␊ |
914 | ␊ |
915 | ␉// Replace remaining with nops␊ |
916 | ␊ |
917 | ␉bytes[patchLocation++] = 0x90;␊ |
918 | ␉bytes[patchLocation++] = 0x90;␊ |
919 | ␉bytes[patchLocation++] = 0x90;␊ |
920 | ␉bytes[patchLocation++] = 0x90;␊ |
921 | ␉//␉bytes[patchLocation++] = 0x90; // double check the lenght of the patch...␊ |
922 | ␉//␉bytes[patchLocation++] = 0x90;␊ |
923 | }␊ |
924 | |