Skip to content

Instantly share code, notes, and snippets.

@copumpkin
Created April 23, 2009 07:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save copumpkin/100370 to your computer and use it in GitHub Desktop.
Save copumpkin/100370 to your computer and use it in GitHub Desktop.
/*
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