Index: branches/meklort/i386/boot2/modules.c =================================================================== --- branches/meklort/i386/boot2/modules.c (revision 493) +++ branches/meklort/i386/boot2/modules.c (revision 494) @@ -18,6 +18,9 @@ #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; @@ -25,8 +28,6 @@ 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); @@ -84,8 +85,16 @@ { 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); + } + } } @@ -94,13 +103,14 @@ * 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; } @@ -124,10 +134,12 @@ //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); } @@ -283,23 +295,25 @@ * 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; @@ -325,12 +339,12 @@ - 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 { @@ -346,10 +360,69 @@ 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; @@ -361,7 +434,7 @@ // = dylibCommand->dylib.current_version; // = dylibCommand->dylib.compatibility_version; - if(!load_module(module)) + if(dylib_loader && !dylib_loader(module)) { // Unable to load dependancy return NULL; @@ -370,9 +443,10 @@ 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: @@ -383,6 +457,9 @@ case LC_UUID: break; + case LC_UNIXTHREAD: + break; + default: DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF); break; @@ -391,11 +468,11 @@ 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) @@ -420,13 +497,7 @@ // 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; } @@ -937,7 +1008,7 @@ * 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; /* @@ -967,9 +1038,9 @@ } entry->next = NULL; - entry->module = name; - entry->version = version; - entry->compat = compat; + entry->module = (char*)name; + entry->version = 0; //version; + entry->compat = 0; //compat; } @@ -979,8 +1050,10 @@ 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 @@ -989,6 +1062,8 @@ } } + DBG("Module %s not found\n", name); + return 0; } @@ -1067,7 +1142,7 @@ 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) { Index: branches/meklort/i386/boot2/modules.h =================================================================== --- branches/meklort/i386/boot2/modules.h (revision 493) +++ branches/meklort/i386/boot2/modules.h (revision 494) @@ -10,7 +10,10 @@ #ifndef __BOOT_MODULES_H #define __BOOT_MODULES_H +extern unsigned long long textAddress; +extern unsigned long long textSection; + typedef struct symbolList_t { char* symbol; @@ -67,14 +70,19 @@ 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, Index: branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c =================================================================== --- branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c (revision 493) +++ branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c (revision 494) @@ -12,9 +12,6 @@ patchRoutine_t* patches = NULL; kernSymbols_t* kernelSymbols = NULL; -unsigned long long textAddress = 0; -unsigned long long textSection = 0; -//UInt64 vmaddr = 0; void KernelPatcher_start() { @@ -178,7 +175,6 @@ locate_symbols(kernelData); - if(patches != NULL) { while(entry) @@ -216,120 +212,9 @@ **/ 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; } @@ -375,8 +260,12 @@ 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; @@ -394,14 +283,10 @@ 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) || @@ -415,16 +300,21 @@ } 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)) && @@ -486,57 +376,79 @@ } 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 } }