Chameleon

Chameleon Svn Source Tree

Root/branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c

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

Archive Download this file

Revision: 540