Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 515