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