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