Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 742