1 | /*␊ |
2 | * Copyright (c) 2009-2010 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | //#include "libsaio.h"␊ |
7 | #include "boot.h"␊ |
8 | #include "kernel_patcher.h"␊ |
9 | #include "platform.h"␊ |
10 | #include "modules.h"␊ |
11 | ␊ |
12 | extern PlatformInfo_t Platform;␊ |
13 | ␊ |
14 | patchRoutine_t* patches = NULL;␊ |
15 | kernSymbols_t* kernelSymbols = NULL;␊ |
16 | ␊ |
17 | ␊ |
18 | void KernelPatcher_start()␊ |
19 | {␊ |
20 | ␉register_kernel_patch(patch_cpuid_set_info_all, KERNEL_ANY, CPUID_MODEL_UNKNOWN); ␊ |
21 | ␊ |
22 | ␉register_kernel_patch(patch_commpage_stuff_routine, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
23 | ␉␊ |
24 | ␉register_kernel_patch(patch_lapic_init, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
25 | ␊ |
26 | ␉// NOTE: following is currently 32bit only␊ |
27 | ␉register_kernel_patch(patch_lapic_configure, KERNEL_32, CPUID_MODEL_ANY);␊ |
28 | ␊ |
29 | ␉␊ |
30 | ␉register_kernel_symbol(KERNEL_ANY, "_panic");␊ |
31 | ␉register_kernel_symbol(KERNEL_ANY, "_cpuid_set_info");␊ |
32 | ␉register_kernel_symbol(KERNEL_ANY, "_pmCPUExitHaltToOff");␊ |
33 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_init");␊ |
34 | ␉register_kernel_symbol(KERNEL_ANY, "_commpage_stuff_routine");␊ |
35 | ␊ |
36 | ␉// lapic_configure symbols␊ |
37 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_configure");␊ |
38 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_start");␊ |
39 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt_base");␊ |
40 | ␉␊ |
41 | ␉// lapic_interrup symbols␊ |
42 | ␉//register_kernel_patch(patch_lapic_interrupt, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
43 | ␉//register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt");␊ |
44 | ␊ |
45 | ␊ |
46 | ␉␊ |
47 | ␉// TODO: register needed symbols␊ |
48 | ␉␊ |
49 | ␉␊ |
50 | ␉register_hook_callback("ExecKernel", &patch_kernel); ␊ |
51 | }␊ |
52 | ␊ |
53 | /*␊ |
54 | * Register a kerenl patch␊ |
55 | */␊ |
56 | void register_kernel_patch(void* patch, int arch, int cpus)␊ |
57 | {␊ |
58 | ␉// TODO: only insert valid patches based on current cpuid and architecture␊ |
59 | ␉// AKA, don't at 64bit patches if it's a 32bit only machine␊ |
60 | ␉patchRoutine_t* entry;␊ |
61 | ␉␊ |
62 | ␉// TODO: verify Platform.CPU.Model is populated this early in bootup␊ |
63 | ␉// Check to ensure that the patch is valid on this machine␊ |
64 | ␉// If it is not, exit early form this function␊ |
65 | ␉if(cpus != Platform.CPU.Model)␊ |
66 | ␉{␊ |
67 | ␉␉if(cpus != CPUID_MODEL_ANY)␊ |
68 | ␉␉{␊ |
69 | ␉␉␉if(cpus == CPUID_MODEL_UNKNOWN)␊ |
70 | ␉␉␉{␊ |
71 | ␉␉␉␉switch(Platform.CPU.Model)␊ |
72 | ␉␉␉␉{␊ |
73 | ␉␉␉␉␉case 13:␊ |
74 | ␉␉␉␉␉case CPUID_MODEL_YONAH:␊ |
75 | ␉␉␉␉␉case CPUID_MODEL_MEROM:␊ |
76 | ␉␉␉␉␉case CPUID_MODEL_PENRYN:␊ |
77 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM:␊ |
78 | ␉␉␉␉␉case CPUID_MODEL_FIELDS:␊ |
79 | ␉␉␉␉␉case CPUID_MODEL_DALES:␊ |
80 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␊ |
81 | ␉␉␉␉␉␉// Known cpu's we don't want to add the patch␊ |
82 | ␉␉␉␉␉␉return;␊ |
83 | ␉␉␉␉␉␉break;␊ |
84 | ␊ |
85 | ␉␉␉␉␉default:␊ |
86 | ␉␉␉␉␉␉// CPU not in supported list, so we are going to add␊ |
87 | ␉␉␉␉␉␉// The patch will be applied␊ |
88 | ␉␉␉␉␉␉break;␊ |
89 | ␉␉␉␉␉␉␊ |
90 | ␉␉␉␉}␊ |
91 | ␉␉␉}␊ |
92 | ␉␉␉else␊ |
93 | ␉␉␉{␊ |
94 | ␉␉␉␉// Invalid cpuid for current cpu. Ignoring patch␊ |
95 | ␉␉␉␉return;␊ |
96 | ␉␉␉}␊ |
97 | ␊ |
98 | ␉␉}␊ |
99 | ␉}␊ |
100 | ␉␉␊ |
101 | ␉if(patches == NULL)␊ |
102 | ␉{␊ |
103 | ␉␉patches = entry = malloc(sizeof(patchRoutine_t));␊ |
104 | ␉}␊ |
105 | ␉else␊ |
106 | ␉{␊ |
107 | ␉␉entry = patches;␊ |
108 | ␉␉while(entry->next)␊ |
109 | ␉␉{␊ |
110 | ␉␉␉entry = entry->next;␊ |
111 | ␉␉}␊ |
112 | ␉␉␊ |
113 | ␉␉entry->next = malloc(sizeof(patchRoutine_t));␊ |
114 | ␉␉entry = entry->next;␊ |
115 | ␉}␊ |
116 | ␉␊ |
117 | ␉entry->next = NULL;␊ |
118 | ␉entry->patchRoutine = patch;␊ |
119 | ␉entry->validArchs = arch;␊ |
120 | ␉entry->validCpu = cpus;␊ |
121 | }␊ |
122 | ␊ |
123 | void register_kernel_symbol(int kernelType, const char* name)␊ |
124 | {␊ |
125 | ␉if(kernelSymbols == NULL)␊ |
126 | ␉{␊ |
127 | ␉␉kernelSymbols = malloc(sizeof(kernSymbols_t));␊ |
128 | ␉␉kernelSymbols->next = NULL;␊ |
129 | ␉␉kernelSymbols->symbol = (char*)name;␊ |
130 | ␉␉kernelSymbols->addr = 0;␊ |
131 | ␉}␊ |
132 | ␉else {␊ |
133 | ␉␉kernSymbols_t *symbol = kernelSymbols;␊ |
134 | ␉␉while(symbol->next != NULL)␊ |
135 | ␉␉{␊ |
136 | ␉␉␉symbol = symbol->next;␊ |
137 | ␉␉}␊ |
138 | ␉␉␊ |
139 | ␉␉symbol->next = malloc(sizeof(kernSymbols_t));␊ |
140 | ␉␉symbol = symbol->next;␊ |
141 | ␊ |
142 | ␉␉symbol->next = NULL;␊ |
143 | ␉␉symbol->symbol = (char*)name;␊ |
144 | ␉␉symbol->addr = 0;␊ |
145 | ␉}␊ |
146 | }␊ |
147 | ␊ |
148 | kernSymbols_t* lookup_kernel_symbol(const char* name)␊ |
149 | {␊ |
150 | ␉kernSymbols_t *symbol = kernelSymbols;␊ |
151 | ␊ |
152 | ␉while(symbol && strcmp(symbol->symbol, name) !=0)␊ |
153 | ␉{␊ |
154 | ␉␉symbol = symbol->next;␊ |
155 | ␉}␊ |
156 | ␉␊ |
157 | ␉if(!symbol)␊ |
158 | ␉{␊ |
159 | ␉␉return NULL;␊ |
160 | ␉}␊ |
161 | ␉else␊ |
162 | ␉{␊ |
163 | ␉␉return symbol;␊ |
164 | ␉}␊ |
165 | ␊ |
166 | }␊ |
167 | ␊ |
168 | void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4)␊ |
169 | {␊ |
170 | ␉bool␉␉␉patchKernel = false; //Kpatcher - default value.␊ |
171 | ␉patchRoutine_t* entry = patches;␊ |
172 | ␊ |
173 | ␉int arch = determineKernelArchitecture(kernelData);␊ |
174 | ␊ |
175 | ␉locate_symbols(kernelData);␊ |
176 | ␊ |
177 | ␉// check if kernel patcher is requested by user.␊ |
178 | ␉getBoolForKey(kKPatcherKey, &patchKernel, &bootInfo->bootConfig);␊ |
179 | ␊ |
180 | ␉if (patches != NULL && patchKernel == true)␊ |
181 | ␉{␊ |
182 | ␉␉while(entry)␊ |
183 | ␉␉{␊ |
184 | ␉␉␉if (entry->validArchs == KERNEL_ANY || arch == entry->validArchs)␊ |
185 | ␉␉␉{␊ |
186 | ␉␉␉␉if (entry->patchRoutine) entry->patchRoutine(kernelData);␊ |
187 | ␉␉␉}␊ |
188 | ␉␉␉entry = entry->next;␊ |
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 | ␉char is64 = 1;␊ |
217 | ␉parse_mach(kernelData, NULL, symbol_handler, NULL);␊ |
218 | ␉//handle_symtable((UInt32)kernelData, symtableData, &symbol_handler, determineKernelArchitecture(kernelData) == KERNEL_64);␊ |
219 | ␉return 1 << is64;␊ |
220 | }␊ |
221 | ␊ |
222 | long long symbol_handler(char* symbolName, long long addr, char is64)␊ |
223 | {␊ |
224 | ␉// Locate the symbol in the list, if it exists, update it's address␊ |
225 | ␉kernSymbols_t *symbol = lookup_kernel_symbol(symbolName);␊ |
226 | ␉␊ |
227 | ␉if(symbol)␊ |
228 | ␉{␊ |
229 | ␉␉symbol->addr = addr;␊ |
230 | ␉}␊ |
231 | ␉␊ |
232 | ␉return 0xFFFFFFFF; // fixme␊ |
233 | }␊ |
234 | ␊ |
235 | ␊ |
236 | /**␊ |
237 | ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it␊ |
238 | ** Or replace it so that the cpuid is set to a valid value.␊ |
239 | **/␊ |
240 | void patch_cpuid_set_info_all(void* kernelData)␊ |
241 | {␊ |
242 | ␉switch(Platform.CPU.Model)␊ |
243 | ␉{␊ |
244 | ␉␉case CPUID_MODEL_ATOM:␊ |
245 | ␉␉␉if(determineKernelArchitecture(kernelData) == KERNEL_32)␊ |
246 | ␉␉␉{␊ |
247 | ␉␉␉␉patch_cpuid_set_info_32(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN); ␊ |
248 | ␉␉␉}␊ |
249 | ␉␉␉else ␊ |
250 | ␉␉␉{␊ |
251 | ␉␉␉␉patch_cpuid_set_info_64(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN); ␊ |
252 | ␊ |
253 | ␉␉␉}␊ |
254 | ␊ |
255 | ␉␉␉break;␊ |
256 | ␉␉␉␊ |
257 | ␉␉default:␊ |
258 | ␉␉␉if(determineKernelArchitecture(kernelData) == KERNEL_32)␊ |
259 | ␉␉␉{␊ |
260 | ␉␉␉␉patch_cpuid_set_info_32(kernelData, 0, 0);␊ |
261 | ␉␉␉}␊ |
262 | ␉␉␉else␊ |
263 | ␉␉␉{␊ |
264 | ␉␉␉␉patch_cpuid_set_info_64(kernelData, 0, 0);␊ |
265 | ␉␉␉}␊ |
266 | ␊ |
267 | ␉␉␉break;␊ |
268 | ␉}␊ |
269 | }␊ |
270 | ␊ |
271 | void patch_cpuid_set_info_64(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)␊ |
272 | {␊ |
273 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
274 | ␉␊ |
275 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");␊ |
276 | ␉␊ |
277 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //␉(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
278 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
279 | ␉␊ |
280 | ␉␊ |
281 | ␉␊ |
282 | //␉UInt32 jumpLocation = 0; unused for now␊ |
283 | ␉␊ |
284 | ␉␊ |
285 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
286 | ␉{␊ |
287 | ␉␉verbose("Unable to locate _cpuid_set_info\n");␊ |
288 | ␉␉return;␊ |
289 | ␉␉␊ |
290 | ␉}␊ |
291 | ␉␊ |
292 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
293 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
294 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
295 | ␉{␊ |
296 | ␉␉printf("Unable to locate _panic\n");␊ |
297 | ␉␉return;␊ |
298 | ␉}␊ |
299 | ␉panicAddr -= (UInt32)kernelData;␊ |
300 | ␉␊ |
301 | ␉␊ |
302 | ␉␊ |
303 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
304 | ␉while( ␊ |
305 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
306 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
307 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
308 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
309 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
310 | ␉␉ )␊ |
311 | ␉{␊ |
312 | ␉␉patchLocation++;␊ |
313 | ␉}␊ |
314 | ␉patchLocation--;␊ |
315 | ␉␊ |
316 | ␉verbose("0x%X 0x%X 0x%X 0x%X 0x%X\n", bytes[patchLocation ], bytes[patchLocation +1], bytes[patchLocation +2], bytes[patchLocation +3], bytes[patchLocation +4]);␊ |
317 | ␉␊ |
318 | ␉// Remove panic just in case␊ |
319 | ␉// The panic instruction is exactly 5 bytes long.␊ |
320 | ␉bytes[patchLocation + 0] = 0x90;␊ |
321 | ␉bytes[patchLocation + 1] = 0x90;␊ |
322 | ␉bytes[patchLocation + 2] = 0x90;␊ |
323 | ␉bytes[patchLocation + 3] = 0x90;␊ |
324 | ␉bytes[patchLocation + 4] = 0x90;␊ |
325 | ␉verbose("0x%X 0x%X 0x%X 0x%X 0x%X\n", bytes[patchLocation ], bytes[patchLocation +1], bytes[patchLocation +2], bytes[patchLocation +3], bytes[patchLocation +4]);␊ |
326 | ␉␊ |
327 | ␉// Check for a 10.2.0+ kernel␊ |
328 | ␉if(bytes[patchLocation - 19] == 0xC7 && bytes[patchLocation - 18] == 0x05)␊ |
329 | ␉{␊ |
330 | ␉␉␊ |
331 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 17] << 0 |␊ |
332 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 16] << 8 |␊ |
333 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 15] << 16 |␊ |
334 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 14] << 24;␊ |
335 | ␉␉␊ |
336 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
337 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 310; ␊ |
338 | ␉␉␊ |
339 | ␉␉␊ |
340 | ␉␉//ffffff8000228b3b -> 0x00490e8b␊ |
341 | ␉␉//ffffff8000228c28 -> -237 -> 0x490D9E -> -310␊ |
342 | ␉␉␊ |
343 | ␉␉␊ |
344 | ␉␉// The mov is 10 bytes␊ |
345 | ␉␉/*␊ |
346 | ␉␉ bytes[patchLocation - 19] = 0x90;␉// c7␊ |
347 | ␉␉ bytes[patchLocation - 18] = 0x90;␉// 05␊ |
348 | ␉␉ bytes[patchLocation - 17] = 0x90;␉// family location␊ |
349 | ␉␉ bytes[patchLocation - 16] = 0x90;␉// family location␊ |
350 | ␉␉ bytes[patchLocation - 15] = 0x90;␉// family location␊ |
351 | ␉␉ bytes[patchLocation - 14] = 0x90;␉// family location␊ |
352 | ␉␉ */␊ |
353 | ␉␉bytes[patchLocation - 13] = (impersonateFamily & 0x000000FF) >> 0;␊ |
354 | ␉␉bytes[patchLocation - 12] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
355 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
356 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0xFF000000) >> 24;␊ |
357 | ␉␉␊ |
358 | ␉␉␊ |
359 | ␉␉// The lea (%rip),%rip is 7 bytes␊ |
360 | ␉␉bytes[patchLocation - 9] = 0xC7;␊ |
361 | ␉␉bytes[patchLocation - 8] = 0x05;␊ |
362 | ␉␉bytes[patchLocation - 7] = ((cpuid_model_addr -10) & 0x000000FF) >> 0;␉// NOTE: this opcode is relative in 64bit mode, subtract offset␊ |
363 | ␉␉bytes[patchLocation - 6] = ((cpuid_model_addr -10) & 0x0000FF00) >> 8;␉␊ |
364 | ␉␉bytes[patchLocation - 5] = ((cpuid_model_addr -10) & 0x00FF0000) >> 16;␊ |
365 | ␉␉bytes[patchLocation - 4] = ((cpuid_model_addr -10) & 0xFF000000) >> 24;␊ |
366 | ␉␉bytes[patchLocation - 3] = impersonateModel;␉// cpuid_model␊ |
367 | ␉␉␊ |
368 | ␉␉ ␊ |
369 | ␉␉ ␊ |
370 | ␉␉ // The xor eax eax is 2 bytes␊ |
371 | ␉␉bytes[patchLocation - 2] = 0x01;␉// cpuid_extmodel␊ |
372 | ␉␉bytes[patchLocation - 1] = 0x00;␉// cpuid_extfamily␊ |
373 | ␉␉␊ |
374 | ␉␉// The panic instruction is exactly 5 bytes long.␊ |
375 | ␉␉bytes[patchLocation - 0] = 0x02;␉// cpuid_stepping␊ |
376 | ␉␉/*bytes[patchLocation + 1] = 0x90;␊ |
377 | ␉␉bytes[patchLocation + 2] = 0x90;␊ |
378 | ␉␉bytes[patchLocation + 3] = 0x90;␊ |
379 | ␉␉bytes[patchLocation + 4] = 0x90;␊ |
380 | ␉␉*/␊ |
381 | ␉␉␊ |
382 | ␉␉// Panic call has been removed.␊ |
383 | ␉␉// Override the CPUID now. This requires ~ 10 bytes on 10.0.0 kernels␊ |
384 | ␉␉// On 10.2.0+ kernels, this requires ~16 bytes␊ |
385 | ␉␉␊ |
386 | ␉␉// Total: 24 bytes␊ |
387 | ␉␉printf("Running on a 10.2.0+ kernel\n");␊ |
388 | //␉␉getchar(); //getc(); Azi: getc stuff␊ |
389 | ␊ |
390 | ␉}␊ |
391 | ␉else {␊ |
392 | ␉␉printf("Running on a 10.0.0 kernel, patch unsupported\n");␊ |
393 | ␉␉getchar(); //getc(); Azi: getc stuff␊ |
394 | ␉}␊ |
395 | ␊ |
396 | ␉␊ |
397 | }␊ |
398 | ␊ |
399 | void patch_cpuid_set_info_32(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)␊ |
400 | {␊ |
401 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
402 | ␉␊ |
403 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");␊ |
404 | ␊ |
405 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //␉(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
406 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
407 | ␉UInt32 addrLocation = patchLocation;␊ |
408 | ␉␊ |
409 | ␉␊ |
410 | ␊ |
411 | ␉UInt32 jumpLocation = 0;␊ |
412 | ␉␊ |
413 | ␉␊ |
414 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
415 | ␉{␊ |
416 | ␉␉verbose("Unable to locate _cpuid_set_info\n");␊ |
417 | ␉␉return;␊ |
418 | ␉␉␊ |
419 | ␉}␊ |
420 | ␊ |
421 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
422 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
423 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
424 | ␉{␊ |
425 | ␉␉printf("Unable to locate _panic\n");␊ |
426 | ␉␉return;␊ |
427 | ␉}␊ |
428 | ␉panicAddr -= (UInt32)kernelData;␊ |
429 | ␊ |
430 | ␉␊ |
431 | ␉␊ |
432 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
433 | ␉while( ␊ |
434 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
435 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
436 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
437 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
438 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
439 | ␉␉ )␊ |
440 | ␉{␊ |
441 | ␉␉patchLocation++;␊ |
442 | ␉}␊ |
443 | ␉patchLocation--;␊ |
444 | ␉␊ |
445 | ␉verbose("0x%X 0x%X 0x%X 0x%X 0x%X\n", bytes[patchLocation ], bytes[patchLocation +1], bytes[patchLocation +2], bytes[patchLocation +3], bytes[patchLocation +4]);␊ |
446 | ␊ |
447 | ␉// Remove panic call, just in case the following patch routines fail␊ |
448 | ␉bytes[patchLocation + 0] = 0x90;␊ |
449 | ␉bytes[patchLocation + 1] = 0x90;␊ |
450 | ␉bytes[patchLocation + 2] = 0x90;␊ |
451 | ␉bytes[patchLocation + 3] = 0x90;␊ |
452 | ␉bytes[patchLocation + 4] = 0x90;␊ |
453 | ␉verbose("0x%X 0x%X 0x%X 0x%X 0x%X\n", bytes[patchLocation ], bytes[patchLocation +1], bytes[patchLocation +2], bytes[patchLocation +3], bytes[patchLocation +4]);␊ |
454 | ␉␊ |
455 | ␉␊ |
456 | ␉// Locate the jump call, so that 10 bytes can be reclamed.␊ |
457 | ␉// NOTE: This will *NOT* be located on pre 10.6.2 kernels␊ |
458 | ␉jumpLocation = patchLocation - 15;␊ |
459 | ␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
460 | ␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation - 18)) &&␊ |
461 | ␉␉ (patchLocation - jumpLocation) < 0xF0)␊ |
462 | ␉{␊ |
463 | ␉␉jumpLocation--;␊ |
464 | ␉}␊ |
465 | ␉␊ |
466 | ␉// If found... AND we want to impersonate a specific cpumodel / family...␊ |
467 | ␉if(impersonateFamily && impersonateModel &&␊ |
468 | ␉ ((patchLocation - jumpLocation) < 0xF0))␊ |
469 | ␉{␊ |
470 | ␉␉␊ |
471 | ␉␉bytes[jumpLocation] -= 10;␉␉// sizeof(movl␉$0x6b5a4cd2,0x00872eb4) = 10bytes␊ |
472 | ␉␉␊ |
473 | ␉␉/* ␊ |
474 | ␉␉ * Inpersonate the specified CPU FAMILY and CPU Model␊ |
475 | ␉␉ */␊ |
476 | ␉␉//␉␉␉␉␉␉␉␉␉cpuid_cpufamily_addr, impersonateFamily␉␉␉␉␉␉␉␉␉cpuid_model_addr␉ impersonateModel␊ |
477 | ␉␉//char new_bytes[] = {0xC7, 0x05, 0x__, 0x__, 0x__, 0x__, 0x__, 0x__, 0x__, 0x__, 0x90, 0x90, 0xC7, 0x05, 0x__, 0x__, 0x__, 0x__, 0x__, 0x01, 0x00, 0x02};␊ |
478 | ␉␉// bytes[patchLocation - 17] = 0xC7;␉// already here... not needed to be done␊ |
479 | ␉␉// bytes[patchLocation - 16] = 0x05;␉// see above␊ |
480 | ␉␉//UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 15] << 0 |␊ |
481 | ␉␉//␉␉␉␉␉␉␉␉bytes[patchLocation - 14] << 8 |␊ |
482 | ␉␉//␉␉␉␉␉␉␉␉bytes[patchLocation - 13] << 16 |␊ |
483 | ␉␉//␉␉␉␉␉␉␉␉bytes[patchLocation - 12] << 24;␊ |
484 | ␊ |
485 | ␉␉// NOTE: may change, determined based on cpuid_info struct: TODO: read from binary␊ |
486 | ␉␉//UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 295;␊ |
487 | ␉␉␊ |
488 | ␉␉␊ |
489 | ␉␉// cpufamily␊ |
490 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;␊ |
491 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
492 | ␉␉bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
493 | ␉␉bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;␊ |
494 | ␉␉␊ |
495 | ␉␉// NOPS, just in case if the jmp call wasn't patched, we'll jump to a␊ |
496 | ␉␉// nop and continue with the rest of the patch␊ |
497 | ␉␉// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few␊ |
498 | ␉␉// from the above code (only cpuid_model needs to be set.␊ |
499 | ␉␉bytes[patchLocation - 7] = 0x90;␊ |
500 | ␉␉bytes[patchLocation - 6] = 0x90;␊ |
501 | ␉␉␊ |
502 | ␉␉bytes[patchLocation - 5] = 0xC7;␊ |
503 | ␉␉bytes[patchLocation - 4] = 0x05;␊ |
504 | ␉␉␊ |
505 | ␉␉// Locate cpuid_addr_addr -> first four bytes after 8b 45 d8 25 f0 00 00 00 c1 e8 04 a2␊ |
506 | ␉␉while(bytes[addrLocation -12] != 0x8B ||␊ |
507 | ␉␉␉ bytes[addrLocation -11] != 0x45 ||␊ |
508 | ␉␉␉ bytes[addrLocation -10] != 0xD8 ||␊ |
509 | ␉␉␉ bytes[addrLocation -9] != 0x25 ||␊ |
510 | ␉␉␉ bytes[addrLocation -8] != 0xF0 ||␊ |
511 | ␉␉␉ bytes[addrLocation -7] != 0x00 ||␊ |
512 | ␉␉␉ bytes[addrLocation -6] != 0x00 ||␊ |
513 | ␉␉␉ bytes[addrLocation -5] != 0x00 ||␊ |
514 | ␉␉␉ bytes[addrLocation -4] != 0xC1 ||␊ |
515 | ␉␉␉ bytes[addrLocation -3] != 0xE8 ||␊ |
516 | ␉␉␉ bytes[addrLocation -2] != 0x04 ||␊ |
517 | ␉␉␉ bytes[addrLocation -1] != 0xA2)␊ |
518 | ␉␉{␊ |
519 | ␉␉␉// TODO: break if location is too large␊ |
520 | ␉␉␉addrLocation++;␊ |
521 | ␉␉}␉␉␊ |
522 | ␊ |
523 | ␉␉bytes[patchLocation - 3] = bytes[addrLocation];␊ |
524 | ␉␉bytes[patchLocation - 2] = bytes[addrLocation+1];␉␊ |
525 | ␉␉bytes[patchLocation - 1] = bytes[addrLocation+2];␊ |
526 | ␉␉bytes[patchLocation - 0] = bytes[addrLocation+3];␊ |
527 | ␉␉␊ |
528 | ␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
529 | ␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
530 | ␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
531 | ␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
532 | ␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
533 | ␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
534 | ␉}␊ |
535 | ␉else if(impersonateFamily && impersonateModel)␊ |
536 | ␉{␊ |
537 | ␉␉// pre 10.6.2 kernel␊ |
538 | ␉␉// Locate the jump to directly *after* the panic call,␊ |
539 | ␉␉jumpLocation = patchLocation - 4;␊ |
540 | ␉␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
541 | ␉␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&␊ |
542 | ␉␉␉ (patchLocation - jumpLocation) < 0x20)␊ |
543 | ␉␉{␊ |
544 | ␉␉␉jumpLocation--;␊ |
545 | ␉␉}␊ |
546 | ␉␉// NOTE above isn't needed (I was going to use it, but I'm not, so instead,␊ |
547 | ␉␉// I'll just leave it to verify the binary stucture.␊ |
548 | ␉␉␊ |
549 | ␉␉// NOTE: the cpumodel_familt data is not set in _cpuid_set_info␊ |
550 | ␉␉// so we don't need to set it here, I'll get set later based on the model␊ |
551 | ␉␉// we set now.␊ |
552 | ␉␉␊ |
553 | ␉␉if((patchLocation - jumpLocation) < 0x20)␊ |
554 | ␉␉{␊ |
555 | ␉␉␉UInt32 cpuid_model_addr =␉(bytes[patchLocation - 14] << 0 |␊ |
556 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 13] << 8 |␊ |
557 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 12] << 16 |␊ |
558 | ␉␉␉␉␉␉␉␉␉␉ bytes[patchLocation - 11] << 24);␊ |
559 | ␉␉␉// Remove jump␊ |
560 | ␉␉␉bytes[patchLocation - 9] = 0x90;␉␉/// Was a jump if supported cpu␊ |
561 | ␉␉␉bytes[patchLocation - 8] = 0x90;␉␉// jumped past the panic call, we want to override the panic␊ |
562 | ␉␉␉␊ |
563 | ␉␉␉bytes[patchLocation - 7] = 0x90;␊ |
564 | ␉␉␉bytes[patchLocation - 6] = 0x90;␊ |
565 | ␉␉␉␊ |
566 | ␉␉␉bytes[patchLocation - 5] = 0xC7;␊ |
567 | ␉␉␉bytes[patchLocation - 4] = 0x05;␊ |
568 | ␉␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
569 | ␉␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
570 | ␉␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
571 | ␉␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
572 | ␉␉␉␊ |
573 | ␉␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
574 | ␉␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
575 | ␉␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
576 | ␉␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
577 | ␉␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
578 | ␉␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
579 | ␉␉␉␊ |
580 | ␉␉␉␊ |
581 | ␉␉␉␊ |
582 | ␉␉␉//patchLocation = jumpLocation;␊ |
583 | ␉␉␉// We now have 14 bytes available for a patch␊ |
584 | ␉␉␉␊ |
585 | ␉␉}␊ |
586 | ␉␉else ␊ |
587 | ␉␉{␊ |
588 | ␉␉␉// Patching failed, using NOP replacement done initialy␊ |
589 | ␉␉}␊ |
590 | ␉}␊ |
591 | ␉else ␊ |
592 | ␉{␊ |
593 | ␉␉// Either We were unable to change the jump call due to the function's sctructure␊ |
594 | ␉␉// changing, or the user did not request a patch. As such, resort to just ␊ |
595 | ␉␉// removing the panic call (using NOP replacement above). Note that the␊ |
596 | ␉␉// IntelCPUPM kext may still panic due to the cpu's Model ID not being patched␊ |
597 | ␉}␊ |
598 | }␊ |
599 | ␊ |
600 | ␊ |
601 | /**␊ |
602 | ** SleepEnabler.kext replacement (for those that need it)␊ |
603 | ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS␊ |
604 | **/␊ |
605 | void patch_pmCPUExitHaltToOff(void* kernelData)␊ |
606 | {␊ |
607 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
608 | ␊ |
609 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_PmCpuExitHaltToOff");␊ |
610 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0;␊ |
611 | ␉␊ |
612 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
613 | ␉{␊ |
614 | ␉␉printf("Unable to locate _pmCPUExitHaltToOff\n");␊ |
615 | ␉␉return;␊ |
616 | ␉}␊ |
617 | ␉␊ |
618 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
619 | ␉␊ |
620 | ␉␊ |
621 | ␉␊ |
622 | ␉while(bytes[patchLocation - 1]␉!= 0xB8 ||␊ |
623 | ␉␉ bytes[patchLocation]␉␉!= 0x04 ||␉// KERN_INVALID_ARGUMENT (0x00000004)␊ |
624 | ␉␉ bytes[patchLocation + 1]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
625 | ␉␉ bytes[patchLocation + 2]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
626 | ␉␉ bytes[patchLocation + 3]␉!= 0x00)␉// KERN_INVALID_ARGUMENT␊ |
627 | ␊ |
628 | ␉{␊ |
629 | ␉␉patchLocation++;␊ |
630 | ␉}␊ |
631 | ␉bytes[patchLocation] = 0x00;␉// KERN_SUCCESS;␊ |
632 | }␊ |
633 | ␊ |
634 | void patch_lapic_init(void* kernelData)␊ |
635 | {␊ |
636 | ␊ |
637 | ␉UInt8 panicIndex = 0;␊ |
638 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
639 | ␉␊ |
640 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_init");␊ |
641 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; ␊ |
642 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
643 | ␉{␊ |
644 | ␉␉printf("Unable to locate %s\n", "_lapic_init");␊ |
645 | ␉␉return;␊ |
646 | ␉␉␊ |
647 | ␉}␊ |
648 | ␉␊ |
649 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
650 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; ␊ |
651 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
652 | ␉{␊ |
653 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
654 | ␉␉return;␊ |
655 | ␉}␊ |
656 | ␉␊ |
657 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
658 | ␉panicAddr -= (UInt32)kernelData;␉// Remove offset␊ |
659 | ␊ |
660 | ␉␊ |
661 | ␉␊ |
662 | ␉␊ |
663 | ␉// Locate the (panicIndex + 1) panic call␊ |
664 | ␉while(panicIndex < 3)␉// Find the third panic call␊ |
665 | ␉{␊ |
666 | ␉␉while( ␊ |
667 | ␉␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
668 | ␉␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
669 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
670 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
671 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
672 | ␉␉␉ )␊ |
673 | ␉␉{␊ |
674 | ␉␉␉patchLocation++;␊ |
675 | ␉␉}␊ |
676 | ␉␉patchLocation++;␊ |
677 | ␉␉panicIndex++;␊ |
678 | ␉}␊ |
679 | ␉patchLocation--;␉// Remove extra increment from the < 3 while loop␊ |
680 | ␉␊ |
681 | ␉bytes[--patchLocation] = 0x90;␉␊ |
682 | ␉bytes[++patchLocation] = 0x90;␊ |
683 | ␉bytes[++patchLocation] = 0x90;␊ |
684 | ␉bytes[++patchLocation] = 0x90;␊ |
685 | ␉bytes[++patchLocation] = 0x90;␊ |
686 | ␉␊ |
687 | ␉␊ |
688 | }␊ |
689 | ␊ |
690 | ␊ |
691 | void patch_commpage_stuff_routine(void* kernelData)␊ |
692 | {␊ |
693 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
694 | ␊ |
695 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_commpage_stuff_routine");␊ |
696 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
697 | ␉{␊ |
698 | ␉␉verbose("Unable to locate %s\n", "_commpage_stuff_routine");␊ |
699 | ␉␉return;␊ |
700 | ␉␉␊ |
701 | ␉}␊ |
702 | ␉␊ |
703 | ␉UInt32 patchLocation = symbol->addr - textAddress + textSection; ␊ |
704 | ␊ |
705 | ␉␊ |
706 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
707 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
708 | ␉{␊ |
709 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
710 | ␉␉return;␊ |
711 | ␉}␊ |
712 | ␉UInt32 panicAddr = symbol->addr - textAddress; ␊ |
713 | ␊ |
714 | ␉patchLocation -= (UInt32)kernelData;␊ |
715 | ␉panicAddr -= (UInt32)kernelData;␊ |
716 | ␉␊ |
717 | ␉while( ␊ |
718 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
719 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
720 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
721 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
722 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
723 | ␉␉ )␊ |
724 | ␉{␊ |
725 | ␉␉patchLocation++;␊ |
726 | ␉}␊ |
727 | ␉patchLocation--;␊ |
728 | ␉␊ |
729 | ␉// Replace panic with nops␊ |
730 | ␉bytes[patchLocation + 0] = 0x90;␊ |
731 | ␉bytes[patchLocation + 1] = 0x90;␊ |
732 | ␉bytes[patchLocation + 2] = 0x90;␊ |
733 | ␉bytes[patchLocation + 3] = 0x90;␊ |
734 | ␉bytes[patchLocation + 4] = 0x90;␊ |
735 | ␉␊ |
736 | ␉␊ |
737 | }␊ |
738 | ␊ |
739 | void patch_lapic_interrupt(void* kernelData)␊ |
740 | {␊ |
741 | ␉// NOTE: this is a hack untill I finish patch_lapic_configure␊ |
742 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
743 | ␉␊ |
744 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_interrupt");␊ |
745 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
746 | ␉{␊ |
747 | ␉␉printf("Unable to locate %s\n", "_lapic_interrupt");␊ |
748 | ␉␉return;␊ |
749 | ␉␉␊ |
750 | ␉}␊ |
751 | ␉␊ |
752 | ␉UInt32 patchLocation = symbol->addr - textAddress + textSection; ␊ |
753 | ␉␊ |
754 | ␉␊ |
755 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
756 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
757 | ␉{␊ |
758 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
759 | ␉␉return;␊ |
760 | ␉}␊ |
761 | ␉UInt32 panicAddr = symbol->addr - textAddress; ␊ |
762 | ␉␊ |
763 | ␉patchLocation -= (UInt32)kernelData;␊ |
764 | ␉panicAddr -= (UInt32)kernelData;␊ |
765 | ␉␊ |
766 | ␉while( ␊ |
767 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
768 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
769 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
770 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
771 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
772 | ␉␉ )␊ |
773 | ␉{␊ |
774 | ␉␉patchLocation++;␊ |
775 | ␉}␊ |
776 | ␉patchLocation--;␊ |
777 | ␉␊ |
778 | ␉// Replace panic with nops␊ |
779 | ␉bytes[patchLocation + 0] = 0x90;␊ |
780 | ␉bytes[patchLocation + 1] = 0x90;␊ |
781 | ␉bytes[patchLocation + 2] = 0x90;␊ |
782 | ␉bytes[patchLocation + 3] = 0x90;␊ |
783 | ␉bytes[patchLocation + 4] = 0x90;␊ |
784 | ␉␊ |
785 | ␉␊ |
786 | }␊ |
787 | ␊ |
788 | ␊ |
789 | void patch_lapic_configure(void* kernelData)␊ |
790 | {␊ |
791 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
792 | ␉␊ |
793 | ␉UInt32 patchLocation;␊ |
794 | ␉UInt32 lapicStart;␊ |
795 | ␉UInt32 lapicInterruptBase;␊ |
796 | ␉␊ |
797 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_configure");␊ |
798 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
799 | ␉{␊ |
800 | ␉␉printf("Unable to locate %s\n", "_lapic_configure");␊ |
801 | ␉␉return;␊ |
802 | ␉}␊ |
803 | ␉patchLocation = symbol->addr - textAddress + textSection; ␊ |
804 | ␉␊ |
805 | ␉symbol = lookup_kernel_symbol("_lapic_start");␊ |
806 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
807 | ␉{␊ |
808 | ␉␉printf("Unable to locate %s\n", "_lapic_start");␊ |
809 | ␉␉return;␊ |
810 | ␉}␊ |
811 | ␉lapicStart = symbol->addr; ␊ |
812 | ␊ |
813 | ␊ |
814 | ␉symbol = lookup_kernel_symbol("_lapic_interrupt_base");␊ |
815 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
816 | ␉{␊ |
817 | ␉␉printf("Unable to locate %s\n", "_lapic_interrupt_base");␊ |
818 | ␉␉return;␊ |
819 | ␉}␊ |
820 | ␉lapicInterruptBase = symbol->addr;␊ |
821 | ␉patchLocation -= (UInt32)kernelData;␊ |
822 | ␉lapicStart -= (UInt32)kernelData;␊ |
823 | ␉lapicInterruptBase -= (UInt32)kernelData;␊ |
824 | ␉␊ |
825 | ␉␊ |
826 | ␉// Looking for the following:␊ |
827 | ␉//movl _lapic_start,%e_x␊ |
828 | ␉//addl $0x00000320,%e_x␊ |
829 | ␉// 8b 15 __ __ __ __ 81 c2 20 03 00 00␊ |
830 | ␉while( ␊ |
831 | ␉␉ (bytes[patchLocation - 2] != 0x8b) ||␊ |
832 | ␉␉ //bytes[patchLocation -1] != 0x15) ||␉// Register, we don't care what it is␊ |
833 | ␉␉ ( lapicStart != (UInt32)(␊ |
834 | ␉␉␉␉␉␉␉␉␉(bytes[patchLocation + 0] << 0 | ␊ |
835 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 1] << 8 | ␊ |
836 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 2] << 16 |␊ |
837 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 3] << 24␊ |
838 | ␉␉␉␉␉␉␉␉␉)␊ |
839 | ␉␉␉␉␉␉␉␉ )␊ |
840 | ␉␉ ) || ␊ |
841 | ␉␉ (bytes[patchLocation + 4 ] != 0x81) ||␊ |
842 | ␉␉ //(bytes[patchLocation + 5 ] != 0Cx2) ||␉// register␊ |
843 | ␉␉ (bytes[patchLocation + 6 ] != 0x20) ||␊ |
844 | ␉␉ (bytes[patchLocation + 7 ] != 0x03) ||␊ |
845 | ␉␉ (bytes[patchLocation + 8 ] != 0x00) ||␊ |
846 | ␉␉ (bytes[patchLocation + 9] != 0x00)␊ |
847 | ␊ |
848 | ␉␉ )␊ |
849 | ␉{␊ |
850 | ␉␉patchLocation++;␊ |
851 | ␉}␊ |
852 | ␉patchLocation-=2;␊ |
853 | ␊ |
854 | ␉// NOTE: this is currently hardcoded, change it to be more resilient to changes␊ |
855 | ␉// At a minimum, I should have this do a cheksup first and if not matching, remove the panic instead.␊ |
856 | ␉␊ |
857 | ␉// 8b 15 __ __ __ __ -> movl␉␉ _lapic_start,%edx (NOTE: this should already be here)␊ |
858 | ␉/*␊ |
859 | ␉bytes[patchLocation++] = 0x8B;␊ |
860 | ␉bytes[patchLocation++] = 0x15;␊ |
861 | ␉bytes[patchLocation++] = (lapicStart & 0x000000FF) >> 0;␊ |
862 | ␉bytes[patchLocation++] = (lapicStart & 0x0000FF00) >> 8;␊ |
863 | ␉bytes[patchLocation++] = (lapicStart & 0x00FF0000) >> 16;␊ |
864 | ␉bytes[patchLocation++] = (lapicStart & 0xFF000000) >> 24;␊ |
865 | ␉*/␊ |
866 | ␉patchLocation += 6;␊ |
867 | ␉␊ |
868 | ␉// 81 c2 60 03 00 00 -> addl␉␉ $0x00000320,%edx␊ |
869 | ␉/*␊ |
870 | ␉bytes[patchLocation++] = 0x81;␊ |
871 | ␉bytes[patchLocation++] = 0xC2;␊ |
872 | ␉*/␊ |
873 | ␉patchLocation += 2;␊ |
874 | ␉bytes[patchLocation++] = 0x60;␊ |
875 | ␉/*␊ |
876 | ␉bytes[patchLocation++];// = 0x03;␊ |
877 | ␉bytes[patchLocation++];// = 0x00;␊ |
878 | ␉bytes[patchLocation++];// = 0x00;␊ |
879 | ␉*/␊ |
880 | ␉ patchLocation += 3;␊ |
881 | ␊ |
882 | ␉// c7 02 00 04 00 00 -> movl␉␉ $0x00000400,(%edx)␊ |
883 | ␉bytes[patchLocation++] = 0xC7;␊ |
884 | ␉bytes[patchLocation++] = 0x02;␊ |
885 | ␉bytes[patchLocation++] = 0x00;␊ |
886 | ␉bytes[patchLocation++] = 0x04;␊ |
887 | ␉bytes[patchLocation++] = 0x00;␊ |
888 | ␉bytes[patchLocation++] = 0x00;␊ |
889 | ␉␊ |
890 | ␉// 83 ea 40 -> subl␉␉ $0x40,edx␊ |
891 | ␉bytes[patchLocation++] = 0x83;␊ |
892 | ␉bytes[patchLocation++] = 0xEA;␊ |
893 | ␉bytes[patchLocation++] = 0x40;␊ |
894 | ␊ |
895 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
896 | ␉bytes[patchLocation++] = 0xA1;␊ |
897 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
898 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
899 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
900 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
901 | ␊ |
902 | ␉// 83 c0 0e -> addl␉␉ $0x0e,%eax␊ |
903 | ␉bytes[patchLocation++] = 0x83;␊ |
904 | ␉bytes[patchLocation++] = 0xC0;␊ |
905 | ␉bytes[patchLocation++] = 0x0E;␊ |
906 | ␊ |
907 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
908 | ␉bytes[patchLocation++] = 0x89;␊ |
909 | ␉bytes[patchLocation++] = 0x02;␊ |
910 | ␉␊ |
911 | ␉// 81c230030000␉␉ addl␉␉ $0x00000330,%edx␊ |
912 | ␉bytes[patchLocation++] = 0x81;␊ |
913 | ␉bytes[patchLocation++] = 0xC2;␊ |
914 | ␉bytes[patchLocation++] = 0x30;␊ |
915 | ␉bytes[patchLocation++] = 0x03;␊ |
916 | ␉bytes[patchLocation++] = 0x00;␊ |
917 | ␉bytes[patchLocation++] = 0x00;␊ |
918 | ␉␊ |
919 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
920 | ␉bytes[patchLocation++] = 0xA1;␊ |
921 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
922 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
923 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
924 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
925 | ␉␊ |
926 | ␉// 83 c0 0f -> addl␉␉ $0x0f,%eax␊ |
927 | ␉bytes[patchLocation++] = 0x83;␊ |
928 | ␉bytes[patchLocation++] = 0xC0;␊ |
929 | ␉bytes[patchLocation++] = 0x0F;␊ |
930 | ␉␊ |
931 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
932 | ␉bytes[patchLocation++] = 0x89;␊ |
933 | ␉bytes[patchLocation++] = 0x02;␊ |
934 | ␉␊ |
935 | ␉// 83 ea 10 -> subl␉␉ $0x10,edx␊ |
936 | ␉bytes[patchLocation++] = 0x83;␊ |
937 | ␉bytes[patchLocation++] = 0xEA;␊ |
938 | ␉bytes[patchLocation++] = 0x10;␊ |
939 | ␊ |
940 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
941 | ␉bytes[patchLocation++] = 0xA1;␊ |
942 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
943 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
944 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
945 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
946 | ␉␊ |
947 | ␉// 83 c0 0c -> addl␉␉ $0x0c,%eax␊ |
948 | ␉bytes[patchLocation++] = 0x83;␊ |
949 | ␉bytes[patchLocation++] = 0xC0;␊ |
950 | ␉bytes[patchLocation++] = 0x0C;␊ |
951 | ␊ |
952 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
953 | ␉bytes[patchLocation++] = 0x89;␊ |
954 | ␉bytes[patchLocation++] = 0x02;␊ |
955 | ␊ |
956 | ␉// Replace remaining with nops␊ |
957 | ␊ |
958 | ␊ |
959 | ␉bytes[patchLocation++] = 0x90;␊ |
960 | ␉bytes[patchLocation++] = 0x90;␊ |
961 | ␉bytes[patchLocation++] = 0x90;␊ |
962 | ␉bytes[patchLocation++] = 0x90;␊ |
963 | ␉//␉bytes[patchLocation++] = 0x90; // double check the lenght of the patch...␊ |
964 | ␉//␉bytes[patchLocation++] = 0x90;␊ |
965 | }␊ |
966 | |