Chameleon

Chameleon Svn Source Tree

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

Source at commit 548 created 13 years 7 months ago.
By meklort, Bugfixes (hpet, gui, etc)
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
223if(symbol)
224{
225symbol->addr = addr;
226}
227
228return 0xFFFFFFFF; // fixme
229}
230
231
232/**
233 ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it
234 ** Or replace it so that the cpuid is set to a valid value.
235 **/
236void patch_cpuid_set_info_all(void* kernelData)
237{
238switch(Platform->CPU.Model)
239{
240case CPUID_MODEL_ATOM:
241if(determineKernelArchitecture(kernelData) == KERNEL_32)
242{
243patch_cpuid_set_info_32(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);
244}
245else
246{
247patch_cpuid_set_info_64(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);
248
249}
250
251break;
252
253default:
254if(determineKernelArchitecture(kernelData) == KERNEL_32)
255{
256patch_cpuid_set_info_32(kernelData, 0, 0);
257}
258else
259{
260patch_cpuid_set_info_64(kernelData, 0, 0);
261}
262
263break;
264}
265}
266void patch_cpuid_set_info_64(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)
267{
268UInt8* bytes = (UInt8*)kernelData;
269
270kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");
271
272UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);
273patchLocation -= (UInt32)kernelData;// Remove offset
274
275
276
277//UInt32 jumpLocation = 0;
278
279
280if(symbol == 0 || symbol->addr == 0)
281{
282printf("Unable to locate _cpuid_set_info\n");
283return;
284
285}
286
287symbol = lookup_kernel_symbol("_panic");
288UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;
289if(symbol == 0 || symbol->addr == 0)
290{
291printf("Unable to locate _panic\n");
292return;
293}
294panicAddr -= (UInt32)kernelData;
295
296
297
298//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)
299while(
300 (bytes[patchLocation -1] != 0xE8) ||
301 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
302bytes[patchLocation + 1] << 8 |
303bytes[patchLocation + 2] << 16 |
304bytes[patchLocation + 3] << 24)))
305 )
306{
307patchLocation++;
308}
309patchLocation--;
310
311// Remove panic just in ca se
312// The panic instruction is exactly 5 bytes long.
313bytes[patchLocation + 0] = 0x90;
314bytes[patchLocation + 1] = 0x90;
315bytes[patchLocation + 2] = 0x90;
316bytes[patchLocation + 3] = 0x90;
317bytes[patchLocation + 4] = 0x90;
318
319
320
321// Check for a 10.2.0+ kernel
322if(bytes[patchLocation - 19] == 0xC7 && bytes[patchLocation - 18] == 0x05)
323{
324
325UInt32 cpuid_cpufamily_addr =bytes[patchLocation - 17] << 0 |
326bytes[patchLocation - 16] << 8 |
327bytes[patchLocation - 15] << 16 |
328bytes[patchLocation - 14] << 24;
329
330// NOTE: may change, determined based on cpuid_info struct
331UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 310;
332
333
334//ffffff8000228b3b -> 0x00490e8b
335//ffffff8000228c28 -> -237 -> 0x490D9E -> -310
336
337
338// The mov is 10 bytes
339/*
340 bytes[patchLocation - 19] = 0x90;// c7
341 bytes[patchLocation - 18] = 0x90;// 05
342 bytes[patchLocation - 17] = 0x90;// family location
343 bytes[patchLocation - 16] = 0x90;// family location
344 bytes[patchLocation - 15] = 0x90;// family location
345 bytes[patchLocation - 14] = 0x90;// family location
346 */
347bytes[patchLocation - 13] = (impersonateFamily & 0x000000FF) >> 0;
348bytes[patchLocation - 12] = (impersonateFamily & 0x0000FF00) >> 8;
349bytes[patchLocation - 11] = (impersonateFamily & 0x00FF0000) >> 16;
350bytes[patchLocation - 10] = (impersonateFamily & 0xFF000000) >> 24;
351
352
353// The lea (%rip),%rip is 7 bytes
354bytes[patchLocation - 9] = 0xC7;
355bytes[patchLocation - 8] = 0x05;
356bytes[patchLocation - 7] = ((cpuid_model_addr -10) & 0x000000FF) >> 0;// NOTE: this opcode is relative in 64bit mode, subtract offset
357bytes[patchLocation - 6] = ((cpuid_model_addr -10) & 0x0000FF00) >> 8;
358bytes[patchLocation - 5] = ((cpuid_model_addr -10) & 0x00FF0000) >> 16;
359bytes[patchLocation - 4] = ((cpuid_model_addr -10) & 0xFF000000) >> 24;
360bytes[patchLocation - 3] = impersonateModel;// cpuid_model
361
362
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
381printf("Running on a 10.2.0+ kernel\n");
382getc();
383
384}
385else {
386printf("Running on a 10.0.0 kernel, patch unsupported\n");
387getc();
388}
389
390
391}
392
393
394
395
396
397void patch_cpuid_set_info_32(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)
398{
399UInt8* bytes = (UInt8*)kernelData;
400
401kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");
402
403UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);
404patchLocation -= (UInt32)kernelData;// Remove offset
405
406
407
408UInt32 jumpLocation = 0;
409
410
411if(symbol == 0 || symbol->addr == 0)
412{
413printf("Unable to locate _cpuid_set_info\n");
414return;
415
416}
417
418symbol = lookup_kernel_symbol("_panic");
419UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;
420if(symbol == 0 || symbol->addr == 0)
421{
422printf("Unable to locate _panic\n");
423return;
424}
425panicAddr -= (UInt32)kernelData;
426
427
428
429//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)
430while(
431 (bytes[patchLocation -1] != 0xE8) ||
432 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
433bytes[patchLocation + 1] << 8 |
434bytes[patchLocation + 2] << 16 |
435bytes[patchLocation + 3] << 24)))
436 )
437{
438patchLocation++;
439}
440patchLocation--;
441
442// Remove panic call, just in case the following patch routines fail
443bytes[patchLocation + 0] = 0x90;
444bytes[patchLocation + 1] = 0x90;
445bytes[patchLocation + 2] = 0x90;
446bytes[patchLocation + 3] = 0x90;
447bytes[patchLocation + 4] = 0x90;
448
449
450// Locate the jump call, so that 10 bytes can be reclamed.
451// NOTE: This will *NOT* be located on pre 10.6.2 kernels
452jumpLocation = patchLocation - 15;
453while((bytes[jumpLocation - 1] != 0x77 ||
454 bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&
455 (patchLocation - jumpLocation) < 0xF0)
456{
457jumpLocation--;
458}
459
460// If found... AND we want to impersonate a specific cpumodel / family...
461if(impersonateFamily &&
462 impersonateModel &&
463 ((patchLocation - jumpLocation) < 0xF0))
464{
465
466bytes[jumpLocation] -= 10;// sizeof(movl$0x6b5a4cd2,0x00872eb4) = 10bytes
467
468/*
469 * Inpersonate the specified CPU FAMILY and CPU Model
470 */
471
472// bytes[patchLocation - 17] = 0xC7;// already here... not needed to be done
473// bytes[patchLocation - 16] = 0x05;// see above
474UInt32 cpuid_cpufamily_addr =bytes[patchLocation - 15] << 0 |
475bytes[patchLocation - 14] << 8 |
476bytes[patchLocation - 13] << 16 |
477bytes[patchLocation - 12] << 24;
478
479// NOTE: may change, determined based on cpuid_info struct
480UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299;
481
482
483// cpufamily
484bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;
485bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;
486bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;
487bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;
488
489// NOPS, just in case if the jmp call wasn't patched, we'll jump to a
490// nop and continue with the rest of the patch
491// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few
492// from the above code (only cpuid_model needs to be set.
493bytes[patchLocation - 7] = 0x90;
494bytes[patchLocation - 6] = 0x90;
495
496bytes[patchLocation - 5] = 0xC7;
497bytes[patchLocation - 4] = 0x05;
498bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;
499bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;
500bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;
501bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;
502
503// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes
504// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.
505bytes[patchLocation + 1] = impersonateModel;// cpuid_model
506bytes[patchLocation + 2] = 0x01;// cpuid_extmodel
507bytes[patchLocation + 3] = 0x00;// cpuid_extfamily
508bytes[patchLocation + 4] = 0x02;// cpuid_stepping
509
510}
511else if(impersonateFamily && impersonateModel)
512{
513// pre 10.6.2 kernel
514// Locate the jump to directly *after* the panic call,
515jumpLocation = patchLocation - 4;
516while((bytes[jumpLocation - 1] != 0x77 ||
517 bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&
518 (patchLocation - jumpLocation) < 0x20)
519{
520jumpLocation--;
521}
522// NOTE above isn't needed (I was going to use it, but I'm not, so instead,
523// I'll just leave it to verify the binary stucture.
524
525// NOTE: the cpumodel_familt data is not set in _cpuid_set_info
526// so we don't need to set it here, I'll get set later based on the model
527// we set now.
528
529if((patchLocation - jumpLocation) < 0x20)
530{
531UInt32 cpuid_model_addr =(bytes[patchLocation - 14] << 0 |
532 bytes[patchLocation - 13] << 8 |
533 bytes[patchLocation - 12] << 16 |
534 bytes[patchLocation - 11] << 24);
535// Remove jump
536bytes[patchLocation - 9] = 0x90;/// Was a jump if supported cpu
537bytes[patchLocation - 8] = 0x90;// jumped past the panic call, we want to override the panic
538
539bytes[patchLocation - 7] = 0x90;
540bytes[patchLocation - 6] = 0x90;
541
542bytes[patchLocation - 5] = 0xC7;
543bytes[patchLocation - 4] = 0x05;
544bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;
545bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;
546bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;
547bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;
548
549// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes
550// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.
551bytes[patchLocation + 1] = impersonateModel;// cpuid_model
552bytes[patchLocation + 2] = 0x01;// cpuid_extmodel
553bytes[patchLocation + 3] = 0x00;// cpuid_extfamily
554bytes[patchLocation + 4] = 0x02;// cpuid_stepping
555
556
557
558patchLocation = jumpLocation;
559// We now have 14 bytes available for a patch
560
561}
562else
563{
564// Patching failed, using NOP replacement done initialy
565}
566}
567else
568{
569// Either We were unable to change the jump call due to the function's sctructure
570// changing, or the user did not request a patch. As such, resort to just
571// removing the panic call (using NOP replacement above). Note that the
572// IntelCPUPM kext may still panic due to the cpu's Model ID not being patched
573}
574}
575
576
577/**
578 ** SleepEnabler.kext replacement (for those that need it)
579 ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS
580 **/
581void patch_pmCPUExitHaltToOff(void* kernelData)
582{
583UInt8* bytes = (UInt8*)kernelData;
584
585kernSymbols_t *symbol = lookup_kernel_symbol("_PmCpuExitHaltToOff");
586UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0;
587
588if(symbol == 0 || symbol->addr == 0)
589{
590printf("Unable to locate _pmCPUExitHaltToOff\n");
591return;
592}
593
594patchLocation -= (UInt32)kernelData;// Remove offset
595
596
597
598while(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{
605patchLocation++;
606}
607bytes[patchLocation] = 0x00;// KERN_SUCCESS;
608}
609
610void patch_lapic_init(void* kernelData)
611{
612
613UInt8 panicIndex = 0;
614UInt8* bytes = (UInt8*)kernelData;
615
616kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_init");
617UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0;
618if(symbol == 0 || symbol->addr == 0)
619{
620printf("Unable to locate %s\n", "_lapic_init");
621return;
622
623}
624
625symbol = lookup_kernel_symbol("_panic");
626UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0;
627if(symbol == 0 || symbol->addr == 0)
628{
629printf("Unable to locate %s\n", "_panic");
630return;
631}
632
633patchLocation -= (UInt32)kernelData;// Remove offset
634panicAddr -= (UInt32)kernelData;// Remove offset
635
636
637
638
639// Locate the (panicIndex + 1) panic call
640while(panicIndex < 3)// Find the third panic call
641{
642while(
643 (bytes[patchLocation -1] != 0xE8) ||
644 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
645bytes[patchLocation + 1] << 8 |
646bytes[patchLocation + 2] << 16 |
647bytes[patchLocation + 3] << 24)))
648 )
649{
650patchLocation++;
651}
652patchLocation++;
653panicIndex++;
654}
655patchLocation--;// Remove extra increment from the < 3 while loop
656
657bytes[--patchLocation] = 0x90;
658bytes[++patchLocation] = 0x90;
659bytes[++patchLocation] = 0x90;
660bytes[++patchLocation] = 0x90;
661bytes[++patchLocation] = 0x90;
662
663
664}
665
666
667void patch_commpage_stuff_routine(void* kernelData)
668{
669UInt8* bytes = (UInt8*)kernelData;
670
671kernSymbols_t *symbol = lookup_kernel_symbol("_commpage_stuff_routine");
672if(symbol == 0 || symbol->addr == 0)
673{
674//printf("Unable to locate %s\n", "_commpage_stuff_routine");
675return;
676
677}
678
679UInt32 patchLocation = symbol->addr - textAddress + textSection;
680
681
682symbol = lookup_kernel_symbol("_panic");
683if(symbol == 0 || symbol->addr == 0)
684{
685printf("Unable to locate %s\n", "_panic");
686return;
687}
688UInt32 panicAddr = symbol->addr - textAddress;
689
690patchLocation -= (UInt32)kernelData;
691panicAddr -= (UInt32)kernelData;
692
693while(
694 (bytes[patchLocation -1] != 0xE8) ||
695 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
696bytes[patchLocation + 1] << 8 |
697bytes[patchLocation + 2] << 16 |
698bytes[patchLocation + 3] << 24)))
699 )
700{
701patchLocation++;
702}
703patchLocation--;
704
705// Replace panic with nops
706bytes[patchLocation + 0] = 0x90;
707bytes[patchLocation + 1] = 0x90;
708bytes[patchLocation + 2] = 0x90;
709bytes[patchLocation + 3] = 0x90;
710bytes[patchLocation + 4] = 0x90;
711
712
713}
714
715void patch_lapic_interrupt(void* kernelData)
716{
717// NOTE: this is a hack untill I finish patch_lapic_configure
718UInt8* bytes = (UInt8*)kernelData;
719
720kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_interrupt");
721if(symbol == 0 || symbol->addr == 0)
722{
723printf("Unable to locate %s\n", "_lapic_interrupt");
724return;
725
726}
727
728UInt32 patchLocation = symbol->addr - textAddress + textSection;
729
730
731symbol = lookup_kernel_symbol("_panic");
732if(symbol == 0 || symbol->addr == 0)
733{
734printf("Unable to locate %s\n", "_panic");
735return;
736}
737UInt32 panicAddr = symbol->addr - textAddress;
738
739patchLocation -= (UInt32)kernelData;
740panicAddr -= (UInt32)kernelData;
741
742while(
743 (bytes[patchLocation -1] != 0xE8) ||
744 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
745bytes[patchLocation + 1] << 8 |
746bytes[patchLocation + 2] << 16 |
747bytes[patchLocation + 3] << 24)))
748 )
749{
750patchLocation++;
751}
752patchLocation--;
753
754// Replace panic with nops
755bytes[patchLocation + 0] = 0x90;
756bytes[patchLocation + 1] = 0x90;
757bytes[patchLocation + 2] = 0x90;
758bytes[patchLocation + 3] = 0x90;
759bytes[patchLocation + 4] = 0x90;
760
761
762}
763
764
765void patch_lapic_configure(void* kernelData)
766{
767UInt8* bytes = (UInt8*)kernelData;
768
769UInt32 patchLocation;
770UInt32 lapicStart;
771UInt32 lapicInterruptBase;
772
773kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_configure");
774if(symbol == 0 || symbol->addr == 0)
775{
776printf("Unable to locate %s\n", "_lapic_configure");
777return;
778}
779patchLocation = symbol->addr - textAddress + textSection;
780
781symbol = lookup_kernel_symbol("_lapic_start");
782if(symbol == 0 || symbol->addr == 0)
783{
784printf("Unable to locate %s\n", "_lapic_start");
785return;
786}
787lapicStart = symbol->addr;
788
789
790symbol = lookup_kernel_symbol("_lapic_interrupt_base");
791if(symbol == 0 || symbol->addr == 0)
792{
793printf("Unable to locate %s\n", "_lapic_interrupt_base");
794return;
795}
796lapicInterruptBase = symbol->addr;
797patchLocation -= (UInt32)kernelData;
798lapicStart -= (UInt32)kernelData;
799lapicInterruptBase -= (UInt32)kernelData;
800
801
802// Looking for the following:
803//movl _lapic_start,%e_x
804//addl $0x00000320,%e_x
805// 8b 15 __ __ __ __ 81 c2 20 03 00 00
806while(
807 (bytes[patchLocation - 2] != 0x8b) ||
808 //bytes[patchLocation -1] != 0x15) ||// Register, we don't care what it is
809 ( lapicStart != (UInt32)(
810(bytes[patchLocation + 0] << 0 |
811 bytes[patchLocation + 1] << 8 |
812 bytes[patchLocation + 2] << 16 |
813 bytes[patchLocation + 3] << 24
814)
815 )
816 ) ||
817 (bytes[patchLocation + 4 ] != 0x81) ||
818 //(bytes[patchLocation + 5 ] != 0Cx2) ||// register
819 (bytes[patchLocation + 6 ] != 0x20) ||
820 (bytes[patchLocation + 7 ] != 0x03) ||
821 (bytes[patchLocation + 8 ] != 0x00) ||
822 (bytes[patchLocation + 9] != 0x00)
823
824 )
825{
826patchLocation++;
827}
828patchLocation-=2;
829
830// NOTE: this is currently hardcoded, change it to be more resilient to changes
831// At a minimum, I should have this do a cheksup first and if not matching, remove the panic instead.
832
833// 8b 15 __ __ __ __ -> movl _lapic_start,%edx (NOTE: this should already be here)
834/*
835bytes[patchLocation++] = 0x8B;
836bytes[patchLocation++] = 0x15;
837bytes[patchLocation++] = (lapicStart & 0x000000FF) >> 0;
838bytes[patchLocation++] = (lapicStart & 0x0000FF00) >> 8;
839bytes[patchLocation++] = (lapicStart & 0x00FF0000) >> 16;
840bytes[patchLocation++] = (lapicStart & 0xFF000000) >> 24;
841*/
842patchLocation += 6;
843
844// 81 c2 60 03 00 00 -> addl $0x00000320,%edx
845/*
846bytes[patchLocation++] = 0x81;
847bytes[patchLocation++] = 0xC2;
848*/
849patchLocation += 2;
850bytes[patchLocation++] = 0x60;
851/*
852bytes[patchLocation++];// = 0x03;
853bytes[patchLocation++];// = 0x00;
854bytes[patchLocation++];// = 0x00;
855*/
856 patchLocation += 3;
857
858// c7 02 00 04 00 00 -> movl $0x00000400,(%edx)
859bytes[patchLocation++] = 0xC7;
860bytes[patchLocation++] = 0x02;
861bytes[patchLocation++] = 0x00;
862bytes[patchLocation++] = 0x04;
863bytes[patchLocation++] = 0x00;
864bytes[patchLocation++] = 0x00;
865
866// 83 ea 40 -> subl $0x40,edx
867bytes[patchLocation++] = 0x83;
868bytes[patchLocation++] = 0xEA;
869bytes[patchLocation++] = 0x40;
870
871// a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax
872bytes[patchLocation++] = 0xA1;
873bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;
874bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;
875bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;
876bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;
877
878// 83 c0 0e -> addl $0x0e,%eax
879bytes[patchLocation++] = 0x83;
880bytes[patchLocation++] = 0xC0;
881bytes[patchLocation++] = 0x0E;
882
883// 89 02 -> movl %eax,(%edx)
884bytes[patchLocation++] = 0x89;
885bytes[patchLocation++] = 0x02;
886
887// 81c230030000 addl $0x00000330,%edx
888bytes[patchLocation++] = 0x81;
889bytes[patchLocation++] = 0xC2;
890bytes[patchLocation++] = 0x30;
891bytes[patchLocation++] = 0x03;
892bytes[patchLocation++] = 0x00;
893bytes[patchLocation++] = 0x00;
894
895// a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax
896bytes[patchLocation++] = 0xA1;
897bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;
898bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;
899bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;
900bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;
901
902// 83 c0 0f -> addl $0x0f,%eax
903bytes[patchLocation++] = 0x83;
904bytes[patchLocation++] = 0xC0;
905bytes[patchLocation++] = 0x0F;
906
907// 89 02 -> movl %eax,(%edx)
908bytes[patchLocation++] = 0x89;
909bytes[patchLocation++] = 0x02;
910
911// 83 ea 10 -> subl $0x10,edx
912bytes[patchLocation++] = 0x83;
913bytes[patchLocation++] = 0xEA;
914bytes[patchLocation++] = 0x10;
915
916// a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax
917bytes[patchLocation++] = 0xA1;
918bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;
919bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;
920bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;
921bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;
922
923// 83 c0 0c -> addl $0x0c,%eax
924bytes[patchLocation++] = 0x83;
925bytes[patchLocation++] = 0xC0;
926bytes[patchLocation++] = 0x0C;
927
928// 89 02 -> movl %eax,(%edx)
929bytes[patchLocation++] = 0x89;
930bytes[patchLocation++] = 0x02;
931
932// Replace remaining with nops
933
934
935bytes[patchLocation++] = 0x90;
936bytes[patchLocation++] = 0x90;
937bytes[patchLocation++] = 0x90;
938bytes[patchLocation++] = 0x90;
939//bytes[patchLocation++] = 0x90; // double check the lenght of the patch...
940//bytes[patchLocation++] = 0x90;
941}
942

Archive Download this file

Revision: 548