Chameleon

Chameleon Commit Details

Date:2010-09-05 01:09:46 (13 years 7 months ago)
Author:Evan Lojewski
Commit:494
Parents: 493
Message:More module changes, panic removal patches should now work in 64bit mode.
Changes:
M/branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c
M/branches/meklort/i386/boot2/modules.c
M/branches/meklort/i386/boot2/modules.h

File differences

branches/meklort/i386/boot2/modules.c
1818
1919
2020
21
22
23
2124
2225
2326
......
2528
2629
2730
28
29
3031
3132
3233
......
8485
8586
8687
87
88
89
90
91
8892
93
94
95
96
97
8998
9099
91100
......
94103
95104
96105
97
106
98107
99108
100109
101110
102111
103112
113
104114
105115
106116
......
124134
125135
126136
127
137
128138
129139
130140
141
142
131143
132144
133145
......
283295
284296
285297
286
298
287299
288300
289301
290302
291303
292
304
293305
294306
295
307
296308
297309
298310
299311
300312
301313
302
314
315
316
303317
304318
305319
......
325339
326340
327341
328
342
329343
330344
331345
332346
333
347
334348
335349
336350
......
346360
347361
348362
349
350
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
351392
393
394
352395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
353426
354427
355428
......
361434
362435
363436
364
437
365438
366439
367440
......
370443
371444
372445
373
446
374447
375448
449
376450
377451
378452
......
383457
384458
385459
460
461
462
386463
387464
388465
......
391468
392469
393470
394
471
395472
396473
397474
398
475
399476
400477
401478
......
420497
421498
422499
423
424500
425
426
427
428
429
430501
431502
432503
......
9371008
9381009
9391010
940
1011
9411012
9421013
9431014
......
9671038
9681039
9691040
970
971
972
1041
1042
1043
9731044
9741045
9751046
......
9791050
9801051
9811052
1053
9821054
9831055
1056
9841057
9851058
9861059
......
9891062
9901063
9911064
1065
1066
9921067
9931068
9941069
......
10671142
10681143
10691144
1070
1145
10711146
10721147
10731148
#define DBG(x...)
#endif
// NOTE: Global so that modules can link with this
unsigned long long textAddress = 0;
unsigned long long textSection = 0;
moduleHook_t* moduleCallbacks = NULL;
moduleList_t* loadedModules = NULL;
unsigned int (*lookup_symbol)(const char*) = NULL;
void rebase_macho(void* base, char* rebase_stream, UInt32 size);
void bind_macho(void* base, char* bind_stream, UInt32 size);
{
if(strcmp(&name[strlen(name) - sizeof("dylib")], ".dylib") == 0)
{
load_module(name);
char* tmp = malloc(strlen(name) + 1); // TODO: look into this
strcpy(tmp, name);
DBG("Attempting to load %s\n", tmp);
load_module(tmp);
}
else
{
DBG("Ignoring %s\n", name);
}
}
}
* Load a module file in /Extra/modules
* TODO: verify version number of module
*/
int load_module(const char* module)
int load_module(char* module)
{
// Check to see if the module has already been loaded
if(is_module_laoded(module))
{
// NOTE: Symbols.dylib tries to load twice, this catches it as well
// as when a module links with an already loaded module
DBG("Module %s already loaded\n", module);
return 1;
}
//printf("Module %s read in.\n", modString);
// Module loaded into memory, parse it
module_start = parse_mach(module_base);
module_start = parse_mach(module_base, &load_module, &add_symbol);
if(module_start && module_start != (void*)0xFFFFFFFF)
{
// Notify the system that it was laoded
module_loaded(module/*moduleName, moduleVersion, moduleCompat*/);
(*module_start)();// Start the module
DBG("Module %s Loaded.\n", module);
}
* symbols will still be available (TODO: fix this). This should not
* happen as all dependencies are verified before the sybols are read in.
*/
void* parse_mach(void* binary)// TODO: add param to specify valid archs
void* parse_mach(void* binary, int(*dylib_loader)(char*), long long(*symbol_handler)(char*, long long, char))// TODO: add param to specify valid archs
{
char is64 = false;
void (*module_start)(void) = NULL;
// Module info
char* moduleName = NULL;
/*char* moduleName = NULL;
UInt32 moduleVersion = 0;
UInt32 moduleCompat = 0;
*/
// TODO convert all of the structs to a union
struct load_command *loadCommand = NULL;
struct dylib_command* dylibCommand = NULL;
struct dyld_info_command* dyldInfoCommand = NULL;
struct symtab_command* symtabCommand = NULL;
struct segment_command *segCommand = NULL;
struct segment_command_64 *segCommand64 = NULL;
//struct dysymtab_command* dysymtabCommand = NULL;
UInt32 binaryIndex = 0;
UInt16 cmd = 0;
if(((struct mach_header*)binary)->filetype != MH_DYLIB)
/*if(((struct mach_header*)binary)->filetype != MH_DYLIB)
{
printf("Module is not a dylib. Unable to load.\n");
getc();
return NULL; // Module is in the incorrect format
}
}*/
while(cmd < ((struct mach_header*)binary)->ncmds)// TODO: for loop instead
{
symtabCommand = binary + binaryIndex;
break;
case LC_SEGMENT:
case LC_SEGMENT_64:
case LC_SEGMENT: // 32bit macho
segCommand = binary + binaryIndex;
//printf("Segment name is %s\n", segCommand->segname);
if(strcmp("__TEXT", segCommand->segname) == 0)
{
UInt32 sectionIndex;
sectionIndex = sizeof(struct segment_command);
struct section *sect;
while(sectionIndex < segCommand->cmdsize)
{
sect = binary + binaryIndex + sectionIndex;
sectionIndex += sizeof(struct section);
if(strcmp("__text", sect->sectname) == 0)
{
// __TEXT,__text found, save the offset and address for when looking for the calls.
textSection = sect->offset;
textAddress = sect->addr;
break;
}
}
}
break;
case LC_SEGMENT_64:// 64bit macho's
segCommand64 = binary + binaryIndex;
//printf("Segment name is %s\n", segCommand->segname);
if(strcmp("__TEXT", segCommand64->segname) == 0)
{
UInt32 sectionIndex;
sectionIndex = sizeof(struct segment_command_64);
struct section_64 *sect;
while(sectionIndex < segCommand64->cmdsize)
{
sect = binary + binaryIndex + sectionIndex;
sectionIndex += sizeof(struct section_64);
if(strcmp("__text", sect->sectname) == 0)
{
// __TEXT,__text found, save the offset and address for when looking for the calls.
textSection = sect->offset;
textAddress = sect->addr;
break;
}
}
}
break;
case LC_DYSYMTAB:
break;
// =dylibCommand->dylib.current_version;
// =dylibCommand->dylib.compatibility_version;
if(!load_module(module))
if(dylib_loader && !dylib_loader(module))
{
// Unable to load dependancy
return NULL;
case LC_ID_DYLIB:
dylibCommand = binary + binaryIndex;
moduleName =binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
/*moduleName =binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
moduleVersion =dylibCommand->dylib.current_version;
moduleCompat =dylibCommand->dylib.compatibility_version;
*/
break;
case LC_DYLD_INFO:
case LC_UUID:
break;
case LC_UNIXTHREAD:
break;
default:
DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);
break;
binaryIndex += cmdSize;
}
if(!moduleName) return NULL;
//if(!moduleName) return NULL;
// bind_macho uses the symbols.
module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, &add_symbol, is64);
module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbol_handler, is64);
// Rebase the module before binding it.
if(dyldInfoCommand && dyldInfoCommand->rebase_off)
// This should be changed to bind when a symbol is referened at runtime instead.
bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);
}
// Notify the system that it was laoded
module_loaded(moduleName, moduleVersion, moduleCompat);
return module_start;
}
* print out the information about the loaded module
*/
void module_loaded(char* name, UInt32 version, UInt32 compat)
void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/)
{
moduleList_t* entry;
/*
}
entry->next = NULL;
entry->module = name;
entry->version = version;
entry->compat = compat;
entry->module = (char*)name;
entry->version = 0; //version;
entry->compat = 0; //compat;
}
moduleList_t* entry = loadedModules;
while(entry)
{
DBG("Comparing %s with %s\n", name, entry->module);
if(strcmp(entry->module, name) == 0)
{
DBG("Located module %s\n", name);
return 1;
}
else
}
}
DBG("Module %s not found\n", name);
return 0;
}
else
{
struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;
// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now)
// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now)
while(symbolIndex < symtabCommand->nsyms)
{
branches/meklort/i386/boot2/modules.h
1010
1111
1212
13
14
1315
16
1417
1518
1619
......
6770
6871
6972
73
74
7075
71
76
7277
73
78
7479
7580
7681
77
82
83
84
85
7886
7987
8088
#ifndef __BOOT_MODULES_H
#define __BOOT_MODULES_H
extern unsigned long long textAddress;
extern unsigned long long textSection;
typedef struct symbolList_t
{
char* symbol;
void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*));
inline void rebase_location(UInt32* location, char* base);
void rebase_macho(void* base, char* rebase_stream, UInt32 size);
void bind_macho(void* base, char* bind_stream, UInt32 size);
int load_module(const char* module);
int load_module(char* module);
int is_module_laoded(const char* name);
void module_loaded(char* name, UInt32 version, UInt32 compat);
void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/);
long long add_symbol(char* symbol, long long addr, char is64);
void* parse_mach(void* binary);
void* parse_mach(void* binary,
int(*dylib_loader)(char*),
long long(*symbol_handler)(char*, long long, char)
);
unsigned int handle_symtable(UInt32 base,
struct symtab_command* symtabCommand,
branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c
1212
1313
1414
15
16
17
1815
1916
2017
......
178175
179176
180177
181
182178
183179
184180
......
216212
217213
218214
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
215
216
217
333218
334219
335220
......
375260
376261
377262
263
378264
265
379266
267
268
380269
381270
382271
......
394283
395284
396285
397
398
399286
400287
401
402288
403289
404
405290
406291
407292
......
415300
416301
417302
303
304
418305
419306
420307
421308
422309
423310
311
312
313
424314
425
426315
427316
317
428318
429319
430320
......
486376
487377
488378
489
490
491
492
493
494
379
380
381
382
383
384
385
495386
496387
497388
498
499
500389
501
502
503
504390
505
391
506392
507
508
509
510
511
512
513
514
515
516
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
517409
518
519
520
521
522
523
410
411
412
524413
525
526
527
528
529
530
531
532
533
534
535
536
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
537447
538448
539449
450
451
540452
541453
542454
patchRoutine_t* patches = NULL;
kernSymbols_t* kernelSymbols = NULL;
unsigned long long textAddress = 0;
unsigned long long textSection = 0;
//UInt64 vmaddr = 0;
void KernelPatcher_start()
{
locate_symbols(kernelData);
if(patches != NULL)
{
while(entry)
**/
int locate_symbols(void* kernelData)
{
char is64;
struct load_command *loadCommand;
struct symtab_command *symtableData = NULL;
struct segment_command *segCommand = NULL;
struct segment_command_64 *segCommand64 = NULL;
UInt32 kernelIndex = 0;
if(((struct mach_header*)kernelData)->magic == MH_MAGIC)
{
is64 = 0;
kernelIndex += sizeof(struct mach_header);
}
else if(((struct mach_header_64*)kernelData)->magic == MH_MAGIC_64)
{
is64 = 1;
kernelIndex += sizeof(struct mach_header_64);
}
else
{
printf("Invalid mach magic 0x%X\n", ((struct mach_header*)kernelData)->magic);
getc();
return KERNEL_ERR;
}
int cmd = 0;
while(cmd < ((struct mach_header*)kernelData)->ncmds)// TODO: for loop instead
{
cmd++;
loadCommand = kernelData + kernelIndex;
UInt cmdSize = loadCommand->cmdsize;
switch ((loadCommand->cmd & 0x7FFFFFFF))
{
case LC_SYMTAB:
//printf("Located symtable, length is 0x%X, 0x%X\n", (unsigned int)loadCommand->cmdsize, (unsigned int)sizeof(symtableData));
symtableData = kernelData + kernelIndex;
break;
case LC_SEGMENT: // 32bit macho
segCommand = kernelData + kernelIndex;
//printf("Segment name is %s\n", segCommand->segname);
if(strcmp("__TEXT", segCommand->segname) == 0)
{
UInt32 sectionIndex;
sectionIndex = sizeof(struct segment_command);
struct section *sect;
while(sectionIndex < segCommand->cmdsize)
{
sect = kernelData + kernelIndex + sectionIndex;
sectionIndex += sizeof(struct section);
if(strcmp("__text", sect->sectname) == 0)
{
// __TEXT,__text found, save the offset and address for when looking for the calls.
textSection = sect->offset;
textAddress = sect->addr;
break;
}
}
}
break;
case LC_SEGMENT_64:// 64bit macho's
segCommand64 = kernelData + kernelIndex;
//printf("Segment name is %s\n", segCommand->segname);
if(strcmp("__TEXT", segCommand64->segname) == 0)
{
UInt32 sectionIndex;
sectionIndex = sizeof(struct segment_command_64);
struct section_64 *sect;
while(sectionIndex < segCommand64->cmdsize)
{
sect = kernelData + kernelIndex + sectionIndex;
sectionIndex += sizeof(struct section_64);
if(strcmp("__text", sect->sectname) == 0)
{
// __TEXT,__text found, save the offset and address for when looking for the calls.
textSection = sect->offset;
textAddress = sect->addr;
break;
}
}
}
break;
default:
break;
}
kernelIndex += cmdSize;
}
handle_symtable((UInt32)kernelData, symtableData, &symbol_handler, determineKernelArchitecture(kernelData) == KERNEL_64);
char is64 = 1;
parse_mach(kernelData, NULL, symbol_handler);
//handle_symtable((UInt32)kernelData, symtableData, &symbol_handler, determineKernelArchitecture(kernelData) == KERNEL_64);
return 1 << is64;
}
UInt8* bytes = (UInt8*)kernelData;
kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");
UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);
patchLocation -= (UInt32)kernelData;// Remove offset
UInt32 jumpLocation = 0;
printf("Unable to locate _panic\n");
return;
}
patchLocation -= (UInt32)kernelData;// Remove offset
panicAddr -= (UInt32)kernelData;
//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)
while(
(bytes[patchLocation -1] != 0xE8) ||
}
patchLocation--;
printf("0x%X 0x%X 0x%X 0x%X 0x%X\n", bytes[patchLocation ], bytes[patchLocation +1], bytes[patchLocation +2], bytes[patchLocation +3], bytes[patchLocation +4]);
// Remove panic call, just in case the following patch routines fail
bytes[patchLocation + 0] = 0x90;
bytes[patchLocation + 1] = 0x90;
bytes[patchLocation + 2] = 0x90;
bytes[patchLocation + 3] = 0x90;
bytes[patchLocation + 4] = 0x90;
printf("0x%X 0x%X 0x%X 0x%X 0x%X\n", bytes[patchLocation ], bytes[patchLocation +1], bytes[patchLocation +2], bytes[patchLocation +3], bytes[patchLocation +4]);
getc();
// Locate the jump call, so that 10 bytes can be reclamed.
// NOTE: This will *NOT* be located on pre 10.6.2 kernels
// NOTE: This will work on a *32* bit kernel and *not* on a 64 bit ont
jumpLocation = patchLocation - 15;
while((bytes[jumpLocation - 1] != 0x77 ||
bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&
}
else if(impersonateFamily && impersonateModel)
{
// pre 10.6.2 kernel
// Locate the jump to directly *after* the panic call,
jumpLocation = patchLocation - 4;
while((bytes[jumpLocation - 1] != 0x77 ||
bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&
(patchLocation - jumpLocation) < 0x20)
// Eitehr a 64bit kernel *or* a pre 10.6.2 kernel
// Look for
jumpLocation = patchLocation - 15;
while((bytes[jumpLocation - 2] != 0x0F ||
bytes[jumpLocation - 1] != 0x87 ||
bytes[jumpLocation] != (patchLocation - jumpLocation - -31)) &&
(patchLocation - jumpLocation) < 0x200)
{
jumpLocation--;
}
// NOTE above isn't needed (I was going to use it, but I'm not, so instead,
// I'll just leave it to verify the binary stucture.
// NOTE: the cpumodel_familt data is not set in _cpuid_set_info
// so we don't need to set it here, I'll get set later based on the model
// we set now.
if((patchLocation - jumpLocation) < 0x20)
if(patchLocation - jumpLocation) < 0x200)
{
UInt32 cpuid_model_addr =(bytes[patchLocation - 14] << 0 |
bytes[patchLocation - 13] << 8 |
bytes[patchLocation - 12] << 16 |
bytes[patchLocation - 11] << 24);
// Remove jump
bytes[patchLocation - 9] = 0x90;/// Was a jump if supported cpu
bytes[patchLocation - 8] = 0x90;// jumped past the panic call, we want to override the panic
bytes[patchLocation - 7] = 0x90;
bytes[patchLocation - 6] = 0x90;
// 64 bit kernel, 10.6.2+
}
else
{// 32 bit kernel
// pre 10.6.2 kernel
// Locate the jump to directly *after* the panic call,
jumpLocation = patchLocation - 4;
while((bytes[jumpLocation - 1] != 0x77 ||
bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&
(patchLocation - jumpLocation) < 0x20)
{
jumpLocation--;
}
// NOTE above isn't needed (I was going to use it, but I'm not, so instead,
// I'll just leave it to verify the binary stucture.
bytes[patchLocation - 5] = 0xC7;
bytes[patchLocation - 4] = 0x05;
bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;
bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;
bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;
bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;
// NOTE: the cpumodel_family data is not set in _cpuid_set_info
// so we don't need to set it here, I'll get set later based on the model
// we set now.
// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes
// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.
bytes[patchLocation + 1] = impersonateModel;// cpuid_model
bytes[patchLocation + 2] = 0x01;// cpuid_extmodel
bytes[patchLocation + 3] = 0x00;// cpuid_extfamily
bytes[patchLocation + 4] = 0x02;// cpuid_stepping
patchLocation = jumpLocation;
// We now have 14 bytes available for a patch
if((patchLocation - jumpLocation) < 0x20)
{
UInt32 cpuid_model_addr =(bytes[patchLocation - 14] << 0 |
bytes[patchLocation - 13] << 8 |
bytes[patchLocation - 12] << 16 |
bytes[patchLocation - 11] << 24);
// Remove jump
bytes[patchLocation - 9] = 0x90;/// Was a jump if supported cpu
bytes[patchLocation - 8] = 0x90;// jumped past the panic call, we want to override the panic
bytes[patchLocation - 7] = 0x90;
bytes[patchLocation - 6] = 0x90;
bytes[patchLocation - 5] = 0xC7;
bytes[patchLocation - 4] = 0x05;
bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;
bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;
bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;
bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;
// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes
// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.
bytes[patchLocation + 1] = impersonateModel;// cpuid_model
bytes[patchLocation + 2] = 0x01;// cpuid_extmodel
bytes[patchLocation + 3] = 0x00;// cpuid_extfamily
bytes[patchLocation + 4] = 0x02;// cpuid_stepping
patchLocation = jumpLocation;
// We now have 14 bytes available for a patch
}
}
else
{
// Check for 64bit kernel.
// Patching failed, using NOP replacement done initialy
}
}

Archive Download the corresponding diff file

Revision: 494