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 | ␊ |
11 | #ifndef DEBUG_KERNEL_PATCHER␊ |
12 | #define DEBUG_KERNEL_PATCHER 0␊ |
13 | #endif␊ |
14 | ␊ |
15 | #if DEBUG_KERNEL_PATCHER␊ |
16 | #define DBG(x...)␉printf(x)␊ |
17 | #else␊ |
18 | #define DBG(x...)␊ |
19 | #endif␊ |
20 | ␊ |
21 | long long symbol_handler(char* module, char* symbolName, long long addr, char is64);␊ |
22 | ␊ |
23 | patchRoutine_t* patches = NULL;␊ |
24 | kernSymbols_t* kernelSymbols = NULL;␊ |
25 | static void register_kernel_patch(void* patch, int arch, int cpus);␊ |
26 | static void register_kernel_symbol(int kernelType, const char* name);␊ |
27 | static kernSymbols_t* lookup_kernel_symbol(const char* name);␊ |
28 | static int determineKernelArchitecture(void* kernelData);␊ |
29 | static int locate_symbols(void* kernelData);␊ |
30 | static unsigned int parse_mach_64(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long, char));␊ |
31 | static unsigned int handle_symtable_64(char *module, UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, char*, long long, char), char is64);␊ |
32 | ␊ |
33 | /*␊ |
34 | * Internal patches provided by this module.␊ |
35 | */␊ |
36 | static void patch_cpuid_set_info_all(void* kernelData);␊ |
37 | static void patch_cpuid_set_info_32(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel);␊ |
38 | static void patch_cpuid_set_info_64(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel);␊ |
39 | ␊ |
40 | //static void patch_pmCPUExitHaltToOff(void* kernelData);␊ |
41 | static void patch_lapic_init(void* kernelData);␊ |
42 | static void patch_commpage_stuff_routine(void* kernelData);␊ |
43 | static void patch_lapic_configure(void* kernelData);␊ |
44 | //static void patch_lapic_interrupt(void* kernelData);␊ |
45 | ␊ |
46 | void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4, void* arg5, void* arg6);␊ |
47 | void kernel_patcher_ignore_cache(void* arg1, void* arg2, void* arg3, void *arg4, void* arg5, void* arg6);␊ |
48 | void kernel_patcher_ignore_cache(void* arg1, void* arg2, void* arg3, void *arg4, void* arg5, void* arg6){}␊ |
49 | ␊ |
50 | void KernelPatcher_start(void);␊ |
51 | void KernelPatcher_start(void)␊ |
52 | {␊ |
53 | ␉register_kernel_patch(patch_cpuid_set_info_all, KERNEL_ANY, CPUID_MODEL_UNKNOWN); ␊ |
54 | ␉␊ |
55 | ␉register_kernel_patch(patch_commpage_stuff_routine, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
56 | ␉␊ |
57 | ␉register_kernel_patch(patch_lapic_init, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
58 | ␉␊ |
59 | ␉// NOTE: following is currently 32bit only␊ |
60 | ␉register_kernel_patch(patch_lapic_configure, KERNEL_32, CPUID_MODEL_ANY);␊ |
61 | ␉␊ |
62 | ␉register_kernel_symbol(KERNEL_ANY, "_panic");␊ |
63 | ␉register_kernel_symbol(KERNEL_ANY, "_cpuid_set_info");␊ |
64 | ␉register_kernel_symbol(KERNEL_ANY, "_pmCPUExitHaltToOff");␊ |
65 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_init");␊ |
66 | ␉register_kernel_symbol(KERNEL_ANY, "_commpage_stuff_routine");␊ |
67 | ␉␊ |
68 | ␉// lapic_configure symbols␊ |
69 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_configure");␊ |
70 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_start");␊ |
71 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt_base");␊ |
72 | ␉␊ |
73 | ␉// lapic_interrup symbols␊ |
74 | ␉//register_kernel_patch(patch_lapic_interrupt, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
75 | ␉//register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt");␊ |
76 | ␉␊ |
77 | ␉// TODO: register needed symbols␊ |
78 | ␉␊ |
79 | ␉register_hook_callback("ExecKernel", &patch_kernel); ␊ |
80 | ␉␊ |
81 | ␉replace_system_function("_getKernelCachePath", &kernel_patcher_ignore_cache);␊ |
82 | }␊ |
83 | ␊ |
84 | /*␊ |
85 | * Register a kernel patch␊ |
86 | */␊ |
87 | static void register_kernel_patch(void* patch, int arch, int cpus)␊ |
88 | {␊ |
89 | ␉// TODO: only insert valid patches based on current cpuid and architecture␊ |
90 | ␉// AKA, don't at 64bit patches if it's a 32bit only machine␊ |
91 | ␉patchRoutine_t* entry;␊ |
92 | ␉␊ |
93 | ␉// Check to ensure that the patch is valid on this machine␊ |
94 | ␉// If it is not, exit early form this function␊ |
95 | ␉if(cpus != get_env(envModel))␊ |
96 | ␉{␊ |
97 | ␉␉if(cpus != CPUID_MODEL_ANY)␊ |
98 | ␉␉{␊ |
99 | ␉␉␉if(cpus == CPUID_MODEL_UNKNOWN)␊ |
100 | ␉␉␉{␊ |
101 | ␉␉␉␉switch(get_env(envModel))␊ |
102 | ␉␉␉␉{␊ |
103 | ␉␉␉␉␉case 13:␊ |
104 | ␉␉␉␉␉case CPUID_MODEL_YONAH:␊ |
105 | ␉␉␉␉␉case CPUID_MODEL_MEROM:␊ |
106 | ␉␉␉␉␉case CPUID_MODEL_PENRYN:␊ |
107 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM:␊ |
108 | ␉␉␉␉␉case CPUID_MODEL_FIELDS:␊ |
109 | ␉␉␉␉␉case CPUID_MODEL_DALES:␊ |
110 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␊ |
111 | ␉␉␉␉␉␉// Known cpu's we don't want to add the patch␊ |
112 | ␉␉␉␉␉␉return;␊ |
113 | ␉␉␉␉␉␉break;␊ |
114 | ␉␉␉␉␉␉␊ |
115 | ␉␉␉␉␉default:␊ |
116 | ␉␉␉␉␉␉// CPU not in supported list, so we are going to add␊ |
117 | ␉␉␉␉␉␉// The patch will be applied␊ |
118 | ␉␉␉␉␉␉break;␊ |
119 | ␉␉␉␉}␊ |
120 | ␉␉␉}␊ |
121 | ␉␉␉else␊ |
122 | ␉␉␉{␊ |
123 | ␉␉␉␉// Invalid cpuid for current cpu. Ignoring patch␊ |
124 | ␉␉␉␉return;␊ |
125 | ␉␉␉}␊ |
126 | ␉␉}␊ |
127 | ␉}␊ |
128 | ␉␊ |
129 | ␉if(patches == NULL)␊ |
130 | ␉{␊ |
131 | ␉␉patches = entry = calloc(1,sizeof(patchRoutine_t));␊ |
132 | ␉␉␊ |
133 | ␉␉if (!entry || !patches) return;␊ |
134 | ␉␉␊ |
135 | ␉}␊ |
136 | ␉else␊ |
137 | ␉{␊ |
138 | ␉␉entry = patches;␊ |
139 | ␉␉while(entry->next)␊ |
140 | ␉␉{␊ |
141 | ␉␉␉entry = entry->next;␊ |
142 | ␉␉}␊ |
143 | ␉␉␊ |
144 | ␉␉entry->next = malloc(sizeof(patchRoutine_t));␊ |
145 | ␉␉␊ |
146 | ␉␉if (!entry->next) return;␊ |
147 | ␉␉if (!entry) ␊ |
148 | ␉␉{␊ |
149 | ␉␉␉free(entry->next);␊ |
150 | ␉␉␉return; ␊ |
151 | ␉␉}␊ |
152 | ␉␉␊ |
153 | ␉␉bzero(entry->next, sizeof(patchRoutine_t));␊ |
154 | ␉␉␊ |
155 | ␉␉entry = entry->next;␊ |
156 | ␉}␊ |
157 | ␉␊ |
158 | ␉entry->next = NULL;␊ |
159 | ␉entry->patchRoutine = patch;␊ |
160 | ␉entry->validArchs = arch;␊ |
161 | ␉entry->validCpu = cpus;␊ |
162 | }␊ |
163 | ␊ |
164 | static void register_kernel_symbol(int kernelType, const char* name)␊ |
165 | {␊ |
166 | ␉if(kernelSymbols == NULL)␊ |
167 | ␉{␊ |
168 | ␉␉kernelSymbols = malloc(sizeof(kernSymbols_t));␊ |
169 | ␉␉if (!kernelSymbols) return;␊ |
170 | ␉␉bzero(kernelSymbols,sizeof(kernSymbols_t));␊ |
171 | ␉␉kernelSymbols->next = NULL;␊ |
172 | ␉␉kernelSymbols->symbol = (char*)name;␊ |
173 | ␉␉kernelSymbols->addr = 0;␊ |
174 | ␉}␊ |
175 | ␉else␊ |
176 | ␉{␊ |
177 | ␉␉kernSymbols_t *symbol = kernelSymbols;␊ |
178 | ␉␉while(symbol->next != NULL)␊ |
179 | ␉␉{␊ |
180 | ␉␉␉symbol = symbol->next;␊ |
181 | ␉␉}␊ |
182 | ␉␉␊ |
183 | ␉␉symbol->next = malloc(sizeof(kernSymbols_t));␊ |
184 | ␉␉if (!symbol->next) return;␊ |
185 | ␉␉bzero(symbol->next,sizeof(kernSymbols_t));␊ |
186 | ␉␉␊ |
187 | ␉␉symbol = symbol->next;␊ |
188 | ␉␉␊ |
189 | ␉␉symbol->next = NULL;␊ |
190 | ␉␉symbol->symbol = (char*)name;␊ |
191 | ␉␉symbol->addr = 0;␊ |
192 | ␉}␊ |
193 | }␊ |
194 | ␊ |
195 | static kernSymbols_t* lookup_kernel_symbol(const char* name)␊ |
196 | {␊ |
197 | ␉kernSymbols_t *symbol = kernelSymbols;␊ |
198 | ␉␊ |
199 | ␉while(symbol && strcmp(symbol->symbol, name) !=0)␊ |
200 | ␉{␊ |
201 | ␉␉symbol = symbol->next;␊ |
202 | ␉}␊ |
203 | ␉␊ |
204 | ␉if(!symbol)␊ |
205 | ␉{␊ |
206 | ␉␉return NULL;␊ |
207 | ␉}␊ |
208 | ␉else␊ |
209 | ␉{␊ |
210 | ␉␉return symbol;␊ |
211 | ␉}␊ |
212 | }␊ |
213 | ␊ |
214 | void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4, void* arg5, void* arg6)␊ |
215 | {␊ |
216 | ␉patchRoutine_t* entry = patches;␊ |
217 | ␉␊ |
218 | ␉int arch = determineKernelArchitecture(kernelData);␊ |
219 | ␉␊ |
220 | ␉locate_symbols(kernelData);␊ |
221 | ␉␊ |
222 | ␉if(patches != NULL)␊ |
223 | ␉{␊ |
224 | ␉␉while(entry)␊ |
225 | ␉␉{␊ |
226 | ␉␉␉if(entry->validArchs == KERNEL_ANY || arch == entry->validArchs)␊ |
227 | ␉␉␉{␊ |
228 | ␉␉␉␉if(entry->patchRoutine) entry->patchRoutine(kernelData);␊ |
229 | ␉␉␉}␊ |
230 | ␉␉␉entry = entry->next;␊ |
231 | ␉␉}␊ |
232 | ␉}␊ |
233 | }␊ |
234 | ␊ |
235 | static int determineKernelArchitecture(void* kernelData)␊ |
236 | {␉␊ |
237 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC)␊ |
238 | ␉{␊ |
239 | ␉␉return KERNEL_32;␊ |
240 | ␉}␊ |
241 | ␉␊ |
242 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC_64)␊ |
243 | ␉{␊ |
244 | ␉␉return KERNEL_64;␊ |
245 | ␉}␊ |
246 | ␉else␊ |
247 | ␉{␊ |
248 | ␉␉return KERNEL_ERR;␊ |
249 | ␉}␊ |
250 | }␊ |
251 | ␊ |
252 | static unsigned int parse_mach_64(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long, char))␉// TODO: add param to specify valid archs␊ |
253 | {␉␊ |
254 | ␉char is64 = false;␊ |
255 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
256 | ␉EFI_STATUS bind_status = EFI_SUCCESS;␊ |
257 | ␊ |
258 | ␉// TODO convert all of the structs to a union␉␊ |
259 | ␉struct dyld_info_command* dyldInfoCommand = NULL;␉␊ |
260 | ␉struct symtab_command* symtabCommand = NULL;␉␊ |
261 | ␉␊ |
262 | ␉{␊ |
263 | ␉␉struct segment_command *segCommand = NULL;␊ |
264 | ␉␉struct segment_command_64 *segCommand64 = NULL;␊ |
265 | ␉␉struct load_command *loadCommand = NULL;␊ |
266 | ␉␉UInt32 binaryIndex = 0;␊ |
267 | ␉␉UInt16 cmd = 0;␊ |
268 | ␉␉␊ |
269 | ␉␉// Parse through the load commands␊ |
270 | ␉␉if(((struct mach_header*)binary)->magic == MH_MAGIC)␊ |
271 | ␉␉{␊ |
272 | ␉␉␉is64 = false;␊ |
273 | ␉␉␉binaryIndex += sizeof(struct mach_header);␊ |
274 | ␉␉}␊ |
275 | ␉␉else if(((struct mach_header_64*)binary)->magic == MH_MAGIC_64)␊ |
276 | ␉␉{␊ |
277 | ␉␉␉// NOTE: modules cannot be 64bit...␊ |
278 | ␉␉␉is64 = true;␊ |
279 | ␉␉␉binaryIndex += sizeof(struct mach_header_64);␊ |
280 | ␉␉}␊ |
281 | ␉␉else␊ |
282 | ␉␉{␊ |
283 | ␉␉␉printf("Modules: Invalid mach magic\n");␊ |
284 | ␉␉␉getc();␊ |
285 | ␉␉␉return 0xFFFFFFFF;␊ |
286 | ␉␉}␊ |
287 | ␉␉␊ |
288 | ␉␉␊ |
289 | ␉␉␊ |
290 | ␉␉/*if(((struct mach_header*)binary)->filetype != MH_DYLIB)␊ |
291 | ␉␉ {␊ |
292 | ␉␉ printf("Module is not a dylib. Unable to load.\n");␊ |
293 | ␉␉ getc();␊ |
294 | ␉␉ return NULL; // Module is in the incorrect format␊ |
295 | ␉␉ }*/␊ |
296 | ␉␉␊ |
297 | ␉␉while(cmd < ((struct mach_header*)binary)->ncmds)␊ |
298 | ␉␉{␊ |
299 | ␉␉␉cmd++;␊ |
300 | ␉␉␉␊ |
301 | ␉␉␉loadCommand = binary + binaryIndex;␊ |
302 | ␉␉␉UInt32 cmdSize = loadCommand->cmdsize;␊ |
303 | ␉␉␉␊ |
304 | ␉␉␉␊ |
305 | ␉␉␉switch ((loadCommand->cmd & 0x7FFFFFFF))␊ |
306 | ␉␉␉{␊ |
307 | ␉␉␉␉case LC_SYMTAB:␊ |
308 | ␉␉␉␉␉symtabCommand = binary + binaryIndex;␊ |
309 | ␉␉␉␉␉break;␊ |
310 | ␉␉␉␉␉␊ |
311 | ␉␉␉␉case LC_SEGMENT: // 32bit macho␊ |
312 | ␉␉␉␉{␊ |
313 | ␉␉␉␉␉segCommand = binary + binaryIndex;␊ |
314 | ␉␉␉␉␉␊ |
315 | ␉␉␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
316 | ␉␉␉␉␉␊ |
317 | ␉␉␉␉␉if(strncmp("__TEXT", segCommand->segname, sizeof("__TEXT")) == 0)␊ |
318 | ␉␉␉␉␉{␊ |
319 | ␉␉␉␉␉␉UInt32 sectionIndex;␊ |
320 | ␉␉␉␉␉␉␊ |
321 | #if DEBUG_KERNEL_PATCHER␊ |
322 | ␉␉␉␉␉␉unsigned long fileaddr;␊ |
323 | ␉␉␉␉␉␉long filesize;␉␉␉␉␉␊ |
324 | ␉␉␉␉␉␉vmaddr = (segCommand->vmaddr & 0x3fffffff);␊ |
325 | ␉␉␉␉␉␉vmsize = segCommand->vmsize;␉ ␊ |
326 | ␉␉␉␉␉␉fileaddr = ((unsigned long)(binary + binaryIndex) + segCommand->fileoff);␊ |
327 | ␉␉␉␉␉␉filesize = segCommand->filesize;␊ |
328 | ␉␉␉␉␉␉␊ |
329 | ␉␉␉␉␉␉printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",␊ |
330 | ␉␉␉␉␉␉␉ segCommand->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize,␊ |
331 | ␉␉␉␉␉␉␉ (unsigned) segCommand->nsects, (unsigned)segCommand->flags);␊ |
332 | #if DEBUG_KERNEL_PATCHER==2␊ |
333 | ␉␉␉␉␉␉␊ |
334 | ␉␉␉␉␉␉getc();␊ |
335 | #endif␊ |
336 | #endif␊ |
337 | ␉␉␉␉␉␉␊ |
338 | ␉␉␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
339 | ␉␉␉␉␉␉␊ |
340 | ␉␉␉␉␉␉struct section *sect;␊ |
341 | ␉␉␉␉␉␉␊ |
342 | ␉␉␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
343 | ␉␉␉␉␉␉{␊ |
344 | ␉␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
345 | ␉␉␉␉␉␉␉␊ |
346 | ␉␉␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
347 | ␉␉␉␉␉␉␉␊ |
348 | ␉␉␉␉␉␉␉␊ |
349 | ␉␉␉␉␉␉␉if(strncmp("__text", sect->sectname,sizeof("__text")) == 0)␊ |
350 | ␉␉␉␉␉␉␉{␊ |
351 | ␉␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
352 | ␉␉␉␉␉␉␉␉textSection = sect->offset;␊ |
353 | ␉␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
354 | ␉␉␉␉␉␉␉␉break;␊ |
355 | ␉␉␉␉␉␉␉}␉␉␉␉␉␊ |
356 | ␉␉␉␉␉␉}␊ |
357 | ␉␉␉␉␉}␊ |
358 | ␉␉␉␉␉break;␊ |
359 | ␉␉␉␉}␉␊ |
360 | ␉␉␉␉case LC_SEGMENT_64:␉// 64bit macho's␊ |
361 | ␉␉␉␉{␊ |
362 | ␉␉␉␉␉segCommand64 = binary + binaryIndex;␊ |
363 | ␉␉␉␉␉␊ |
364 | ␉␉␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
365 | ␉␉␉␉␉␊ |
366 | ␉␉␉␉␉if(strncmp("__TEXT", segCommand64->segname, sizeof("__TEXT")) == 0)␊ |
367 | ␉␉␉␉␉{␊ |
368 | ␉␉␉␉␉␉UInt32 sectionIndex;␊ |
369 | ␉␉␉␉␉␉␊ |
370 | #if DEBUG_KERNEL_PATCHER␉␉␉␉␉␉␊ |
371 | ␉␉␉␉␉␉unsigned long fileaddr;␊ |
372 | ␉␉␉␉␉␉long filesize;␉␉␉␉␉␊ |
373 | ␉␉␉␉␉␉vmaddr = (segCommand64->vmaddr & 0x3fffffff);␊ |
374 | ␉␉␉␉␉␉vmsize = segCommand64->vmsize;␉ ␊ |
375 | ␉␉␉␉␉␉fileaddr = ((unsigned long)(binary + binaryIndex) + segCommand64->fileoff);␊ |
376 | ␉␉␉␉␉␉filesize = segCommand64->filesize;␊ |
377 | ␉␉␉␉␉␉␊ |
378 | ␉␉␉␉␉␉printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",␊ |
379 | ␉␉␉␉␉␉␉ segCommand64->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize,␊ |
380 | ␉␉␉␉␉␉␉ (unsigned) segCommand64->nsects, (unsigned)segCommand64->flags);␊ |
381 | #if DEBUG_KERNEL_PATCHER==2␊ |
382 | ␉␉␉␉␉␉␊ |
383 | ␉␉␉␉␉␉getc();␊ |
384 | #endif␊ |
385 | #endif␊ |
386 | ␉␉␉␉␉␉␊ |
387 | ␉␉␉␉␉␉sectionIndex = sizeof(struct segment_command_64);␊ |
388 | ␉␉␉␉␉␉␊ |
389 | ␉␉␉␉␉␉struct section_64 *sect;␊ |
390 | ␉␉␉␉␉␉␊ |
391 | ␉␉␉␉␉␉while(sectionIndex < segCommand64->cmdsize)␊ |
392 | ␉␉␉␉␉␉{␊ |
393 | ␉␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
394 | ␉␉␉␉␉␉␉␊ |
395 | ␉␉␉␉␉␉␉sectionIndex += sizeof(struct section_64);␊ |
396 | ␉␉␉␉␉␉␉␊ |
397 | ␉␉␉␉␉␉␉␊ |
398 | ␉␉␉␉␉␉␉if(strncmp("__text", sect->sectname, sizeof("__text")) == 0)␊ |
399 | ␉␉␉␉␉␉␉{␊ |
400 | ␉␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
401 | ␉␉␉␉␉␉␉␉textSection = sect->offset;␊ |
402 | ␉␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
403 | ␉␉␉␉␉␉␉␉␊ |
404 | ␉␉␉␉␉␉␉␉break;␊ |
405 | ␉␉␉␉␉␉␉}␉␉␉␉␉␊ |
406 | ␉␉␉␉␉␉}␊ |
407 | ␉␉␉␉␉}␊ |
408 | ␉␉␉␉␉␊ |
409 | ␉␉␉␉␉break;␊ |
410 | ␉␉␉␉}␊ |
411 | ␉␉␉␉case LC_DYSYMTAB:␊ |
412 | ␉␉␉␉␉break;␊ |
413 | ␉␉␉␉␉␊ |
414 | ␉␉␉␉case LC_LOAD_DYLIB:␊ |
415 | ␉␉␉␉case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:␊ |
416 | break;␊ |
417 | ␊ |
418 | ␉␉␉␉case LC_ID_DYLIB:␊ |
419 | break;␊ |
420 | ␊ |
421 | ␉␉␉␉␉␊ |
422 | ␉␉␉␉case LC_DYLD_INFO:␊ |
423 | ␉␉␉␉␉// Bind and rebase info is stored here␊ |
424 | ␉␉␉␉␉dyldInfoCommand = binary + binaryIndex;␊ |
425 | ␉␉␉␉␉break;␊ |
426 | ␉␉␉␉␉␊ |
427 | ␉␉␉␉case LC_UUID:␊ |
428 | ␉␉␉␉␉break;␊ |
429 | ␉␉␉␉␉␊ |
430 | ␉␉␉␉case LC_UNIXTHREAD:␊ |
431 | ␉␉␉␉␉break;␊ |
432 | ␉␉␉␉␉␊ |
433 | ␉␉␉␉default:␊ |
434 | ␉␉␉␉␉DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);␊ |
435 | ␉␉␉␉␉break;␊ |
436 | ␉␉␉␉␉␊ |
437 | ␉␉␉}␊ |
438 | ␉␉␉␊ |
439 | ␉␉␉binaryIndex += cmdSize;␊ |
440 | ␉␉}␊ |
441 | ␉␉//if(!moduleName) return NULL;␊ |
442 | ␉}␉␉␊ |
443 | ␉␊ |
444 | ␉// bind_macho uses the symbols.␊ |
445 | ␉module_start = handle_symtable_64(module, (UInt32)binary, symtabCommand, symbol_handler, is64);␊ |
446 | ␉␊ |
447 | ␉// Rebase the module before binding it.␊ |
448 | ␉if(dyldInfoCommand && dyldInfoCommand->rebase_off)␊ |
449 | ␉{␊ |
450 | ␉␉rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);␊ |
451 | ␉}␊ |
452 | ␉␊ |
453 | ␉if(dyldInfoCommand && dyldInfoCommand->bind_off)␊ |
454 | ␉{␊ |
455 | ␉␉bind_status = bind_macho(module, binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size);␊ |
456 | ␉}␊ |
457 | ␉␊ |
458 | ␉if(dyldInfoCommand && dyldInfoCommand->weak_bind_off && (bind_status == EFI_SUCCESS))␊ |
459 | ␉{␊ |
460 | ␉␉// NOTE: this currently should never happen.␊ |
461 | ␉␉bind_status = bind_macho(module, binary, (char*)dyldInfoCommand->weak_bind_off, dyldInfoCommand->weak_bind_size);␊ |
462 | ␉}␊ |
463 | ␉␊ |
464 | ␉if(dyldInfoCommand && dyldInfoCommand->lazy_bind_off && (bind_status == EFI_SUCCESS))␊ |
465 | ␉{␊ |
466 | ␉␉// NOTE: we are binding the lazy pointers as a module is laoded,␊ |
467 | ␉␉// This should be changed to bind when a symbol is referened at runtime instead.␊ |
468 | ␉␉bind_status = bind_macho(module, binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);␊ |
469 | ␉}␊ |
470 | ␉␊ |
471 | if (bind_status != EFI_SUCCESS) {␊ |
472 | module_start = 0xFFFFFFFF;␊ |
473 | }␊ |
474 | ␊ |
475 | ␉return module_start;␊ |
476 | ␉␊ |
477 | }␊ |
478 | ␊ |
479 | static unsigned int handle_symtable_64(char *module, UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, char*, long long, char), char is64)␊ |
480 | {␉␉␊ |
481 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
482 | ␉␊ |
483 | ␉UInt32 symbolIndex = 0;␊ |
484 | if (!symtabCommand) {␊ |
485 | return 0xFFFFFFFF;␊ |
486 | }␊ |
487 | ␉char* symbolString = base + (char*)symtabCommand->stroff;␊ |
488 | ␉if(!is64)␊ |
489 | ␉{␊ |
490 | ␉␉struct nlist* symbolEntry = (void*)base + symtabCommand->symoff;␊ |
491 | ␉␉while(symbolIndex < symtabCommand->nsyms)␊ |
492 | ␉␉{␉␉␉␉␉␉␊ |
493 | ␉␉␉if(symbolEntry->n_value)␊ |
494 | ␉␉␉{␉␉␉␉␊ |
495 | ␉␉␉␉if(strstr(symbolString + symbolEntry->n_un.n_strx, "module_start") || (strncmp(symbolString + symbolEntry->n_un.n_strx, "start", sizeof("start")) == 0))␊ |
496 | ␉␉␉␉{␊ |
497 | ␉␉␉␉␉module_start = base + symbolEntry->n_value;␊ |
498 | ␉␉␉␉␉DBG("n_value %x module_start %x\n", (unsigned)symbolEntry->n_value, (unsigned)module_start);␊ |
499 | ␉␉␉␉}␊ |
500 | ␉␉␉␉else␊ |
501 | ␉␉␉␉{␊ |
502 | ␉␉␉␉␉symbol_handler(module, symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64);␊ |
503 | ␉␉␉␉␉␊ |
504 | ␉␉␉␉␉␊ |
505 | ␉␉␉␉}␊ |
506 | #if DEBUG_KERNEL_PATCHER␊ |
507 | ␉␉␉␉bool isTexT = (((unsigned)symbolEntry->n_value > (unsigned)vmaddr) && ((unsigned)(vmaddr + vmsize) > (unsigned)symbolEntry->n_value ));␊ |
508 | ␉␉␉␉printf("%s %s\n", isTexT ? "__TEXT :" : "__DATA(OR ANY) :", symbolString + symbolEntry->n_un.n_strx);␊ |
509 | #if DEBUG_KERNEL_PATCHER==2␉␊ |
510 | ␉␉␉␉␊ |
511 | ␉␉␉␉if(strcmp(symbolString + symbolEntry->n_un.n_strx, "_BootHelp_txt") == 0)␊ |
512 | ␉␉␉␉{␊ |
513 | ␉␉␉␉␉long long addr = (long long)base + symbolEntry->n_value;␊ |
514 | ␉␉␉␉␉unsigned char *BootHelp = NULL;␊ |
515 | ␉␉␉␉␉BootHelp = (unsigned char*)(UInt32)addr;␉␉␉␉␉␊ |
516 | ␉␉␉␉␉printf("method 1: __DATA : BootHelp_txt[0] %x\n", BootHelp[0]);␊ |
517 | ␉␉␉␉␉␊ |
518 | ␉␉␉␉␉long long addr2 = symbolEntry->n_value;␊ |
519 | ␉␉␉␉␉unsigned char *BootHelp2 = NULL;␊ |
520 | ␉␉␉␉␉BootHelp2 = (unsigned char*)(UInt32)addr2;␉␉␉␉␉␊ |
521 | ␉␉␉␉␉printf("method 2: __DATA : BootHelp_txt[0] %x\n", BootHelp2[0]);␊ |
522 | ␉␉␉␉}␊ |
523 | #endif␊ |
524 | #endif␊ |
525 | ␉␉␉␉␊ |
526 | ␉␉␉}␊ |
527 | ␉␉␉␊ |
528 | ␉␉␉symbolEntry++;␊ |
529 | ␉␉␉symbolIndex++;␉// TODO remove␊ |
530 | ␉␉}␊ |
531 | ␉}␊ |
532 | ␉else␊ |
533 | ␉{␊ |
534 | ␉␉struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;␊ |
535 | ␉␉// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now)␉␊ |
536 | ␉␉while(symbolIndex < symtabCommand->nsyms)␊ |
537 | ␉␉{␉␊ |
538 | ␉␉␉␊ |
539 | ␉␉␉if(strstr(symbolString + symbolEntry->n_un.n_strx, "module_start") || (strncmp(symbolString + symbolEntry->n_un.n_strx, "start",sizeof("start")) == 0))␊ |
540 | ␉␉␉{␊ |
541 | ␉␉␉␉module_start = (unsigned int)(base + symbolEntry->n_value);␊ |
542 | ␉␉␉}␊ |
543 | ␉␉␉else␊ |
544 | ␉␉␉{␊ |
545 | ␉␉␉␉symbol_handler(module, symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64);␊ |
546 | ␉␉␉}␊ |
547 | ␉␉␉␊ |
548 | ␉␉␉symbolEntry++;␊ |
549 | ␉␉␉symbolIndex++;␉// TODO remove␊ |
550 | ␉␉}␊ |
551 | ␉}␉␊ |
552 | ␉return module_start;␊ |
553 | ␉␊ |
554 | }␊ |
555 | ␊ |
556 | /**␊ |
557 | **␉␉This functions located the requested symbols in the mach-o file.␊ |
558 | **␉␉␉as well as determines the start of the __TEXT segment and __TEXT,__text sections␊ |
559 | **/␊ |
560 | static int locate_symbols(void* kernelData)␊ |
561 | {␊ |
562 | ␉char is64 = 1;␊ |
563 | ␉parse_mach_64("VirtualXnuSyms",kernelData, symbol_handler);␊ |
564 | ␉//handle_symtable((UInt32)kernelData, symtableData, &symbol_handler, determineKernelArchitecture(kernelData) == KERNEL_64);␊ |
565 | ␉return 1 << is64;␊ |
566 | }␊ |
567 | ␊ |
568 | long long symbol_handler(char* module, char* symbolName, long long addr, char is64)␊ |
569 | {␊ |
570 | ␉// Locate the symbol in the list, if it exists, update it's address␊ |
571 | ␉kernSymbols_t *symbol = lookup_kernel_symbol(symbolName);␊ |
572 | ␉␊ |
573 | ␉if(symbol)␊ |
574 | ␉{␊ |
575 | ␉␉symbol->addr = addr;␊ |
576 | ␉}␊ |
577 | ␉␊ |
578 | ␉return 0xFFFFFFFF; // fixme␊ |
579 | }␊ |
580 | ␊ |
581 | /**␊ |
582 | ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it␊ |
583 | ** Or replace it so that the cpuid is set to a valid value.␊ |
584 | **/␊ |
585 | static void patch_cpuid_set_info_all(void* kernelData)␊ |
586 | {␊ |
587 | ␉switch(get_env(envModel))␊ |
588 | ␉{␊ |
589 | ␉␉case CPUID_MODEL_ATOM:␊ |
590 | ␉␉␉if(determineKernelArchitecture(kernelData) == KERNEL_32)␊ |
591 | ␉␉␉{␊ |
592 | ␉␉␉␉patch_cpuid_set_info_32(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);␊ |
593 | ␉␉␉}␊ |
594 | ␉␉␉else ␊ |
595 | ␉␉␉{␊ |
596 | ␉␉␉␉patch_cpuid_set_info_64(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);␊ |
597 | ␉␉␉}␊ |
598 | ␉␉␉␊ |
599 | ␉␉␉break;␊ |
600 | ␉␉␉␊ |
601 | ␉␉default:␊ |
602 | ␉␉{␊ |
603 | ␉␉␉// AnV: Extra cpuid fix for spoofing Nehalem CPU for i5/i9␊ |
604 | ␉␉␉switch(get_env(envFamily))␊ |
605 | ␉␉␉{␊ |
606 | ␉␉␉␉case 0x1E: /* Intel i5 */␊ |
607 | ␉␉␉␉case 0x2C: /* Intel i9 */␊ |
608 | ␉␉␉␉␉if(determineKernelArchitecture(kernelData) == KERNEL_32)␊ |
609 | ␉␉␉␉␉{␊ |
610 | ␉␉␉␉␉␉patch_cpuid_set_info_32(kernelData, CPUFAMILY_INTEL_NEHALEM, CPUID_MODEL_NEHALEM);␊ |
611 | ␉␉␉␉␉}␊ |
612 | ␉␉␉␉␉else ␊ |
613 | ␉␉␉␉␉{␊ |
614 | ␉␉␉␉␉␉patch_cpuid_set_info_64(kernelData, CPUFAMILY_INTEL_NEHALEM, CPUID_MODEL_NEHALEM);␊ |
615 | ␉␉␉␉␉}␊ |
616 | ␉␉␉␉␉␊ |
617 | ␉␉␉␉␉break;␊ |
618 | ␉␉␉␉␉␊ |
619 | ␉␉␉␉default:␊ |
620 | ␉␉␉␉␉if(determineKernelArchitecture(kernelData) == KERNEL_32)␊ |
621 | ␉␉␉␉␉{␊ |
622 | ␉␉␉␉␉␉patch_cpuid_set_info_32(kernelData, 0, 0);␊ |
623 | ␉␉␉␉␉}␊ |
624 | ␉␉␉␉␉else␊ |
625 | ␉␉␉␉␉{␊ |
626 | ␉␉␉␉␉␉patch_cpuid_set_info_64(kernelData, 0, 0);␊ |
627 | ␉␉␉␉␉}␉␉␉␉␉␊ |
628 | ␉␉␉␉␉break;␊ |
629 | ␉␉␉}␊ |
630 | ␉␉␉break;␉␉␉␊ |
631 | ␉␉}␊ |
632 | ␉}␊ |
633 | }␊ |
634 | ␊ |
635 | static void patch_cpuid_set_info_64(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)␊ |
636 | {␊ |
637 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
638 | ␉␊ |
639 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");␊ |
640 | ␉␊ |
641 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //␉(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
642 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
643 | ␉␊ |
644 | ␉//UInt32 jumpLocation = 0;␊ |
645 | ␉␊ |
646 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
647 | ␉{␊ |
648 | ␉␉verbose("Unable to locate _cpuid_set_info\n");␊ |
649 | ␉␉return;␊ |
650 | ␉}␊ |
651 | ␉␊ |
652 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
653 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
654 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
655 | ␉{␊ |
656 | ␉␉printf("Unable to locate _panic\n");␊ |
657 | ␉␉return;␊ |
658 | ␉}␊ |
659 | ␉panicAddr -= (UInt32)kernelData;␊ |
660 | ␉␊ |
661 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
662 | ␉while( ␊ |
663 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
664 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
665 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
666 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
667 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
668 | ␉␉ )␊ |
669 | ␉{␊ |
670 | ␉␉patchLocation++;␊ |
671 | ␉}␊ |
672 | ␉patchLocation--;␊ |
673 | ␉␊ |
674 | ␉// Remove panic just in ca se␊ |
675 | ␉// The panic instruction is exactly 5 bytes long.␊ |
676 | ␉bytes[patchLocation + 0] = 0x90;␊ |
677 | ␉bytes[patchLocation + 1] = 0x90;␊ |
678 | ␉bytes[patchLocation + 2] = 0x90;␊ |
679 | ␉bytes[patchLocation + 3] = 0x90;␊ |
680 | ␉bytes[patchLocation + 4] = 0x90;␊ |
681 | ␉␊ |
682 | ␉// Check for a 10.2.0+ kernel␊ |
683 | ␉if(bytes[patchLocation - 19] == 0xC7 && bytes[patchLocation - 18] == 0x05)␊ |
684 | ␉{␊ |
685 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 17] << 0 |␊ |
686 | ␉␉bytes[patchLocation - 16] << 8 |␊ |
687 | ␉␉bytes[patchLocation - 15] << 16 |␊ |
688 | ␉␉bytes[patchLocation - 14] << 24;␊ |
689 | ␉␉␊ |
690 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
691 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 310; ␊ |
692 | ␉␉␊ |
693 | ␉␉//ffffff8000228b3b -> 0x00490e8b␊ |
694 | ␉␉//ffffff8000228c28 -> -237 -> 0x490D9E -> -310␊ |
695 | ␉␉␊ |
696 | ␉␉// The mov is 10 bytes␊ |
697 | ␉␉/*␊ |
698 | ␉␉ bytes[patchLocation - 19] = 0x90;␉// c7␊ |
699 | ␉␉ bytes[patchLocation - 18] = 0x90;␉// 05␊ |
700 | ␉␉ bytes[patchLocation - 17] = 0x90;␉// family location␊ |
701 | ␉␉ bytes[patchLocation - 16] = 0x90;␉// family location␊ |
702 | ␉␉ bytes[patchLocation - 15] = 0x90;␉// family location␊ |
703 | ␉␉ bytes[patchLocation - 14] = 0x90;␉// family location␊ |
704 | ␉␉ */␊ |
705 | ␉␉bytes[patchLocation - 13] = (impersonateFamily & 0x000000FF) >> 0;␊ |
706 | ␉␉bytes[patchLocation - 12] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
707 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
708 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0xFF000000) >> 24;␊ |
709 | ␉␉␊ |
710 | ␉␉// The lea (%rip),%rip is 7 bytes␊ |
711 | ␉␉bytes[patchLocation - 9] = 0xC7;␊ |
712 | ␉␉bytes[patchLocation - 8] = 0x05;␊ |
713 | ␉␉bytes[patchLocation - 7] = ((cpuid_model_addr -10) & 0x000000FF) >> 0;␉// NOTE: this opcode is relative in 64bit mode, subtract offset␊ |
714 | ␉␉bytes[patchLocation - 6] = ((cpuid_model_addr -10) & 0x0000FF00) >> 8;␉␊ |
715 | ␉␉bytes[patchLocation - 5] = ((cpuid_model_addr -10) & 0x00FF0000) >> 16;␊ |
716 | ␉␉bytes[patchLocation - 4] = ((cpuid_model_addr -10) & 0xFF000000) >> 24;␊ |
717 | ␉␉bytes[patchLocation - 3] = impersonateModel;␉// cpuid_model␊ |
718 | ␉␉␊ |
719 | ␉␉// The xor eax eax is 2 bytes␊ |
720 | ␉␉bytes[patchLocation - 2] = 0x01;␉// cpuid_extmodel␊ |
721 | ␉␉bytes[patchLocation - 1] = 0x00;␉// cpuid_extfamily␊ |
722 | ␉␉␊ |
723 | ␉␉// The panic instruction is exactly 5 bytes long.␊ |
724 | ␉␉bytes[patchLocation - 0] = 0x02;␉// cpuid_stepping␊ |
725 | ␉␉/*bytes[patchLocation + 1] = 0x90;␊ |
726 | ␉␉ bytes[patchLocation + 2] = 0x90;␊ |
727 | ␉␉ bytes[patchLocation + 3] = 0x90;␊ |
728 | ␉␉ bytes[patchLocation + 4] = 0x90;␊ |
729 | ␉␉ */␊ |
730 | ␉␉␊ |
731 | ␉␉// Panic call has been removed.␊ |
732 | ␉␉// Override the CPUID now. This requires ~ 10 bytes on 10.0.0 kernels␊ |
733 | ␉␉// On 10.2.0+ kernels, this requires ~16 bytes␊ |
734 | ␉␉␊ |
735 | ␉␉// Total: 24 bytes␊ |
736 | ␉␉printf("Running on a 10.2.0+ kernel\n");␊ |
737 | ␉␉getc();␊ |
738 | ␉}␊ |
739 | ␉else {␊ |
740 | ␉␉printf("Running on a 10.0.0 kernel, patch unsupported\n");␊ |
741 | ␉␉getc();␊ |
742 | ␉}␊ |
743 | }␊ |
744 | ␊ |
745 | static void patch_cpuid_set_info_32(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)␊ |
746 | {␉␊ |
747 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
748 | ␉␊ |
749 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");␊ |
750 | ␉␊ |
751 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //␉(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
752 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
753 | ␉␊ |
754 | ␉UInt32 jumpLocation = 0;␉␊ |
755 | ␉␊ |
756 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
757 | ␉{␊ |
758 | ␉␉verbose("Unable to locate _cpuid_set_info\n");␊ |
759 | ␉␉return;␊ |
760 | ␉}␊ |
761 | ␉␊ |
762 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
763 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
764 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
765 | ␉{␊ |
766 | ␉␉printf("Unable to locate _panic\n");␊ |
767 | ␉␉return;␊ |
768 | ␉}␊ |
769 | ␉panicAddr -= (UInt32)kernelData;␊ |
770 | ␉␊ |
771 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
772 | ␉while( ␊ |
773 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
774 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
775 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
776 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
777 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
778 | ␉␉ )␊ |
779 | ␉{␊ |
780 | ␉␉patchLocation++;␊ |
781 | ␉}␊ |
782 | ␉patchLocation--;␊ |
783 | ␉␊ |
784 | ␉// Remove panic call, just in case the following patch routines fail␊ |
785 | ␉bytes[patchLocation + 0] = 0x90;␊ |
786 | ␉bytes[patchLocation + 1] = 0x90;␊ |
787 | ␉bytes[patchLocation + 2] = 0x90;␊ |
788 | ␉bytes[patchLocation + 3] = 0x90;␊ |
789 | ␉bytes[patchLocation + 4] = 0x90;␊ |
790 | ␉␊ |
791 | ␉// Locate the jump call, so that 10 bytes can be reclamed.␊ |
792 | ␉// NOTE: This will *NOT* be located on pre 10.6.2 kernels␊ |
793 | ␉jumpLocation = patchLocation - 15;␊ |
794 | ␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
795 | ␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&␊ |
796 | ␉␉ (patchLocation - jumpLocation) < 0xF0)␊ |
797 | ␉{␊ |
798 | ␉␉jumpLocation--;␊ |
799 | ␉}␊ |
800 | ␉␊ |
801 | ␉// If found... AND we want to impersonate a specific cpumodel / family...␊ |
802 | ␉if(impersonateFamily &&␊ |
803 | ␉ impersonateModel &&␊ |
804 | ␉ ((patchLocation - jumpLocation) < 0xF0))␊ |
805 | ␉{␊ |
806 | ␉␉␊ |
807 | ␉␉bytes[jumpLocation] -= 10;␉␉// sizeof(movl␉$0x6b5a4cd2,0x00872eb4) = 10bytes␊ |
808 | ␉␉␊ |
809 | ␉␉/* ␊ |
810 | ␉␉ * Inpersonate the specified CPU FAMILY and CPU Model␊ |
811 | ␉␉ */␊ |
812 | ␉␉␊ |
813 | ␉␉// bytes[patchLocation - 17] = 0xC7;␉// already here... not needed to be done␊ |
814 | ␉␉// bytes[patchLocation - 16] = 0x05;␉// see above␊ |
815 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 15] << 0 |␊ |
816 | ␉␉bytes[patchLocation - 14] << 8 |␊ |
817 | ␉␉bytes[patchLocation - 13] << 16 |␊ |
818 | ␉␉bytes[patchLocation - 12] << 24;␊ |
819 | ␉␉␊ |
820 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
821 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299; ␊ |
822 | ␉␉␊ |
823 | ␉␉// cpufamily␊ |
824 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;␊ |
825 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
826 | ␉␉bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
827 | ␉␉bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;␊ |
828 | ␉␉␊ |
829 | ␉␉// NOPS, just in case if the jmp call wasn't patched, we'll jump to a␊ |
830 | ␉␉// nop and continue with the rest of the patch␊ |
831 | ␉␉// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few␊ |
832 | ␉␉// from the above code (only cpuid_model needs to be set.␊ |
833 | ␉␉bytes[patchLocation - 7] = 0x90;␊ |
834 | ␉␉bytes[patchLocation - 6] = 0x90;␊ |
835 | ␉␉␊ |
836 | ␉␉bytes[patchLocation - 5] = 0xC7;␊ |
837 | ␉␉bytes[patchLocation - 4] = 0x05;␊ |
838 | ␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
839 | ␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
840 | ␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
841 | ␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
842 | ␉␉␊ |
843 | ␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
844 | ␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
845 | ␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
846 | ␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
847 | ␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
848 | ␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
849 | ␉}␊ |
850 | ␉else if(impersonateFamily && impersonateModel)␊ |
851 | ␉{␊ |
852 | ␉␉// pre 10.6.2 kernel␊ |
853 | ␉␉// Locate the jump to directly *after* the panic call,␊ |
854 | ␉␉jumpLocation = patchLocation - 4;␊ |
855 | ␉␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
856 | ␉␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&␊ |
857 | ␉␉␉ (patchLocation - jumpLocation) < 0x20)␊ |
858 | ␉␉{␊ |
859 | ␉␉␉jumpLocation--;␊ |
860 | ␉␉}␊ |
861 | ␉␉// NOTE above isn't needed (I was going to use it, but I'm not, so instead,␊ |
862 | ␉␉// I'll just leave it to verify the binary stucture.␊ |
863 | ␉␉␊ |
864 | ␉␉// NOTE: the cpumodel_familt data is not set in _cpuid_set_info␊ |
865 | ␉␉// so we don't need to set it here, I'll get set later based on the model␊ |
866 | ␉␉// we set now.␊ |
867 | ␉␉␊ |
868 | ␉␉if((patchLocation - jumpLocation) < 0x20)␊ |
869 | ␉␉{␊ |
870 | ␉␉␉UInt32 cpuid_model_addr =␉(bytes[patchLocation - 14] << 0 |␊ |
871 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 13] << 8 |␊ |
872 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 12] << 16 |␊ |
873 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 11] << 24);␊ |
874 | ␉␉␉// Remove jump␊ |
875 | ␉␉␉bytes[patchLocation - 9] = 0x90;␉␉/// Was a jump if supported cpu␊ |
876 | ␉␉␉bytes[patchLocation - 8] = 0x90;␉␉// jumped past the panic call, we want to override the panic␊ |
877 | ␉␉␉␊ |
878 | ␉␉␉bytes[patchLocation - 7] = 0x90;␊ |
879 | ␉␉␉bytes[patchLocation - 6] = 0x90;␊ |
880 | ␉␉␉␊ |
881 | ␉␉␉bytes[patchLocation - 5] = 0xC7;␊ |
882 | ␉␉␉bytes[patchLocation - 4] = 0x05;␊ |
883 | ␉␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
884 | ␉␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
885 | ␉␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
886 | ␉␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
887 | ␉␉␉␊ |
888 | ␉␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
889 | ␉␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
890 | ␉␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
891 | ␉␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
892 | ␉␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
893 | ␉␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
894 | ␉␉␉␊ |
895 | #if 0␊ |
896 | ␉␉␉patchLocation = jumpLocation;␊ |
897 | #endif␊ |
898 | ␉␉␉// We now have 14 bytes available for a patch␊ |
899 | ␉␉}␊ |
900 | ␉␉else ␊ |
901 | ␉␉{␊ |
902 | ␉␉␉// Patching failed, using NOP replacement done initialy␊ |
903 | ␉␉}␊ |
904 | ␉}␊ |
905 | ␉else ␊ |
906 | ␉{␊ |
907 | ␉␉// Either We were unable to change the jump call due to the function's sctructure␊ |
908 | ␉␉// changing, or the user did not request a patch. As such, resort to just ␊ |
909 | ␉␉// removing the panic call (using NOP replacement above). Note that the␊ |
910 | ␉␉// IntelCPUPM kext may still panic due to the cpu's Model ID not being patched␊ |
911 | ␉}␊ |
912 | }␊ |
913 | ␊ |
914 | /**␊ |
915 | ** SleepEnabler.kext replacement (for those that need it)␊ |
916 | ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS␊ |
917 | **/␊ |
918 | #if 0␊ |
919 | static void patch_pmCPUExitHaltToOff(void* kernelData)␊ |
920 | {␊ |
921 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
922 | ␉␊ |
923 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_PmCpuExitHaltToOff");␊ |
924 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0;␊ |
925 | ␉␊ |
926 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
927 | ␉{␊ |
928 | ␉␉printf("Unable to locate _pmCPUExitHaltToOff\n");␊ |
929 | ␉␉return;␊ |
930 | ␉}␊ |
931 | ␉␊ |
932 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
933 | ␉␊ |
934 | ␉while(bytes[patchLocation - 1]␉!= 0xB8 ||␊ |
935 | ␉␉ bytes[patchLocation]␉␉!= 0x04 ||␉// KERN_INVALID_ARGUMENT (0x00000004)␊ |
936 | ␉␉ bytes[patchLocation + 1]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
937 | ␉␉ bytes[patchLocation + 2]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
938 | ␉␉ bytes[patchLocation + 3]␉!= 0x00)␉// KERN_INVALID_ARGUMENT␊ |
939 | ␉␉␊ |
940 | ␉{␊ |
941 | ␉␉patchLocation++;␊ |
942 | ␉}␊ |
943 | ␉bytes[patchLocation] = 0x00;␉// KERN_SUCCESS;␊ |
944 | }␊ |
945 | #endif␊ |
946 | ␊ |
947 | static void patch_lapic_init(void* kernelData)␊ |
948 | {␊ |
949 | ␉UInt8 panicIndex = 0;␊ |
950 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
951 | ␉␊ |
952 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_init");␊ |
953 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; ␊ |
954 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
955 | ␉{␊ |
956 | ␉␉printf("Unable to locate %s\n", "_lapic_init");␊ |
957 | ␉␉return;␊ |
958 | ␉}␊ |
959 | ␉␊ |
960 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
961 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; ␊ |
962 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
963 | ␉{␊ |
964 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
965 | ␉␉return;␊ |
966 | ␉}␊ |
967 | ␉␊ |
968 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
969 | ␉panicAddr -= (UInt32)kernelData;␉// Remove offset␊ |
970 | ␉␊ |
971 | ␉// Locate the (panicIndex + 1) panic call␊ |
972 | ␉while(panicIndex < 3)␉// Find the third panic call␊ |
973 | ␉{␊ |
974 | ␉␉while( ␊ |
975 | ␉␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
976 | ␉␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
977 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
978 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
979 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
980 | ␉␉␉ )␊ |
981 | ␉␉{␊ |
982 | ␉␉␉patchLocation++;␊ |
983 | ␉␉}␊ |
984 | ␉␉patchLocation++;␊ |
985 | ␉␉panicIndex++;␊ |
986 | ␉}␊ |
987 | ␉patchLocation--;␉// Remove extra increment from the < 3 while loop␊ |
988 | ␉␊ |
989 | ␉bytes[--patchLocation] = 0x90;␉␊ |
990 | ␉bytes[++patchLocation] = 0x90;␊ |
991 | ␉bytes[++patchLocation] = 0x90;␊ |
992 | ␉bytes[++patchLocation] = 0x90;␊ |
993 | ␉bytes[++patchLocation] = 0x90;␊ |
994 | }␊ |
995 | ␊ |
996 | static void patch_commpage_stuff_routine(void* kernelData)␊ |
997 | {␊ |
998 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
999 | ␉␊ |
1000 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_commpage_stuff_routine");␊ |
1001 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
1002 | ␉{␊ |
1003 | ␉␉//printf("Unable to locate %s\n", "_commpage_stuff_routine");␊ |
1004 | ␉␉return;␊ |
1005 | ␉␉␊ |
1006 | ␉}␊ |
1007 | ␉␊ |
1008 | ␉UInt32 patchLocation = symbol->addr - textAddress + textSection; ␊ |
1009 | ␉␊ |
1010 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
1011 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
1012 | ␉{␊ |
1013 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
1014 | ␉␉return;␊ |
1015 | ␉}␊ |
1016 | ␉UInt32 panicAddr = symbol->addr - textAddress; ␊ |
1017 | ␉␊ |
1018 | ␉patchLocation -= (UInt32)kernelData;␊ |
1019 | ␉panicAddr -= (UInt32)kernelData;␊ |
1020 | ␉␊ |
1021 | ␉while( ␊ |
1022 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
1023 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
1024 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
1025 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
1026 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
1027 | ␉␉ )␊ |
1028 | ␉{␊ |
1029 | ␉␉patchLocation++;␊ |
1030 | ␉}␊ |
1031 | ␉patchLocation--;␊ |
1032 | ␉␊ |
1033 | ␉// Replace panic with nops␊ |
1034 | ␉bytes[patchLocation + 0] = 0x90;␊ |
1035 | ␉bytes[patchLocation + 1] = 0x90;␊ |
1036 | ␉bytes[patchLocation + 2] = 0x90;␊ |
1037 | ␉bytes[patchLocation + 3] = 0x90;␊ |
1038 | ␉bytes[patchLocation + 4] = 0x90;␊ |
1039 | }␊ |
1040 | #if 0␊ |
1041 | static void patch_lapic_interrupt(void* kernelData)␊ |
1042 | {␊ |
1043 | ␉// NOTE: this is a hack untill I finish patch_lapic_configure␊ |
1044 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
1045 | ␉␊ |
1046 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_interrupt");␊ |
1047 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
1048 | ␉{␊ |
1049 | ␉␉printf("Unable to locate %s\n", "_lapic_interrupt");␊ |
1050 | ␉␉return;␊ |
1051 | ␉}␊ |
1052 | ␉␊ |
1053 | ␉UInt32 patchLocation = symbol->addr - textAddress + textSection; ␊ |
1054 | ␉␊ |
1055 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
1056 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
1057 | ␉{␊ |
1058 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
1059 | ␉␉return;␊ |
1060 | ␉}␊ |
1061 | ␉UInt32 panicAddr = symbol->addr - textAddress; ␊ |
1062 | ␉␊ |
1063 | ␉patchLocation -= (UInt32)kernelData;␊ |
1064 | ␉panicAddr -= (UInt32)kernelData;␊ |
1065 | ␉␊ |
1066 | ␉while( ␊ |
1067 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
1068 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
1069 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
1070 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
1071 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
1072 | ␉␉ )␊ |
1073 | ␉{␊ |
1074 | ␉␉patchLocation++;␊ |
1075 | ␉}␊ |
1076 | ␉patchLocation--;␊ |
1077 | ␉␊ |
1078 | ␉// Replace panic with nops␊ |
1079 | ␉bytes[patchLocation + 0] = 0x90;␊ |
1080 | ␉bytes[patchLocation + 1] = 0x90;␊ |
1081 | ␉bytes[patchLocation + 2] = 0x90;␊ |
1082 | ␉bytes[patchLocation + 3] = 0x90;␊ |
1083 | ␉bytes[patchLocation + 4] = 0x90;␊ |
1084 | }␊ |
1085 | #endif␊ |
1086 | static void patch_lapic_configure(void* kernelData)␊ |
1087 | {␊ |
1088 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
1089 | ␉␊ |
1090 | ␉UInt32 patchLocation;␊ |
1091 | ␉UInt32 lapicStart;␊ |
1092 | ␉UInt32 lapicInterruptBase;␊ |
1093 | ␉␊ |
1094 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_configure");␊ |
1095 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
1096 | ␉{␊ |
1097 | ␉␉printf("Unable to locate %s\n", "_lapic_configure");␊ |
1098 | ␉␉return;␊ |
1099 | ␉}␊ |
1100 | ␉patchLocation = symbol->addr - textAddress + textSection; ␊ |
1101 | ␉␊ |
1102 | ␉symbol = lookup_kernel_symbol("_lapic_start");␊ |
1103 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
1104 | ␉{␊ |
1105 | ␉␉printf("Unable to locate %s\n", "_lapic_start");␊ |
1106 | ␉␉return;␊ |
1107 | ␉}␊ |
1108 | ␉lapicStart = symbol->addr; ␊ |
1109 | ␉␊ |
1110 | ␉symbol = lookup_kernel_symbol("_lapic_interrupt_base");␊ |
1111 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
1112 | ␉{␊ |
1113 | ␉␉printf("Unable to locate %s\n", "_lapic_interrupt_base");␊ |
1114 | ␉␉return;␊ |
1115 | ␉}␊ |
1116 | ␉lapicInterruptBase = symbol->addr;␊ |
1117 | ␉patchLocation -= (UInt32)kernelData;␊ |
1118 | ␉lapicStart -= (UInt32)kernelData;␊ |
1119 | ␉lapicInterruptBase -= (UInt32)kernelData;␊ |
1120 | ␉␊ |
1121 | ␉// Looking for the following:␊ |
1122 | ␉//movl _lapic_start,%e_x␊ |
1123 | ␉//addl $0x00000320,%e_x␊ |
1124 | ␉// 8b 15 __ __ __ __ 81 c2 20 03 00 00␊ |
1125 | ␉while( ␊ |
1126 | ␉␉ (bytes[patchLocation - 2] != 0x8b) ||␊ |
1127 | ␉␉ //bytes[patchLocation -1] != 0x15) ||␉// Register, we don't care what it is␊ |
1128 | ␉␉ ( lapicStart != (UInt32)(␊ |
1129 | ␉␉␉␉␉␉␉␉␉(bytes[patchLocation + 0] << 0 | ␊ |
1130 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 1] << 8 | ␊ |
1131 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 2] << 16 |␊ |
1132 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 3] << 24␊ |
1133 | ␉␉␉␉␉␉␉␉␉ )␊ |
1134 | ␉␉␉␉␉␉␉␉␉)␊ |
1135 | ␉␉ ) || ␊ |
1136 | ␉␉ (bytes[patchLocation + 4 ] != 0x81) ||␊ |
1137 | ␉␉ //(bytes[patchLocation + 5 ] != 0Cx2) ||␉// register␊ |
1138 | ␉␉ (bytes[patchLocation + 6 ] != 0x20) ||␊ |
1139 | ␉␉ (bytes[patchLocation + 7 ] != 0x03) ||␊ |
1140 | ␉␉ (bytes[patchLocation + 8 ] != 0x00) ||␊ |
1141 | ␉␉ (bytes[patchLocation + 9] != 0x00)␊ |
1142 | ␉␉ ␊ |
1143 | ␉␉ )␊ |
1144 | ␉{␊ |
1145 | ␉␉patchLocation++;␊ |
1146 | ␉}␊ |
1147 | ␉patchLocation-=2;␊ |
1148 | ␉␊ |
1149 | ␉// NOTE: this is currently hardcoded, change it to be more resilient to changes␊ |
1150 | ␉// At a minimum, I should have this do a cheksup first and if not matching, remove the panic instead.␊ |
1151 | ␉␊ |
1152 | ␉// 8b 15 __ __ __ __ -> movl␉␉ _lapic_start,%edx (NOTE: this should already be here)␊ |
1153 | ␉/*␊ |
1154 | ␉ bytes[patchLocation++] = 0x8B;␊ |
1155 | ␉ bytes[patchLocation++] = 0x15;␊ |
1156 | ␉ bytes[patchLocation++] = (lapicStart & 0x000000FF) >> 0;␊ |
1157 | ␉ bytes[patchLocation++] = (lapicStart & 0x0000FF00) >> 8;␊ |
1158 | ␉ bytes[patchLocation++] = (lapicStart & 0x00FF0000) >> 16;␊ |
1159 | ␉ bytes[patchLocation++] = (lapicStart & 0xFF000000) >> 24;␊ |
1160 | ␉ */␊ |
1161 | ␉patchLocation += 6;␊ |
1162 | ␉␊ |
1163 | ␉// 81 c2 60 03 00 00 -> addl␉␉ $0x00000320,%edx␊ |
1164 | ␉/*␊ |
1165 | ␉ bytes[patchLocation++] = 0x81;␊ |
1166 | ␉ bytes[patchLocation++] = 0xC2;␊ |
1167 | ␉ */␊ |
1168 | ␉patchLocation += 2;␊ |
1169 | ␉bytes[patchLocation++] = 0x60;␊ |
1170 | ␉/*␊ |
1171 | ␉ bytes[patchLocation++];// = 0x03;␊ |
1172 | ␉ bytes[patchLocation++];// = 0x00;␊ |
1173 | ␉ bytes[patchLocation++];// = 0x00;␊ |
1174 | ␉ */␊ |
1175 | ␉patchLocation += 3;␊ |
1176 | ␉␊ |
1177 | ␉// c7 02 00 04 00 00 -> movl␉␉ $0x00000400,(%edx)␊ |
1178 | ␉bytes[patchLocation++] = 0xC7;␊ |
1179 | ␉bytes[patchLocation++] = 0x02;␊ |
1180 | ␉bytes[patchLocation++] = 0x00;␊ |
1181 | ␉bytes[patchLocation++] = 0x04;␊ |
1182 | ␉bytes[patchLocation++] = 0x00;␊ |
1183 | ␉bytes[patchLocation++] = 0x00;␊ |
1184 | ␉␊ |
1185 | ␉// 83 ea 40 -> subl␉␉ $0x40,edx␊ |
1186 | ␉bytes[patchLocation++] = 0x83;␊ |
1187 | ␉bytes[patchLocation++] = 0xEA;␊ |
1188 | ␉bytes[patchLocation++] = 0x40;␊ |
1189 | ␉␊ |
1190 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
1191 | ␉bytes[patchLocation++] = 0xA1;␊ |
1192 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
1193 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
1194 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
1195 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
1196 | ␉␊ |
1197 | ␉// 83 c0 0e -> addl␉␉ $0x0e,%eax␊ |
1198 | ␉bytes[patchLocation++] = 0x83;␊ |
1199 | ␉bytes[patchLocation++] = 0xC0;␊ |
1200 | ␉bytes[patchLocation++] = 0x0E;␊ |
1201 | ␉␊ |
1202 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
1203 | ␉bytes[patchLocation++] = 0x89;␊ |
1204 | ␉bytes[patchLocation++] = 0x02;␊ |
1205 | ␉␊ |
1206 | ␉// 81c230030000␉␉ addl␉␉ $0x00000330,%edx␊ |
1207 | ␉bytes[patchLocation++] = 0x81;␊ |
1208 | ␉bytes[patchLocation++] = 0xC2;␊ |
1209 | ␉bytes[patchLocation++] = 0x30;␊ |
1210 | ␉bytes[patchLocation++] = 0x03;␊ |
1211 | ␉bytes[patchLocation++] = 0x00;␊ |
1212 | ␉bytes[patchLocation++] = 0x00;␊ |
1213 | ␉␊ |
1214 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
1215 | ␉bytes[patchLocation++] = 0xA1;␊ |
1216 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
1217 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
1218 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
1219 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
1220 | ␉␊ |
1221 | ␉// 83 c0 0f -> addl␉␉ $0x0f,%eax␊ |
1222 | ␉bytes[patchLocation++] = 0x83;␊ |
1223 | ␉bytes[patchLocation++] = 0xC0;␊ |
1224 | ␉bytes[patchLocation++] = 0x0F;␊ |
1225 | ␉␊ |
1226 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
1227 | ␉bytes[patchLocation++] = 0x89;␊ |
1228 | ␉bytes[patchLocation++] = 0x02;␊ |
1229 | ␉␊ |
1230 | ␉// 83 ea 10 -> subl␉␉ $0x10,edx␊ |
1231 | ␉bytes[patchLocation++] = 0x83;␊ |
1232 | ␉bytes[patchLocation++] = 0xEA;␊ |
1233 | ␉bytes[patchLocation++] = 0x10;␊ |
1234 | ␉␊ |
1235 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
1236 | ␉bytes[patchLocation++] = 0xA1;␊ |
1237 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
1238 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
1239 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
1240 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
1241 | ␉␊ |
1242 | ␉// 83 c0 0c -> addl␉␉ $0x0c,%eax␊ |
1243 | ␉bytes[patchLocation++] = 0x83;␊ |
1244 | ␉bytes[patchLocation++] = 0xC0;␊ |
1245 | ␉bytes[patchLocation++] = 0x0C;␊ |
1246 | ␉␊ |
1247 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
1248 | ␉bytes[patchLocation++] = 0x89;␊ |
1249 | ␉bytes[patchLocation++] = 0x02;␊ |
1250 | ␉␊ |
1251 | ␉// Replace remaining with nops␊ |
1252 | ␉␊ |
1253 | ␉bytes[patchLocation++] = 0x90;␊ |
1254 | ␉bytes[patchLocation++] = 0x90;␊ |
1255 | ␉bytes[patchLocation++] = 0x90;␊ |
1256 | ␉bytes[patchLocation++] = 0x90;␊ |
1257 | ␉//␉bytes[patchLocation++] = 0x90; // double check the lenght of the patch...␊ |
1258 | ␉//␉bytes[patchLocation++] = 0x90;␊ |
1259 | }␊ |
1260 | |