Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1144