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

Archive Download this file

Revision: 1047