Created
April 23, 2009 07:19
-
-
Save copumpkin/100370 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
kernelcache.idc, by pumpkin with contributions from roxfan | |
Copyright (C) 2008 pumpkin | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#include <idc.idc> | |
static makestructs() { | |
auto id; | |
id = AddStrucEx(-1,"mach_header",0); | |
AddStrucMember(id,"magic", 0X0, 0x20000400, -1, 4); | |
AddStrucMember(id,"cputype", 0X4, 0x20000400, -1, 4); | |
AddStrucMember(id,"cpusubtype", 0X8, 0x20000400, -1, 4); | |
AddStrucMember(id,"filetype", 0XC, 0x20000400, -1, 4); | |
AddStrucMember(id,"ncmds", 0X10, 0x20000400, -1, 4); | |
AddStrucMember(id,"sizeofcmds", 0X14, 0x20000400, -1, 4); | |
AddStrucMember(id,"flags", 0X18, 0x20000400, -1, 4); | |
id = AddStrucEx(-1,"segment_command",0); | |
AddStrucMember(id,"cmd", 0X0, 0x20000400, -1, 4); | |
AddStrucMember(id,"cmdsize", 0X4, 0x20000400, -1, 4); | |
AddStrucMember(id,"segname", 0X8, 0x50000400, 0x0, 16); | |
AddStrucMember(id,"vmaddr", 0X18, 0x20500400, 0XFFFFFFFF, 4); | |
AddStrucMember(id,"vmsize", 0X1C, 0x20000400, -1, 4); | |
AddStrucMember(id,"fileoff", 0X20, 0x20000400, -1, 4); | |
AddStrucMember(id,"filesize", 0X24, 0x20000400, -1, 4); | |
AddStrucMember(id,"maxprot", 0X28, 0x20000400, -1, 4); | |
AddStrucMember(id,"initprot", 0X2C, 0x20000400, -1, 4); | |
AddStrucMember(id,"nsects", 0X30, 0x20000400, -1, 4); | |
AddStrucMember(id,"flags", 0X34, 0x20000400, -1, 4); | |
id = AddStrucEx(-1, "section", 0); | |
AddStrucMember(id,"sectname", 0X0, 0x50000400, 0x0, 16); | |
AddStrucMember(id,"segname", 0X10, 0x50000400, 0x0, 16); | |
AddStrucMember(id,"addr", 0X20, 0x20500400, 0XFFFFFFFF, 4); | |
AddStrucMember(id,"size", 0X24, 0x20000400, -1, 4); | |
AddStrucMember(id,"offset", 0X28, 0x20000400, -1, 4); | |
AddStrucMember(id,"align", 0X2C, 0x20000400, -1, 4); | |
AddStrucMember(id,"reloff", 0X30, 0x20000400, -1, 4); | |
AddStrucMember(id,"nreloc", 0X34, 0x20000400, -1, 4); | |
AddStrucMember(id,"flags", 0X38, 0x20000400, -1, 4); | |
AddStrucMember(id,"reserved1", 0X3C, 0x20000400, -1, 4); | |
AddStrucMember(id,"reserved2", 0X40, 0x20000400, -1, 4); | |
id = AddStrucEx(-1, "symtab_command", 0); | |
AddStrucMember(id,"cmd", 0X0, 0x20000400, -1, 4); | |
AddStrucMember(id,"cmdsize", 0X4, 0x20000400, -1, 4); | |
AddStrucMember(id,"symoff", 0X8, 0x20000400, -1, 4); | |
AddStrucMember(id,"nsyms", 0XC, 0x20000400, -1, 4); | |
AddStrucMember(id,"stroff", 0X10, 0x20000400, -1, 4); | |
AddStrucMember(id,"strsize", 0X14, 0x20000400, -1, 4); | |
id = AddStrucEx(-1,"uuid_command",0); | |
AddStrucMember(id,"cmd", 0X0, 0x20000400, -1, 4); | |
AddStrucMember(id,"cmdsize", 0X4, 0x20000400, -1, 4); | |
AddStrucMember(id,"uuid", 0X8, 0x000400, -1, 16); | |
id = AddStrucEx(-1,"prelink_info",0); | |
AddStrucMember(id,"field_0", 0X0, 0x20000400, -1, 4); | |
AddStrucMember(id,"field_4", 0X4, 0x20000400, -1, 4); | |
AddStrucMember(id,"offset", 0X8, 0x20500400, 0X0, 4); | |
AddStrucMember(id,"identifier", 0XC, 0x50000400, 0x0, 64); | |
AddStrucMember(id,"version", 0X4C, 0x50000400, 0x0, 64); | |
AddStrucMember(id,"field_8C", 0X8C, 0x20000400, -1, 4); | |
AddStrucMember(id,"field_90", 0X90, 0x20000400, -1, 4); | |
AddStrucMember(id,"macho_start", 0X94, 0x20500400, 0X0, 4); | |
AddStrucMember(id,"field_98", 0X98, 0x20000400, -1, 4); | |
AddStrucMember(id,"field_9C", 0X9C, 0x20000400, -1, 4); | |
AddStrucMember(id,"initializer", 0XA0, 0x20500400, 0X0, 4); | |
AddStrucMember(id,"finalizer", 0XA4, 0x20500400, 0X0, 4); | |
} | |
static mkcode(addr) { | |
if (addr & 1 == 1) { | |
SetReg(addr - 1, "T", 1); | |
MakeCode(addr - 1); | |
MakeFunction(addr - 1, BADADDR); | |
} else { | |
SetReg(addr, "T", 0); | |
MakeCode(addr); | |
MakeFunction(addr, BADADDR); | |
} | |
} | |
static process_macho(addr) { | |
auto i, j, k; | |
auto lc_cur, lc_count; | |
auto cur_seg_text_start, cur_seg_text_end; | |
auto cur_sec_name, cur_sec_addr, cur_sec_size; | |
MakeStructEx(addr, -1, "mach_header"); | |
lc_count = Dword(addr + GetMemberOffset(GetStrucIdByName("mach_header"), "ncmds")); | |
lc_cur = addr + GetStrucSize(GetStrucIdByName("mach_header")); | |
for (i = 0; i < lc_count; i++) { | |
if(Dword(lc_cur) == 1) { | |
MakeStructEx(lc_cur, -1, "segment_command"); | |
for (j = 0; j < Dword(lc_cur + GetMemberOffset(GetStrucIdByName("segment_command"), "nsects")); j++) { | |
MakeStructEx(lc_cur + GetStrucSize(GetStrucIdByName("segment_command")) + (GetStrucSize(GetStrucIdByName("section")) * j), -1, "section"); | |
cur_sec_name = GetString(lc_cur + GetStrucSize(GetStrucIdByName("segment_command")) + (GetStrucSize(GetStrucIdByName("section")) * j) + GetMemberOffset(GetStrucIdByName("section"), "sectname"), -1, ASCSTR_C); | |
cur_sec_addr = Dword(lc_cur + GetStrucSize(GetStrucIdByName("segment_command")) + (GetStrucSize(GetStrucIdByName("section")) * j) + GetMemberOffset(GetStrucIdByName("section"), "addr")); | |
cur_sec_size = Dword(lc_cur + GetStrucSize(GetStrucIdByName("segment_command")) + (GetStrucSize(GetStrucIdByName("section")) * j) + GetMemberOffset(GetStrucIdByName("section"), "size")); | |
if (cur_sec_name == "__text") { | |
cur_seg_text_start = cur_sec_addr; | |
cur_seg_text_end = cur_sec_addr + cur_sec_size; | |
} else if (cur_sec_name == "__const") { | |
// This is where vtables live... I'm assuming that any dword in here that's in the text section is code | |
for (k = 0; k < cur_sec_size; k = k + 4) { | |
MakeDword(cur_sec_addr + k); | |
if (Dword(cur_sec_addr + k) >= cur_seg_text_start && Dword(cur_sec_addr + k) < cur_seg_text_end) { | |
mkcode(Dword(cur_sec_addr + k)); | |
} | |
} | |
} else if (cur_sec_name == "__constructor" || cur_sec_name == "__destructor") { | |
for (k = 0; k < cur_sec_size; k = k + 4) { | |
MakeDword(cur_sec_addr + k); | |
mkcode(Dword(cur_sec_addr + k)); | |
} | |
} | |
} | |
} else if (Dword(lc_cur) == 2) { | |
// Check if symtab has any entries | |
MakeStructEx(lc_cur, -1, "symtab_command"); | |
} else if (Dword(lc_cur) == 0x1b) { | |
// Totally useless | |
MakeStructEx(lc_cur, -1, "uuid_command"); | |
} | |
lc_cur = lc_cur + Dword(lc_cur + 4); | |
} | |
// wait for autoanalysis of above to complete | |
Wait(); | |
// now go through the text section of this mach-o and codeify it as best we can (currently broken in that unexpected thumb code will throw it off) | |
/* | |
i = cur_seg_text_start; | |
while (i < cur_seg_text_end) { | |
Message("i = %x\n", i); | |
if (isUnknown(GetFlags(i))) { | |
mkcode(i); | |
} else if (isCode(GetFlags(i))) { | |
if (strlen(GetFunctionName(i)) > 0) { | |
i = GetFchunkAttr(i, FUNCATTR_END); | |
} else { | |
MakeFunction(i, BADADDR); | |
Wait(); | |
if (strlen(GetFunctionName(i)) > 0) { | |
i = GetFchunkAttr(i, FUNCATTR_END); | |
} | |
} | |
} else if (isData(GetFlags(i))) { | |
i = i + ItemSize(i); | |
} | |
} | |
*/ | |
} | |
static main() | |
{ | |
auto macho_start; | |
auto info_xml, info_xml_rest; | |
auto current_pos, stop; | |
auto extension_identifier; | |
auto base64_chars; | |
auto string_offset, base64_data_start, base64_data_end, base64_data; | |
auto i, j, k; | |
auto cur_char, first_three, second_three, info_offset; | |
auto initializer, finalizer; | |
makestructs(); | |
base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
macho_start = GetMemberOffset(GetStrucIdByName("prelink_info"), "macho_start"); | |
info_xml = GetString(SegByBase(SegByName("__info")), -1, ASCSTR_C); | |
current_pos = 0; | |
while (1) { | |
string_offset = strstr(info_xml, "OSBundlePrelink</key><data>"); | |
base64_data_start = string_offset + strlen("OSBundlePrelink</key><data>"); | |
info_xml_rest = substr(info_xml, base64_data_start, -1); | |
base64_data_end = strstr(info_xml_rest, "</data>"); | |
base64_data = substr(info_xml_rest, 0, base64_data_end); | |
// Dumb criterion, should probably just fix the parsing instead of relying on this shit | |
if (base64_data_end == -1 || substr(base64_data, 0, 1) != "w") { | |
break; | |
} | |
info_xml = info_xml_rest; | |
first_three = 0; | |
second_three = 0; | |
// Super lame base64 | |
for (i = 0; i < 4; i++) { | |
cur_char = strstr(base64_chars, substr(base64_data, i, i + 1)); | |
first_three = first_three | (cur_char << (6 * (3 - i))); | |
} | |
for (i = 4; i < 8; i++) { | |
cur_char = strstr(base64_chars, substr(base64_data, i, i + 1)); | |
second_three = second_three | (cur_char << (6 * (3 - (i - 4)))); | |
} | |
info_offset = (first_three << 8) | (second_three >> 16); | |
Message("Processing %s\n", GetString(info_offset + GetMemberOffset(GetStrucIdByName("prelink_info"), "identifier"), -1, ASCSTR_C)); | |
SegCreate(Dword(info_offset + macho_start), Dword(info_offset + macho_start) + Dword(info_offset + macho_start + 4), 0, 1, saRelDble, scCommon); | |
SegRename(Dword(info_offset + macho_start), substr(GetString(info_offset + GetMemberOffset(GetStrucIdByName("prelink_info"), "identifier"), -1, ASCSTR_C), 10, -1)); | |
MakeStructEx(info_offset, -1, "prelink_info"); | |
initializer = Dword(info_offset + GetMemberOffset(GetStrucIdByName("prelink_info"), "initializer")); | |
finalizer = Dword(info_offset + GetMemberOffset(GetStrucIdByName("prelink_info"), "finalizer")); | |
mkcode(initializer); | |
mkcode(finalizer); | |
for (i = 0; i < Dword(info_offset + macho_start + 4); i = i + 4) { | |
if (Dword(Dword(info_offset + macho_start) + i) == 0xFEEDFACE) { | |
Message("found Mach-O header at %#x\n", Dword(info_offset + macho_start) + i); | |
process_macho(Dword(info_offset + macho_start) + i); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment