Chameleon

Chameleon Svn Source Tree

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

Source at commit 1166 created 13 years 10 days ago.
By meklort, Fixed recent Makefile changes. Please do not use /Users/evan/SourceCode/tmp/chameleon/trunk or VPATH. the *only* time you should use /Users/evan/SourceCode/tmp/chameleon/trunk is when setting the SRCROOT variable. Also note that very soon make pkg is going to be removed. The pkg build script in trunk is very out of date. Instead please use the package maker at http://forge.voodooprojects.org/p/chameleonApplications/. Once this is ready for trunk it will be merged.
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: 1166