Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 491