Chameleon

Chameleon Svn Source Tree

Root/branches/slice/trunkM/i386/modules/KernelPatcher/kernel_patcher.c

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

Archive Download this file

Revision: 1207