Chameleon

Chameleon Commit Details

Date:2010-09-03 08:47:13 (8 years 10 months ago)
Author:Evan Lojewski
Commit:482
Parents: 481
Message:Modified macho parser to handle 64bit files properly (untested). Modified module hooks to be a sorted linked list for now, I may convert to a faster search later on. I should now be able to add 64bit support to the kernel patcher.
Changes:
M/branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c
M/branches/meklort/i386/modules/KernelPatcher/kernel_patcher.h
M/branches/meklort/i386/boot2/modules.c
M/branches/meklort/i386/boot2/modules.h

File differences

branches/meklort/i386/boot2/modules.c
2929
3030
3131
32
33
34
35
36
37
38
39
40
41
42
43
44
3245
3346
3447
......
3952
4053
4154
42
55
4356
4457
4558
......
7184
7285
7386
74
7587
7688
7789
......
8799
88100
89101
102
103
90104
91105
92106
93107
94108
95
109
96110
97111
98112
......
112126
113127
114128
115
129
116130
117131
118
132
119133
120134
121
135
122136
123
124
125
137
126138
127139
128140
129
141
130142
131143
132144
133145
134146
135
136147
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170148
171149
172150
......
181159
182160
183161
184
162
185163
186164
187165
188166
189
167
190168
191169
192170
......
223201
224202
225203
226
204
227205
206
228207
229
230
231
232
233208
234209
210
235211
236212
237213
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
214
215
216
259217
260
261
262
218
219
220
263221
264222
265223
266
267
224
225
226
227
268228
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
269263
264
265
266
270267
271
272
273
274
275
276268
269
270
271
272
273
277274
278275
279276
280
281277
282278
283279
......
287283
288284
289285
290
286
291287
288
292289
293
290
294291
295292
296293
......
300297
301298
302299
300
303301
302
304303
305304
306305
307306
308307
309
308
310309
311
310
311
312
313
314
315
316
317
318
312319
313
320
314321
322
323
315324
316325
317326
......
381390
382391
383392
384
393
385394
386395
387396
......
465474
466475
467476
468
477
478
469479
470480
471481
......
536546
537547
538548
539
549
540550
541551
542552
......
695705
696706
697707
698
708
699709
700710
701711
......
878888
879889
880890
881
891
882892
893
894
895
883896
884897
885898
......
901914
902915
903916
904
917
905918
906919
907920
......
910923
911924
912925
913
926
914927
915928
916929
......
10181031
10191032
10201033
1021
1034
10221035
10231036
10241037
......
10281041
10291042
10301043
1031
1032
1044
10331045
10341046
1035
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
10361067
1037
1038
1039
1068
10401069
1041
1042
1043
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
10441084
1085
10451086
1046
1047
1048
1049
10501087
10511088
10521089
void bind_macho(void* base, char* bind_stream, UInt32 size);
#if DEBUG_MODULES
void print_hook_list()
{
moduleHook_t* hooks = moduleCallbacks;
while(hooks)
{
printf("Hook: %s\n", hooks->name);
hooks = hooks->next;
}
}
#endif
/*
* Initialize the module system by loading the Symbols.dylib module.
* Once laoded, locate the _lookup_symbol function so that internal
// Intialize module system
if(load_module(SYMBOLS_MODULE))
{
lookup_symbol = (void*)lookup_all_symbols("_lookup_symbol");
lookup_symbol = (void*)lookup_all_symbols(SYMBOL_LOOKUP_SYMBOL);
if((UInt32)lookup_symbol != 0xFFFFFFFF)
{
{
if(strcmp(&name[strlen(name) - sizeof("dylib")], ".dylib") == 0)
{
name[strlen(name) - sizeof("dylib")] = 0;
load_module(name);
}
}
// 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
return 1;
}
char modString[128];
int fh = -1;
sprintf(modString, "/Extra/modules/%s.dylib", module);
sprintf(modString, "/Extra/modules/%s", module);
fh = open(modString, 0);
if(fh < 0)
{
// Module loaded into memory, parse it
module_start = parse_mach(module_base);
if(module_start)
if(module_start && module_start != (void*)0xFFFFFFFF)
{
(*module_start)();// Start the module
DBG("Module %s.dylib Loaded.\n", module);
DBG("Module %s Loaded.\n", module);
}
else {
printf("Unabel to start %s.dylib\n", module);
printf("Unable to start %s\n", module);
getc();
}
// TODO: Add module to loaded list if loaded successfuly
}
}
else
{
printf("Unable to read in module %s.dylib\n.", module);
printf("Unable to read in module %s\n.", module);
getc();
}
return 1;
}
/*
* register_hook( const char* name )
*name - Name of the module Hook.
* NOTE: If the name already exists in the list, it'll
* still be added, however the entry will not be used, the first one
* will instead. That also means the the hook will most likely be
* called twice.
*
* Registers a hook with the module system, This allows modules to
* register a callback when the hook is executed.
*/
inline void register_hook(const char* name)
{
moduleHook_t* hooks;
if(moduleCallbacks == NULL)
{
moduleCallbacks = malloc(sizeof(moduleHook_t));
moduleCallbacks->next = NULL;
}
hooks = moduleCallbacks;
while(hooks->next != NULL)
{
hooks = hooks->next;
}
hooks->name = name;
hooks->callbacks = NULL;
}
/*
*execute_hook( const char* name )
*name - Name of the module hook
*If any callbacks have been registered for this hook
{
moduleHook_t* hooks = moduleCallbacks;
while(hooks != NULL && strcmp(name, hooks->name) != 0)
while(hooks != NULL && strcmp(name, hooks->name) < 0)
{
hooks = hooks->next;
}
if(hooks != NULL)
if(strcmp(name, hooks->name) == 0)
{
// Loop through all callbacks for this module
callbackList_t* callbacks = hooks->callbacks;
*register_hook_callback( const char* name, void(*callback)())
*name - Name of the module hook to attach to.
*callbacks - The funciton pointer that will be called when the
*hook is executed.
*hook is executed. When registering a new callback name, the callback is added sorted.
*NOTE: the hooks take four void* arguments.
*TODO: refactor
*/
/*
void register_hook_callback(const char* name,
void(*callback)(void*, void*, void*, void*),
)*/
void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))
{
DBG("Registering %s\n", name);
// Locate Module hook
if(moduleCallbacks == NULL)
{
register_hook(name);
}
volatile moduleHook_t* hooks = moduleCallbacks;
while(hooks != NULL && strcmp(name, hooks->name) != 0)
{
hooks = hooks->next;
}
if(hooks == NULL)
{
// Hook doesn't exist, add it.
register_hook(name);
// This is just a pointer, the data was modified in the register_hook function.
hooks = hooks->next;
}
// Module Hooks located
if(hooks->callbacks == NULL)
{
moduleCallbacks = malloc(sizeof(moduleHook_t));
moduleCallbacks->next = NULL;
moduleCallbacks->name = name;
// Initialize hook list
hooks->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));
hooks->callbacks->callback = callback;
hooks->callbacks->next = NULL;
moduleCallbacks->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));
moduleCallbacks->callbacks->callback = callback;
moduleCallbacks->callbacks->next = NULL;
}
else
{
callbackList_t* callbacks = hooks->callbacks;
while(callbacks->next != NULL)
moduleHook_t* hooks = moduleCallbacks;
moduleHook_t* newHook = malloc(sizeof(moduleHook_t));;
while(hooks->next != NULL && strcmp(name, hooks->name) < 0)
{
hooks = hooks->next;
}
DBG("%s cmp %s = %d\n", name, hooks->name, strcmp(name, hooks->name));
if(hooks == NULL)
{
newHook->next = moduleCallbacks;
moduleCallbacks = newHook;
newHook->name = name;
newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));
newHook->callbacks->callback = callback;
newHook->callbacks->next = NULL;
}
else if(strcmp(name, hooks->name) != 0)
{
newHook->next = hooks->next;
hooks->next = newHook;
newHook->name = name;
newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));
newHook->callbacks->callback = callback;
newHook->callbacks->next = NULL;
}
else
{
callbackList_t* callbacks = hooks->callbacks;
while(callbacks->next != NULL)
{
callbacks = callbacks->next;
}
// Add new entry to end of hook list.
callbacks->next = (callbackList_t*)malloc(sizeof(callbackList_t));
callbacks = callbacks->next;
callbacks->next = NULL;
callbacks->callback = callback;
}
// Add new entry to end of hook list.
callbacks->next = (callbackList_t*)malloc(sizeof(callbackList_t));
callbacks = callbacks->next;
callbacks->next = NULL;
callbacks->callback = callback;
}
#if DEBUG_MODULES
print_hook_list();
getc();
#endif
}
/*
* Parse through a macho module. The module will be rebased and binded
* as specified in the macho header. If the module is sucessfuly laoded
* 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)
void* parse_mach(void* binary)// TODO: add param to specify valid archs
{
char is64 = false;
void (*module_start)(void) = NULL;
// Module info
char* moduleName = NULL;
UInt32 moduleVersion = 0;
struct load_command *loadCommand = NULL;
struct dylib_command* dylibCommand = NULL;
struct dyld_info_command* dyldInfoCommand = NULL;
struct symtab_command* symtabCommand = NULL;
//struct dysymtab_command* dysymtabCommand = NULL;
UInt32 binaryIndex = sizeof(struct mach_header);
UInt16 cmd = 0;
// Parse through the load commands
if(((struct mach_header*)binary)->magic != MH_MAGIC)
if(((struct mach_header*)binary)->magic == MH_MAGIC)
{
printf("Module is not 32bit\n");
is64 = 0;
}
else if(((struct mach_header_64*)binary)->magic != MH_MAGIC_64)
{
is64 = 1;
}
else
{
printf("Invalid mach magic\n");
getc();
return NULL;// 32bit only
return NULL;
}
if(((struct mach_header*)binary)->filetype != MH_DYLIB)
{
// bind_macho uses the symbols.
module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, &add_symbol);
module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, &add_symbol, is64);
// Rebase the module before binding it.
if(dyldInfoCommand && dyldInfoCommand->rebase_off)
// Locate address to begin rebasing
segmentAddress = 0;
struct segment_command* segCommand = NULL;
struct segment_command* segCommand = NULL; // NOTE: 32bit only
unsigned int binIndex = 0;
index = 0;
index = 0;
for (index = 0; index < tmp; ++index) {
//printf("\tRebasing 0x%X\n", segmentAddress);
//DBG("\tRebasing 0x%X\n", segmentAddress);
rebase_location(base + segmentAddress, (char*)base);
segmentAddress += sizeof(void*);
}
segmentAddress = 0;
// Locate address
struct segment_command* segCommand = NULL;
struct segment_command* segCommand = NULL;// NOTE: 32bit only
unsigned int binIndex = 0;
index = 0;
* adjust it's internal symbol list (sort) to optimize locating new symbols
* NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF
*/
void* add_symbol(char* symbol, void* addr)
long long add_symbol(char* symbol, long long addr, char is64)
{
if(is64) return 0xFFFFFFFF; // Fixme
// This only can handle 32bit symbols
symbolList_t* entry;
//DBG("Adding symbol %s at 0x%X\n", symbol, addr);
}
entry->next = NULL;
entry->addr = (unsigned int)addr;
entry->addr = (UInt32)addr;
entry->symbol = symbol;
if(strcmp(symbol, "start") == 0)
}
else
{
return (void*)0xFFFFFFFF;
return 0xFFFFFFFF; // fixme
}
}
* Lookup any undefined symbols
*/
unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, void*(*symbol_handler)(char*, void*))
unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64)
{
// TODO: verify that the _TEXT,_text segment starts at the same locaiton in the file. If not
//subtract the vmaddress and add the actual file address back on. (NOTE: if compiled properly, not needed)
UInt32 symbolIndex = 0;
char* symbolString = base + (char*)symtabCommand->stroff;
//char* symbolTable = base + symtabCommand->symoff;
while(symbolIndex < symtabCommand->nsyms)
if(!is64)
{
struct nlist* symbolEntry = (void*)base + symtabCommand->symoff + (symbolIndex * sizeof(struct nlist));
while(symbolIndex < symtabCommand->nsyms)
{
struct nlist* symbolEntry = (void*)base + symtabCommand->symoff + (symbolIndex * sizeof(struct nlist));
// If the symbol is exported by this module
if(symbolEntry->n_value &&
symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF)
{
// Module start located. Start is an alias so don't register it
module_start = base + symbolEntry->n_value;
}
symbolEntry+= sizeof(struct nlist);
symbolIndex++;// TODO remove
}
}
else
{
// If the symbol is exported by this module
if(symbolEntry->n_value &&
symbol_handler(symbolString + symbolEntry->n_un.n_strx, (void*)base + symbolEntry->n_value) != (void*)0xFFFFFFFF)
while(symbolIndex < symtabCommand->nsyms)
{
// Module start located. Start is an alias so don't register it
module_start = base + symbolEntry->n_value;
struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff + (symbolIndex * sizeof(struct nlist_64));
// If the symbol is exported by this module
if(symbolEntry->n_value &&
symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF)
{
// Module start located. Start is an alias so don't register it
module_start = base + symbolEntry->n_value;
}
symbolEntry+= sizeof(struct nlist);
symbolIndex++;// TODO remove
}
}
symbolEntry+= sizeof(struct nlist);
symbolIndex++;// TODO remove
}
return module_start;
}
branches/meklort/i386/boot2/modules.h
3939
4040
4141
42
4243
43
44
4544
45
4646
4747
4848
......
5555
5656
5757
58
59
60
61
6258
6359
6460
......
6763
6864
6965
70
7166
7267
7368
......
7772
7873
7974
80
75
8176
8277
8378
8479
8580
86
81
82
8783
8884
8985
struct moduleHook_t* next;
} moduleHook_t;
#define SYMBOLS_MODULE "Symbols.dylib"
#define SYMBOLS_MODULE "Symbols"
#define SYMBOL_DYLD_STUB_BINDER"dyld_stub_binder"
#define SYMBOL_LOOKUP_SYMBOL"_lookup_symbol"
#define STUB_ENTRY_SIZE6
#define SECT_NON_LAZY_SYMBOL_PTR"__nl_symbol_ptr"
/*
* Modules Interface
* register_hook
*Notifies the module system that it should log requests
*for callbacks on the hool execution
*
* execute_hook
*Exexutes a registered hook. All callbaks are
*called in the same order that they were added
*registers a void function to be executed when a
*hook is executed.
*/
inline void register_hook(const char* name);
int execute_hook(const char* name, void*, void*, void*, void*);
void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*));
int is_module_laoded(const char* name);
void module_loaded(char* name, UInt32 version, UInt32 compat);
void* add_symbol(char* symbol, void* addr);
long long add_symbol(char* symbol, long long addr, char is64);
void* parse_mach(void* binary);
unsigned int handle_symtable(UInt32 base,
struct symtab_command* symtabCommand,
void*(*symbol_handler)(char*, void*));
long long(*symbol_handler)(char*, long long, char),
char is64);
unsigned int lookup_all_symbols(const char* name);
branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c
286286
287287
288288
289
289
290290
291291
292
292
293293
294294
295295
......
297297
298298
299299
300
300
301301
302
302
303303
304304
305305
}
}
handle_symtable((UInt32)kernelData, symtableData, &symbol_handler);
handle_symtable((UInt32)kernelData, symtableData, &symbol_handler, determineKernelArchitecture(kernelData) == KERNEL_64);
}
void* symbol_handler(char* symbolName, void* addr)
long long symbol_handler(char* symbolName, long long addr, char is64)
{
// Locate the symbol in the list, if it exists, update it's address
kernSymbols_t *symbol = lookup_kernel_symbol(symbolName);
if(symbol)
{
symbol->addr = (UInt32)addr;
symbol->addr = addr;
}
return (void*)0xFFFFFFFF;
return 0xFFFFFFFF; // fixme
}
branches/meklort/i386/modules/KernelPatcher/kernel_patcher.h
4545
4646
4747
48
48
4949
5050
5151
kernSymbols_t* lookup_kernel_symbol(const char* name);
void register_kernel_symbol(int kernelType, const char* name);
void* symbol_handler(char* symbol, void* addr);
long long symbol_handler(char* symbolName, long long addr, char is64);
void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4);
void register_kernel_patch(void* patch, int arch, int cpus);

Archive Download the corresponding diff file

Revision: 482