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

Archive Download this file

Revision: 506