Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 2006