Root/
Source at commit 439 created 13 years 7 months ago. By meklort, Kernel patcher update, closer to working again, not done yet. | |
---|---|
1 | ␉/*␊ |
2 | * Copyright (c) 2009 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 | extern PlatformInfo_t Platform;␊ |
11 | ␊ |
12 | patchRoutine_t* patches = NULL;␊ |
13 | kernSymbols_t* kernelSymbols = NULL;␊ |
14 | ␊ |
15 | ␊ |
16 | UInt32 textSection = 0;␊ |
17 | UInt32 textAddress = 0;␊ |
18 | ␊ |
19 | ␊ |
20 | void KernelPatcher_start()␊ |
21 | {␊ |
22 | ␉register_kernel_patch(patch_cpuid_set_info, KERNEL_32, CPUID_MODEL_ATOM);␉␉// TODO: CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN␊ |
23 | ␉register_kernel_patch(patch_cpuid_set_info, KERNEL_32, CPUID_MODEL_UNKNOWN);␉// 0, 0 ␊ |
24 | ␉␊ |
25 | ␉register_kernel_patch(patch_commpage_stuff_routine, KERNEL_32, CPUID_MODEL_ANY);␊ |
26 | ␉␊ |
27 | ␉register_kernel_patch(patch_lapic_init, KERNEL_32, CPUID_MODEL_ANY);␊ |
28 | ␉␊ |
29 | ␉register_kernel_symbol(KERNEL_32, "_panic");␊ |
30 | ␉register_kernel_symbol(KERNEL_32, "_cpuid_set_info");␊ |
31 | ␉register_kernel_symbol(KERNEL_32, "_pmCPUExitHaltToOff");␊ |
32 | ␉register_kernel_symbol(KERNEL_32, "_lapic_init");␊ |
33 | ␉register_kernel_symbol(KERNEL_32, "_commpage_stuff_routine");␊ |
34 | ␉␉␊ |
35 | ␉␊ |
36 | ␉// TODO: register needed symbols␊ |
37 | ␉␊ |
38 | ␉␊ |
39 | ␉register_hook_callback("ExecKernel", &patch_kernel); ␊ |
40 | }␊ |
41 | ␊ |
42 | /*␊ |
43 | * Register a kerenl patch␊ |
44 | */␊ |
45 | void register_kernel_patch(void* patch, int arch, int cpus)␊ |
46 | {␊ |
47 | ␉// TODO: only insert valid patches based on current cpuid and architecture␊ |
48 | ␉// AKA, don't at 64bit patches if it's a 32bit only machine␊ |
49 | ␉patchRoutine_t* entry;␊ |
50 | ␉␊ |
51 | ␉// TODO: verify Platform.CPU.Model is populated this early in bootup␊ |
52 | ␉// Check to ensure that the patch is valid on this machine␊ |
53 | ␉// If it is not, exit early form this function␊ |
54 | ␉if(cpus != Platform.CPU.Model)␊ |
55 | ␉{␊ |
56 | ␉␉if(cpus != CPUID_MODEL_ANY)␊ |
57 | ␉␉{␊ |
58 | ␉␉␉if(cpus == CPUID_MODEL_UNKNOWN)␊ |
59 | ␉␉␉{␊ |
60 | ␉␉␉␉switch(Platform.CPU.Model)␊ |
61 | ␉␉␉␉{␊ |
62 | ␉␉␉␉␉case 13:␊ |
63 | ␉␉␉␉␉case CPUID_MODEL_YONAH:␊ |
64 | ␉␉␉␉␉case CPUID_MODEL_MEROM:␊ |
65 | ␉␉␉␉␉case CPUID_MODEL_PENRYN:␊ |
66 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM:␊ |
67 | ␉␉␉␉␉case CPUID_MODEL_FIELDS:␊ |
68 | ␉␉␉␉␉case CPUID_MODEL_DALES:␊ |
69 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␊ |
70 | ␉␉␉␉␉␉// Known cpu's we don't want to add the patch␊ |
71 | ␉␉␉␉␉␉return;␊ |
72 | ␉␉␉␉␉␉break;␊ |
73 | ␊ |
74 | ␉␉␉␉␉default:␊ |
75 | ␉␉␉␉␉␉// CPU not in supported list, so we are going to add␊ |
76 | ␉␉␉␉␉␉// The patch will be applied␊ |
77 | ␉␉␉␉␉␉break;␊ |
78 | ␉␉␉␉␉␉␊ |
79 | ␉␉␉␉}␊ |
80 | ␉␉␉}␊ |
81 | ␉␉␉else␊ |
82 | ␉␉␉{␊ |
83 | ␉␉␉␉// Invalid cpuid for current cpu. Ignoring patch␊ |
84 | ␉␉␉␉return;␊ |
85 | ␉␉␉}␊ |
86 | ␊ |
87 | ␉␉}␊ |
88 | ␉}␊ |
89 | ␉␉␊ |
90 | ␉if(patches == NULL)␊ |
91 | ␉{␊ |
92 | ␉␉patches = entry = malloc(sizeof(patchRoutine_t));␊ |
93 | ␉}␊ |
94 | ␉else␊ |
95 | ␉{␊ |
96 | ␉␉entry = patches;␊ |
97 | ␉␉while(entry->next)␊ |
98 | ␉␉{␊ |
99 | ␉␉␉entry = entry->next;␊ |
100 | ␉␉}␊ |
101 | ␉␉␊ |
102 | ␉␉entry->next = malloc(sizeof(patchRoutine_t));␊ |
103 | ␉␉entry = entry->next;␊ |
104 | ␉}␊ |
105 | ␉␊ |
106 | ␉entry->next = NULL;␊ |
107 | ␉entry->patchRoutine = patch;␊ |
108 | ␉entry->validArchs = arch;␊ |
109 | ␉entry->validCpu = cpus;␊ |
110 | }␊ |
111 | ␊ |
112 | void register_kernel_symbol(int kernelType, const char* name)␊ |
113 | {␊ |
114 | ␉if(kernelSymbols == NULL)␊ |
115 | ␉{␊ |
116 | ␉␉kernelSymbols = malloc(sizeof(kernSymbols_t));␊ |
117 | ␉␉kernelSymbols->next = NULL;␊ |
118 | ␉␉kernelSymbols->symbol = (char*)name;␊ |
119 | ␉␉kernelSymbols->addr = 0;␊ |
120 | ␉}␊ |
121 | ␉else {␊ |
122 | ␉␉kernSymbols_t *symbol = kernelSymbols;␊ |
123 | ␉␉while(symbol->next != NULL)␊ |
124 | ␉␉{␊ |
125 | ␉␉␉symbol = symbol->next;␊ |
126 | ␉␉}␊ |
127 | ␉␉␊ |
128 | ␉␉symbol->next = malloc(sizeof(kernSymbols_t));␊ |
129 | ␉␉symbol = symbol->next;␊ |
130 | ␊ |
131 | ␉␉symbol->next = NULL;␊ |
132 | ␉␉symbol->symbol = (char*)name;␊ |
133 | ␉␉symbol->addr = 0;␊ |
134 | ␉}␊ |
135 | }␊ |
136 | ␊ |
137 | kernSymbols_t* lookup_kernel_symbol(const char* name)␊ |
138 | {␊ |
139 | ␉if(kernelSymbols == NULL)␊ |
140 | ␉{␊ |
141 | ␉␉return NULL;␊ |
142 | ␉}␊ |
143 | ␉kernSymbols_t *symbol = kernelSymbols;␊ |
144 | ␊ |
145 | ␊ |
146 | ␉while(symbol && strcmp(symbol->symbol, name) !=0)␊ |
147 | ␉{␊ |
148 | ␉␉symbol = symbol->next;␊ |
149 | ␉}␊ |
150 | ␉␊ |
151 | ␉if(!symbol)␊ |
152 | ␉{␊ |
153 | ␉␉return NULL;␊ |
154 | ␉}␊ |
155 | ␉else␊ |
156 | ␉{␊ |
157 | ␉␉return symbol;␊ |
158 | ␉}␊ |
159 | ␊ |
160 | }␊ |
161 | ␊ |
162 | void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4)␊ |
163 | {␊ |
164 | ␉patchRoutine_t* entry = patches;␊ |
165 | ␉␊ |
166 | ␉printf("Patching kernel located at 0x%X\n", kernelData);␊ |
167 | ␉locate_symbols(kernelData);␊ |
168 | ␉printf("Symbols located\n", kernelData);␊ |
169 | ␉getc();␊ |
170 | ␉␊ |
171 | ␉int arch = determineKernelArchitecture(kernelData);␊ |
172 | ␉␊ |
173 | ␉// TODO:locate all symbols␊ |
174 | ␉␊ |
175 | ␉␊ |
176 | ␉if(patches != NULL)␊ |
177 | ␉{␊ |
178 | ␉␉while(entry->next)␊ |
179 | ␉␉{␊ |
180 | ␉␉␉if(entry->validArchs == KERNEL_ANY || arch == entry->validArchs)␊ |
181 | ␉␉␉{␊ |
182 | ␉␉␉␉entry->patchRoutine(kernelData);␊ |
183 | ␉␉␉}␊ |
184 | ␉␉␉entry = entry->next;␊ |
185 | ␉␉}␊ |
186 | ␉␉␊ |
187 | ␉}␊ |
188 | }␊ |
189 | ␊ |
190 | int determineKernelArchitecture(void* kernelData)␊ |
191 | {␉␊ |
192 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC)␊ |
193 | ␉{␊ |
194 | ␉␉return KERNEL_32;␊ |
195 | ␉}␊ |
196 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC_64)␊ |
197 | ␉{␊ |
198 | ␉␉return KERNEL_64;␊ |
199 | ␉}␊ |
200 | ␉else␊ |
201 | ␉{␊ |
202 | ␉␉return KERNEL_ERR;␊ |
203 | ␉}␊ |
204 | }␊ |
205 | ␊ |
206 | ␊ |
207 | /**␊ |
208 | **␉␉This functions located the requested symbols in the mach-o file.␊ |
209 | **␉␉␉as well as determines the start of the __TEXT segment and __TEXT,__text sections␊ |
210 | **/␊ |
211 | int locate_symbols(void* kernelData)␊ |
212 | {␊ |
213 | ␊ |
214 | ␉struct load_command *loadCommand;␊ |
215 | ␉struct symtab_command *symtableData;␊ |
216 | ␉//␉struct nlist *symbolEntry;␊ |
217 | ␉␊ |
218 | ␉char* symbolString;␊ |
219 | ␊ |
220 | ␉UInt32 kernelIndex = 0;␊ |
221 | ␉kernelIndex += sizeof(struct mach_header);␊ |
222 | ␉␊ |
223 | ␉if(((struct mach_header*)kernelData)->magic != MH_MAGIC) return KERNEL_64;␊ |
224 | ␉␊ |
225 | ␉␊ |
226 | ␉int cmd = 0;␊ |
227 | ␉while(cmd < ((struct mach_header*)kernelData)->ncmds)␉// TODO: for loop instead␊ |
228 | ␉{␊ |
229 | ␉␉cmd++;␊ |
230 | ␉␉␊ |
231 | ␉␉loadCommand = kernelData + kernelIndex;␊ |
232 | ␉␉␊ |
233 | ␉␉UInt cmdSize = loadCommand->cmdsize;␊ |
234 | ␉␉␊ |
235 | ␉␉␊ |
236 | ␉␉if((loadCommand->cmd & 0x7FFFFFFF) == LC_SYMTAB)␉␉// We only care about the symtab segment␊ |
237 | ␉␉{␊ |
238 | ␉␉␉//printf("Located symtable, length is 0x%X, 0x%X\n", (unsigned int)loadCommand->cmdsize, (unsigned int)sizeof(symtableData));␊ |
239 | ␉␉␉␊ |
240 | ␉␉␉symtableData = kernelData + kernelIndex;␊ |
241 | ␉␉␉kernelIndex += sizeof(struct symtab_command);␊ |
242 | ␉␉␊ |
243 | ␉␉␉symbolString = kernelData + symtableData->stroff;␊ |
244 | ␉␉}␊ |
245 | ␉␉else if((loadCommand->cmd & 0x7FFFFFFF) == LC_SEGMENT)␉␉// We only care about the __TEXT segment, any other load command can be ignored␊ |
246 | ␉␉{␊ |
247 | ␉␉␉␊ |
248 | ␉␉␉struct segment_command *segCommand;␊ |
249 | ␉␉␉␊ |
250 | ␉␉␉segCommand = kernelData + kernelIndex;␊ |
251 | ␉␉␉␊ |
252 | ␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
253 | ␉␉␉␊ |
254 | ␉␉␉if(strcmp("__TEXT", segCommand->segname) == 0)␊ |
255 | ␉␉␉{␊ |
256 | ␉␉␉␉UInt32 sectionIndex;␊ |
257 | ␉␉␉␉␊ |
258 | ␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
259 | ␉␉␉␉␊ |
260 | ␉␉␉␉struct section *sect;␊ |
261 | ␉␉␉␉␊ |
262 | ␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
263 | ␉␉␉␉{␊ |
264 | ␉␉␉␉␉sect = kernelData + kernelIndex + sectionIndex;␊ |
265 | ␉␉␉␉␉␊ |
266 | ␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
267 | ␉␉␉␉␉␊ |
268 | ␉␉␉␉␉␊ |
269 | ␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
270 | ␉␉␉␉␉{␊ |
271 | ␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
272 | ␉␉␉␉␉␉textSection = sect->offset;␊ |
273 | ␉␉␉␉␉␉textAddress = sect->addr;␊ |
274 | ␉␉␉␉␉␉break;␊ |
275 | ␉␉␉␉␉}␉␉␉␉␉␊ |
276 | ␉␉␉␉}␊ |
277 | ␉␉␉}␊ |
278 | ␉␉␉␊ |
279 | ␉␉␉␊ |
280 | ␉␉␉kernelIndex += cmdSize;␊ |
281 | ␉␉} else {␊ |
282 | ␉␉␉kernelIndex += cmdSize;␊ |
283 | ␉␉}␊ |
284 | ␉}␊ |
285 | ␉␊ |
286 | ␉printf("Parseing symtabl.\n");␊ |
287 | ␉handle_symtable((UInt32)kernelData, symtableData, &symbol_handler);␊ |
288 | ␉getc();␊ |
289 | }␊ |
290 | ␊ |
291 | void* symbol_handler(char* symbolName, void* addr)␊ |
292 | {␊ |
293 | ␉// Locate the symbol in the list, if it exists, update it's address␊ |
294 | ␉kernSymbols_t *symbol = lookup_kernel_symbol(symbolName);␊ |
295 | ␉␊ |
296 | ␉␊ |
297 | ␉if(symbol)␊ |
298 | ␉{␊ |
299 | ␉␉printf("Located registered symbol %s at 0x%X\n", symbolName, addr);␊ |
300 | ␉␉getc();␊ |
301 | ␉␉symbol->addr = (UInt32)addr;␊ |
302 | ␉}␊ |
303 | ␉return (void*)0xFFFFFFFF;␊ |
304 | }␊ |
305 | ␊ |
306 | ␊ |
307 | /**␊ |
308 | ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it␊ |
309 | ** Or replace it so that the cpuid is set to a valid value.␊ |
310 | **/␊ |
311 | void patch_cpuid_set_info(void* kernelData/*, UInt32 impersonateFamily, UInt8 impersonateModel*/)␊ |
312 | {␊ |
313 | ␉printf("patch_cpuid_set_info\n");␊ |
314 | ␉getc();␊ |
315 | ␉UInt32 impersonateFamily = 0;␊ |
316 | ␉UInt8 impersonateModel = 0;␊ |
317 | ␉␊ |
318 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
319 | ␉␊ |
320 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");␊ |
321 | ␉UInt32 patchLocation = symbol ? symbol->addr : 0; //␉(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
322 | ␉␊ |
323 | ␉UInt32 jumpLocation = 0;␊ |
324 | ␉␊ |
325 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
326 | ␉UInt32 panicAddr = symbol ? symbol->addr : 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
327 | ␉if(patchLocation == 0)␊ |
328 | ␉{␊ |
329 | ␉␉printf("Unable to locate _cpuid_set_info\n");␊ |
330 | ␉␉return;␊ |
331 | ␉␉␊ |
332 | ␉}␊ |
333 | ␉if(panicAddr == 0)␊ |
334 | ␉{␊ |
335 | ␉␉printf("Unable to locate _panic\n");␊ |
336 | ␉␉return;␊ |
337 | ␉}␊ |
338 | ␉␊ |
339 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
340 | ␉while( ␊ |
341 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
342 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
343 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
344 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
345 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
346 | ␉␉ )␊ |
347 | ␉{␊ |
348 | ␉␉patchLocation++;␊ |
349 | ␉}␊ |
350 | ␉patchLocation--;␊ |
351 | ␉␊ |
352 | ␉␊ |
353 | ␉// Remove panic call, just in case the following patch routines fail␊ |
354 | ␉bytes[patchLocation + 0] = 0x90;␊ |
355 | ␉bytes[patchLocation + 1] = 0x90;␊ |
356 | ␉bytes[patchLocation + 2] = 0x90;␊ |
357 | ␉bytes[patchLocation + 3] = 0x90;␊ |
358 | ␉bytes[patchLocation + 4] = 0x90;␊ |
359 | ␉␊ |
360 | ␉␊ |
361 | ␉// Locate the jump call, so that 10 bytes can be reclamed.␊ |
362 | ␉// NOTE: This will *NOT* be located on pre 10.6.2 kernels␊ |
363 | ␉jumpLocation = patchLocation - 15;␊ |
364 | ␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
365 | ␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&␊ |
366 | ␉␉ (patchLocation - jumpLocation) < 0xF0)␊ |
367 | ␉{␊ |
368 | ␉␉jumpLocation--;␊ |
369 | ␉}␊ |
370 | ␉␊ |
371 | ␉// If found... AND we want to impersonate a specific cpumodel / family...␊ |
372 | ␉if(impersonateFamily &&␊ |
373 | ␉ impersonateModel &&␊ |
374 | ␉ ((patchLocation - jumpLocation) < 0xF0))␊ |
375 | ␉{␊ |
376 | ␉␉␊ |
377 | ␉␉bytes[jumpLocation] -= 10;␉␉// sizeof(movl␉$0x6b5a4cd2,0x00872eb4) = 10bytes␊ |
378 | ␉␉␊ |
379 | ␉␉/* ␊ |
380 | ␉␉ * Inpersonate the specified CPU FAMILY and CPU Model␊ |
381 | ␉␉ */␊ |
382 | ␊ |
383 | ␉␉// bytes[patchLocation - 17] = 0xC7;␉// already here... not needed to be done␊ |
384 | ␉␉// bytes[patchLocation - 16] = 0x05;␉// see above␊ |
385 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 15] << 0 |␊ |
386 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 14] << 8 |␊ |
387 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 13] << 16 |␊ |
388 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 12] << 24;␊ |
389 | ␉␉␊ |
390 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
391 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299; ␊ |
392 | ␉␉␊ |
393 | ␉␉␊ |
394 | ␉␉// cpufamily = CPUFAMILY_INTEL_PENRYN␊ |
395 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;␊ |
396 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
397 | ␉␉bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
398 | ␉␉bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;␊ |
399 | ␉␉␊ |
400 | ␉␉// NOPS, just in case if the jmp call wasn't patched, we'll jump to a␊ |
401 | ␉␉// nop and continue with the rest of the patch␊ |
402 | ␉␉// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few␊ |
403 | ␉␉// from the above code (only cpuid_model needs to be set.␊ |
404 | ␉␉bytes[patchLocation - 7] = 0x90;␊ |
405 | ␉␉bytes[patchLocation - 6] = 0x90;␊ |
406 | ␉␉␊ |
407 | ␉␉bytes[patchLocation - 5] = 0xC7;␊ |
408 | ␉␉bytes[patchLocation - 4] = 0x05;␊ |
409 | ␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
410 | ␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
411 | ␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
412 | ␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
413 | ␉␉␊ |
414 | ␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
415 | ␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
416 | ␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
417 | ␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
418 | ␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
419 | ␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
420 | ␉␉␊ |
421 | ␉}␊ |
422 | ␉else if(impersonateFamily && impersonateModel)␊ |
423 | ␉{␊ |
424 | ␉␉// pre 10.6.2 kernel␊ |
425 | ␉␉// Locate the jump to directly *after* the panic call,␊ |
426 | ␉␉jumpLocation = patchLocation - 4;␊ |
427 | ␉␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
428 | ␉␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&␊ |
429 | ␉␉␉ (patchLocation - jumpLocation) < 0x20)␊ |
430 | ␉␉{␊ |
431 | ␉␉␉jumpLocation--;␊ |
432 | ␉␉}␊ |
433 | ␉␉// NOTE above isn't needed (I was going to use it, but I'm not, so instead,␊ |
434 | ␉␉// I'll just leave it to verify the binary stucture.␊ |
435 | ␉␉␊ |
436 | ␉␉// NOTE: the cpumodel_familt data is not set in _cpuid_set_info␊ |
437 | ␉␉// so we don't need to set it here, I'll get set later based on the model␊ |
438 | ␉␉// we set now.␊ |
439 | ␉␉␊ |
440 | ␉␉if((patchLocation - jumpLocation) < 0x20)␊ |
441 | ␉␉{␊ |
442 | ␉␉␉UInt32 cpuid_model_addr =␉(bytes[patchLocation - 14] << 0 |␊ |
443 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 13] << 8 |␊ |
444 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 12] << 16 |␊ |
445 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 11] << 24);␊ |
446 | ␉␉␉// Remove jump␊ |
447 | ␉␉␉bytes[patchLocation - 9] = 0x90;␉␉/// Was a jump if supported cpu␊ |
448 | ␉␉␉bytes[patchLocation - 8] = 0x90;␉␉// jumped past the panic call, we want to override the panic␊ |
449 | ␊ |
450 | ␉␉␉bytes[patchLocation - 7] = 0x90;␊ |
451 | ␉␉␉bytes[patchLocation - 6] = 0x90;␊ |
452 | ␉␉␉␊ |
453 | ␉␉␉bytes[patchLocation - 5] = 0xC7;␊ |
454 | ␉␉␉bytes[patchLocation - 4] = 0x05;␊ |
455 | ␉␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
456 | ␉␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
457 | ␉␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
458 | ␉␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
459 | ␉␉␉␊ |
460 | ␉␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
461 | ␉␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
462 | ␉␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
463 | ␉␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
464 | ␉␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
465 | ␉␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
466 | ␉␉␉␊ |
467 | ␉␉␉␊ |
468 | ␉␉␉␊ |
469 | ␉␉␉patchLocation = jumpLocation;␊ |
470 | ␉␉␉// We now have 14 bytes available for a patch␊ |
471 | ␉␉␉␊ |
472 | ␉␉}␊ |
473 | ␉␉else ␊ |
474 | ␉␉{␊ |
475 | ␉␉␉// Patching failed, using NOP replacement done initialy␊ |
476 | ␉␉}␊ |
477 | ␉}␊ |
478 | ␉else ␊ |
479 | ␉{␊ |
480 | ␉␉// Either We were unable to change the jump call due to the function's sctructure␊ |
481 | ␉␉// changing, or the user did not request a patch. As such, resort to just ␊ |
482 | ␉␉// removing the panic call (using NOP replacement above). Note that the␊ |
483 | ␉␉// IntelCPUPM kext may still panic due to the cpu's Model ID not being patched␊ |
484 | ␉}␊ |
485 | }␊ |
486 | ␊ |
487 | ␊ |
488 | /**␊ |
489 | ** SleepEnabler.kext replacement (for those that need it)␊ |
490 | ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS␊ |
491 | **/␊ |
492 | void patch_pmCPUExitHaltToOff(void* kernelData)␊ |
493 | {␊ |
494 | ␉printf("patch_pmCPUExitHaltToOff\n");␊ |
495 | ␉getc();␊ |
496 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
497 | ␊ |
498 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_PmCpuExitHaltToOff");␊ |
499 | ␉UInt32 patchLocation = symbol ? symbol->addr : 0; //(kernelSymbolAddresses[SYMBOL_PMCPUEXITHALTTOOFF] - textAddress + textSection);␊ |
500 | ␊ |
501 | ␉if(patchLocation == 0)␊ |
502 | ␉{␊ |
503 | ␉␉printf("Unable to locate _pmCPUExitHaltToOff\n");␊ |
504 | ␉␉return;␊ |
505 | ␉}␊ |
506 | ␉␊ |
507 | ␉while(bytes[patchLocation - 1]␉!= 0xB8 ||␊ |
508 | ␉␉ bytes[patchLocation]␉␉!= 0x04 ||␉// KERN_INVALID_ARGUMENT (0x00000004)␊ |
509 | ␉␉ bytes[patchLocation + 1]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
510 | ␉␉ bytes[patchLocation + 2]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
511 | ␉␉ bytes[patchLocation + 3]␉!= 0x00)␉// KERN_INVALID_ARGUMENT␊ |
512 | ␊ |
513 | ␉{␊ |
514 | ␉␉patchLocation++;␊ |
515 | ␉}␊ |
516 | ␉bytes[patchLocation] = 0x00;␉// KERN_SUCCESS;␊ |
517 | }␊ |
518 | ␊ |
519 | void patch_lapic_init(void* kernelData)␊ |
520 | {␊ |
521 | ␉printf("patch_lapic_init\n");␊ |
522 | ␉getc();␊ |
523 | ␊ |
524 | ␉UInt8 panicIndex = 0;␊ |
525 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
526 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_init");␊ |
527 | ␉UInt32 patchLocation = symbol ? symbol->addr : 0; ␊ |
528 | ␉␊ |
529 | ␉// (kernelSymbolAddresses[SYMBOL_LAPIC_INIT] - textAddress + textSection);␊ |
530 | ␉// kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
531 | ␉␊ |
532 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
533 | ␉UInt32 panicAddr = symbol ? symbol->addr : 0; ␊ |
534 | ␊ |
535 | ␉if(patchLocation == 0)␊ |
536 | ␉{␊ |
537 | ␉␉printf("Unable to locate %s\n", "_lapic_init");␊ |
538 | ␉␉return;␊ |
539 | ␉␉␊ |
540 | ␉}␊ |
541 | ␉if(panicAddr == 0)␊ |
542 | ␉{␊ |
543 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
544 | ␉␉return;␊ |
545 | ␉}␊ |
546 | ␉␊ |
547 | ␉␊ |
548 | ␉␊ |
549 | ␉// Locate the (panicIndex + 1) panic call␊ |
550 | ␉while(panicIndex < 3)␉// Find the third panic call␊ |
551 | ␉{␊ |
552 | ␉␉while( ␊ |
553 | ␉␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
554 | ␉␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
555 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
556 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
557 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
558 | ␉␉␉ )␊ |
559 | ␉␉{␊ |
560 | ␉␉␉patchLocation++;␊ |
561 | ␉␉}␊ |
562 | ␉␉patchLocation++;␊ |
563 | ␉␉panicIndex++;␊ |
564 | ␉}␊ |
565 | ␉patchLocation--;␉// Remove extra increment from the < 3 while loop␊ |
566 | ␉␊ |
567 | ␉bytes[--patchLocation] = 0x90;␉␊ |
568 | ␉bytes[++patchLocation] = 0x90;␊ |
569 | ␉bytes[++patchLocation] = 0x90;␊ |
570 | ␉bytes[++patchLocation] = 0x90;␊ |
571 | ␉bytes[++patchLocation] = 0x90;␊ |
572 | ␉␊ |
573 | ␉␊ |
574 | }␊ |
575 | ␊ |
576 | ␊ |
577 | void patch_commpage_stuff_routine(void* kernelData)␊ |
578 | {␊ |
579 | ␉printf("patch_commpage_stuff_routine\n");␊ |
580 | ␉getc();␊ |
581 | ␊ |
582 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
583 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_commpage_stuff_routine");␊ |
584 | ␉UInt32 patchLocation = symbol ? symbol->addr : 0; ␊ |
585 | ␊ |
586 | ␉␊ |
587 | ␉// (kernelSymbolAddresses[SYMBOL_COMMPAGE_STUFF_ROUTINE] - textAddress + textSection);␊ |
588 | ␉// kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
589 | ␉␊ |
590 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
591 | ␉UInt32 panicAddr = symbol ? symbol->addr : 0; ␊ |
592 | ␊ |
593 | ␉//if(kernelSymbolAddresses[SYMBOL_COMMPAGE_STUFF_ROUTINE] == 0)␊ |
594 | ␉{␊ |
595 | ␉␉//␉printf("Unable to locate %s\n", SYMBOL_COMMPAGE_STUFF_ROUTINE_STRING);␊ |
596 | ␉␉return;␊ |
597 | ␉␉␊ |
598 | ␉}␊ |
599 | ␉//if(kernelSymbolAddresses[SYMBOL_PANIC] == 0)␊ |
600 | ␉{␊ |
601 | ␉␉//␉printf("Unable to locate %s\n", SYMBOL_PANIC_STRING);␊ |
602 | ␉␉return;␊ |
603 | ␉}␊ |
604 | ␉␊ |
605 | ␉␊ |
606 | ␉while( ␊ |
607 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
608 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
609 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
610 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
611 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
612 | ␉␉ )␊ |
613 | ␉{␊ |
614 | ␉␉patchLocation++;␊ |
615 | ␉}␊ |
616 | ␉patchLocation--;␊ |
617 | ␉␊ |
618 | ␉␊ |
619 | ␉// Remove panic call, just in case the following patch routines fail␊ |
620 | ␉bytes[patchLocation + 0] = 0x90;␊ |
621 | ␉bytes[patchLocation + 1] = 0x90;␊ |
622 | ␉bytes[patchLocation + 2] = 0x90;␊ |
623 | ␉bytes[patchLocation + 3] = 0x90;␊ |
624 | ␉bytes[patchLocation + 4] = 0x90;␊ |
625 | ␉␊ |
626 | ␉␊ |
627 | }␊ |
628 |