Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 689