Skip to content

Instantly share code, notes, and snippets.

@ChiChou
Last active April 13, 2023 04:46
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ChiChou/cc9b95a7c42bd0988a453716f18a2aaf to your computer and use it in GitHub Desktop.
Save ChiChou/cc9b95a7c42bd0988a453716f18a2aaf to your computer and use it in GitHub Desktop.
Frida in-memory Mach-O parser
// to speed up, I removed all data validation
function MemoryBuffer(address, size) {
this.base = address
if (!size) {
// const range = Process.findRangeByAddress(address)
// if (!range)
// throw new Error('invalid address: ' + address)
// this.length = range.base.add(range.size).sub(address).toInt32()
this.length = 4096
} else {
this.length = size
}
}
const mapping = [
['Int', 'Int', 4],
['UInt', 'UInt', 4],
['Float', 'Float', 4],
['Double', 'Double', 8],
['Int8', 'S8', 1],
['UInt8', 'U8', 1],
['Int16', 'S16', 2],
['UInt16', 'U16', 2],
['Int32', 'S32', 4],
['UInt32', 'U32', 4]
]
const isLE = ((new Uint32Array((new Uint8Array([1, 2, 3, 4])).buffer))[0] === 0x04030201)
const proto = MemoryBuffer.prototype
proto.slice = function(begin, end) {
// if (isNaN(begin) || begin < 0) {
// throw new Error('invalid offset: ' + begin)
// }
size = (typeof end === 'undefined' ? this.length : end ) - begin
/* if (isNaN(end) || end > this.length) {
throw new Error('invalid end: ' + end)
} */
return new MemoryBuffer(this.base.add(begin), size)
}
proto.toString = function() {
try {
return Memory.readUtf8String(this.base)
} catch(e) {
return '(invalid utf8)'
}
}
const noImpl = function() {
throw new Error('not implemented')
}
mapping.forEach(function(type) {
const method = type[0]
const dest = type[1]
const size = type[2]
proto['read' + method] = function(offset) {
// validate?
const address = this.base.add(offset)
return Memory['read' + dest](address)
}
// proto['write' + method] = function(offset, val) {
// const address = this.base.add(offset)
// return Memory['write' + dest](address)
// }
const inverse = function(offset) {
const address = this.base.add(offset)
const buf = new Buffer(Memory.readByteArray(address, size))
return buf['read' + method + (isLE ? 'BE' : 'LE')]()
}
if (size > 1) {
// le, be
proto['read' + method + 'LE'] = isLE ? proto['read' + method] : inverse
proto['read' + method + 'BE'] = isLE ? inverse : proto['read' + method]
// readonly
proto['write' + method + 'LE'] = proto['write' + method + 'BE'] = noImpl
}
})
// usage
const macho = require('macho')
const fatmacho = require('fatmacho')
const main = Process.enumerateModulesSync()[0]
const buffer = new MemoryBuffer(main.base, main.size)
var info = null
try {
const bins = fatmacho.parse(buffer)
console.log(bins)
info = macho.parse(bins[0].data)
} catch (ex) {
info = macho.parse(buffer)
}
const CSSLOT_CODEDIRECTORY = 0
const CSSLOT_REQUIREMENTS = 2
const CSSLOT_ENTITLEMENTS = 5
function parseEntitlements(data) {
const count = data.readUInt32BE(8)
for (var i = 0; i < count; i++) {
const base = 8 * i
const type = data.readUInt32BE(base + 12)
const blob = data.readUInt32BE(base + 16)
if (type === CSSLOT_ENTITLEMENTS) {
const size = data.readUInt32BE(blob + 4)
const buf = data.slice(blob + 8, blob + size)
return Memory.readUtf8String(buf.base, buf.length)
}
}
return null;
}
info.cmds.forEach(function(cmd) {
if (cmd.type === 'code_signature') {
const result = parseEntitlements(buffer.slice(cmd.dataoff))
console.log(result)
}
})
// console.log(JSON.stringify(info, null, 4))
@ChiChou
Copy link
Author

ChiChou commented Nov 13, 2017

And the sample output


➜  demo frida Calculator -l agent.js --debug
     ____
    / _  |   Frida 10.6.4 - A world-class dynamic instrumentation framework
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at http://www.frida.re/docs/home/
Attaching...
Debugger listening on port 5858

{
    "bits": 64,
    "magic": 4277009103,
    "cpu": {
        "type": "x86_64",
        "subtype": "all",
        "endian": "le"
    },
    "filetype": "execute",
    "ncmds": 26,
    "sizeofcmds": 3872,
    "flags": {
        "noundefs": true,
        "dyldlink": true,
        "twolevel": true,
        "pie": true
    },
    "cmds": [
        {
            "type": "segment_64",
            "name": "__PAGEZERO",
            "vmaddr": 0,
            "vmsize": 4294967296,
            "fileoff": 32,
            "filesize": 0,
            "maxprot": {
                "read": false,
                "write": false,
                "exec": false
            },
            "initprot": {
                "read": false,
                "write": false,
                "exec": false
            },
            "nsects": 0,
            "flags": {},
            "sections": []
        },
        {
            "type": "segment_64",
            "name": "__TEXT",
            "vmaddr": 4294967296,
            "vmsize": 122880,
            "fileoff": 104,
            "filesize": 122880,
            "maxprot": {
                "read": true,
                "write": true,
                "exec": true
            },
            "initprot": {
                "read": true,
                "write": false,
                "exec": true
            },
            "nsects": 9,
            "flags": {},
            "sections": [
                {
                    "sectname": "__text",
                    "segname": "__TEXT",
                    "addr": 4294973380,
                    "size": 85041,
                    "offset": 6084,
                    "align": 2,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {
                            "pure_instructions": true
                        },
                        "sys": {
                            "some_instructions": true
                        }
                    },
                    "data": {
                        "base": "0x10aef17c4",
                        "length": 85041
                    }
                },
                {
                    "sectname": "__stubs",
                    "segname": "__TEXT",
                    "addr": 4295058422,
                    "size": 180,
                    "offset": 91126,
                    "align": 1,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "symbol_stubs",
                    "attributes": {
                        "usr": {
                            "pure_instructions": true
                        },
                        "sys": {
                            "some_instructions": true
                        }
                    },
                    "data": {
                        "base": "0x10af063f6",
                        "length": 180
                    }
                },
                {
                    "sectname": "__stub_helper",
                    "segname": "__TEXT",
                    "addr": 4295058604,
                    "size": 316,
                    "offset": 91308,
                    "align": 2,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {
                            "pure_instructions": true
                        },
                        "sys": {
                            "some_instructions": true
                        }
                    },
                    "data": {
                        "base": "0x10af064ac",
                        "length": 316
                    }
                },
                {
                    "sectname": "__objc_methname",
                    "segname": "__TEXT",
                    "addr": 4295058920,
                    "size": 17894,
                    "offset": 91624,
                    "align": 0,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "cstring_literals",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af065e8",
                        "length": 17894
                    }
                },
                {
                    "sectname": "__objc_classname__TEXT",
                    "segname": "__TEXT",
                    "addr": 4295076814,
                    "size": 710,
                    "offset": 109518,
                    "align": 0,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "cstring_literals",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0abce",
                        "length": 710
                    }
                },
                {
                    "sectname": "__objc_methtype",
                    "segname": "__TEXT",
                    "addr": 4295077524,
                    "size": 2507,
                    "offset": 110228,
                    "align": 0,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "cstring_literals",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0ae94",
                        "length": 2507
                    }
                },
                {
                    "sectname": "__const",
                    "segname": "__TEXT",
                    "addr": 4295080032,
                    "size": 528,
                    "offset": 112736,
                    "align": 4,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0b860",
                        "length": 528
                    }
                },
                {
                    "sectname": "__cstring",
                    "segname": "__TEXT",
                    "addr": 4295080560,
                    "size": 8528,
                    "offset": 113264,
                    "align": 0,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "cstring_literals",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0ba70",
                        "length": 8528
                    }
                },
                {
                    "sectname": "__unwind_info",
                    "segname": "__TEXT",
                    "addr": 4295089088,
                    "size": 1076,
                    "offset": 121792,
                    "align": 2,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0dbc0",
                        "length": 1076
                    }
                }
            ]
        },
        {
            "type": "segment_64",
            "name": "__DATA",
            "vmaddr": 4295090176,
            "vmsize": 53248,
            "fileoff": 896,
            "filesize": 53248,
            "maxprot": {
                "read": true,
                "write": true,
                "exec": true
            },
            "initprot": {
                "read": true,
                "write": true,
                "exec": false
            },
            "nsects": 19,
            "flags": {
                "highvm": true
            },
            "sections": [
                {
                    "sectname": "__nl_symbol_ptr",
                    "segname": "__DATA",
                    "addr": 4295090176,
                    "size": 16,
                    "offset": 122880,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "non_lazy_symbol_pointers",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0e000",
                        "length": 16
                    }
                },
                {
                    "sectname": "__got",
                    "segname": "__DATA",
                    "addr": 4295090192,
                    "size": 176,
                    "offset": 122896,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "non_lazy_symbol_pointers",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0e010",
                        "length": 176
                    }
                },
                {
                    "sectname": "__la_symbol_ptr",
                    "segname": "__DATA",
                    "addr": 4295090368,
                    "size": 240,
                    "offset": 123072,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "lazy_symbol_pointers",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0e0c0",
                        "length": 240
                    }
                },
                {
                    "sectname": "__const",
                    "segname": "__DATA",
                    "addr": 4295090608,
                    "size": 576,
                    "offset": 123312,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0e1b0",
                        "length": 576
                    }
                },
                {
                    "sectname": "__cfstring",
                    "segname": "__DATA",
                    "addr": 4295091184,
                    "size": 9344,
                    "offset": 123888,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af0e3f0",
                        "length": 9344
                    }
                },
                {
                    "sectname": "__objc_classlist__DATA",
                    "segname": "__DATA",
                    "addr": 4295100528,
                    "size": 232,
                    "offset": 133232,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {
                            "no_dead_strip": true
                        },
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af10870",
                        "length": 232
                    }
                },
                {
                    "sectname": "__objc_catlist",
                    "segname": "__DATA",
                    "addr": 4295100760,
                    "size": 16,
                    "offset": 133464,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {
                            "no_dead_strip": true
                        },
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af10958",
                        "length": 16
                    }
                },
                {
                    "sectname": "__objc_protolist__DATA",
                    "segname": "__DATA",
                    "addr": 4295100776,
                    "size": 72,
                    "offset": 133480,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af10968",
                        "length": 72
                    }
                },
                {
                    "sectname": "__objc_imageinfo__DATA",
                    "segname": "__DATA",
                    "addr": 4295100848,
                    "size": 8,
                    "offset": 133552,
                    "align": 2,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af109b0",
                        "length": 8
                    }
                },
                {
                    "sectname": "__objc_const",
                    "segname": "__DATA",
                    "addr": 4295100856,
                    "size": 29264,
                    "offset": 133560,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af109b8",
                        "length": 29264
                    }
                },
                {
                    "sectname": "__objc_selrefs",
                    "segname": "__DATA",
                    "addr": 4295130120,
                    "size": 4752,
                    "offset": 162824,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "literal_pointers",
                    "attributes": {
                        "usr": {
                            "no_dead_strip": true
                        },
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af17c08",
                        "length": 4752
                    }
                },
                {
                    "sectname": "__objc_protorefs__DATA",
                    "segname": "__DATA",
                    "addr": 4295134872,
                    "size": 8,
                    "offset": 167576,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af18e98",
                        "length": 8
                    }
                },
                {
                    "sectname": "__objc_classrefs__DATA",
                    "segname": "__DATA",
                    "addr": 4295134880,
                    "size": 456,
                    "offset": 167584,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {
                            "no_dead_strip": true
                        },
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af18ea0",
                        "length": 456
                    }
                },
                {
                    "sectname": "__objc_superrefs__DATA",
                    "segname": "__DATA",
                    "addr": 4295135336,
                    "size": 184,
                    "offset": 168040,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {
                            "no_dead_strip": true
                        },
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af19068",
                        "length": 184
                    }
                },
                {
                    "sectname": "__objc_ivar",
                    "segname": "__DATA",
                    "addr": 4295135520,
                    "size": 1928,
                    "offset": 168224,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af19120",
                        "length": 1928
                    }
                },
                {
                    "sectname": "__objc_data",
                    "segname": "__DATA",
                    "addr": 4295137448,
                    "size": 2320,
                    "offset": 170152,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af198a8",
                        "length": 2320
                    }
                },
                {
                    "sectname": "__data",
                    "segname": "__DATA",
                    "addr": 4295139768,
                    "size": 1784,
                    "offset": 172472,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "regular",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10af1a1b8",
                        "length": 1784
                    }
                },
                {
                    "sectname": "__common",
                    "segname": "__DATA",
                    "addr": 4295141552,
                    "size": 24,
                    "offset": 0,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "zerofill",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10aef0000",
                        "length": 24
                    }
                },
                {
                    "sectname": "__bss",
                    "segname": "__DATA",
                    "addr": 4295141576,
                    "size": 40,
                    "offset": 0,
                    "align": 3,
                    "reloff": 0,
                    "nreloc": 0,
                    "type": "zerofill",
                    "attributes": {
                        "usr": {},
                        "sys": {}
                    },
                    "data": {
                        "base": "0x10aef0000",
                        "length": 40
                    }
                }
            ]
        },
        {
            "type": "segment_64",
            "name": "__LINKEDIT",
            "vmaddr": 4295143424,
            "vmsize": 24576,
            "fileoff": 2488,
            "filesize": 23376,
            "maxprot": {
                "read": true,
                "write": true,
                "exec": true
            },
            "initprot": {
                "read": true,
                "write": false,
                "exec": false
            },
            "nsects": 0,
            "flags": {},
            "sections": []
        },
        {
            "type": "dyld_info",
            "data": {
                "base": "0x10aef0a08",
                "length": 40
            },
            "fileoff": 2560
        },
        {
            "type": "symtab",
            "symoff": 182536,
            "nsyms": 130,
            "stroff": 184952,
            "strsize": 3272,
            "fileoff": 2608
        },
        {
            "type": "dysymtab",
            "ilocalsym": 0,
            "nlocalsym": 1,
            "iextdefsym": 1,
            "nextdefsym": 1,
            "iundefsym": 2,
            "nundefsym": 128,
            "tocoff": 0,
            "ntoc": 0,
            "modtaboff": 0,
            "nmodtab": 0,
            "extrefsymoff": 0,
            "nextrefsyms": 0,
            "indirectsymoff": 184616,
            "nindirectsyms": 84,
            "extreloff": 0,
            "nextrel": 0,
            "locreloff": 0,
            "nlocrel": 0,
            "fileoff": 2632
        },
        {
            "type": "load_dylinker",
            "cmd": "/usr/lib/dyld",
            "fileoff": 2712
        },
        {
            "type": "uuid",
            "data": {
                "base": "0x10aef0ac0",
                "length": 16
            },
            "fileoff": 2744
        },
        {
            "type": "version_min_macosx",
            "version": "10.undefined.undefined",
            "sdk": "10.undefined.undefined",
            "fileoff": 2768
        },
        {
            "type": "source_version",
            "data": {
                "base": "0x10aef0ae8",
                "length": 8
            },
            "fileoff": 2784
        },
        {
            "type": "main",
            "entryoff": 26549,
            "stacksize": 0,
            "fileoff": 2800
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa",
            "timestamp": 2,
            "current_version": 1441792,
            "compatibility_version": 65536,
            "fileoff": 2824
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/PrivateFrameworks/SpeechDictionary.framework/Versions/A/SpeechDictionary",
            "timestamp": 2,
            "current_version": 65536,
            "compatibility_version": 65536,
            "fileoff": 2912
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/PrivateFrameworks/SpeechObjects.framework/Versions/A/SpeechObjects",
            "timestamp": 2,
            "current_version": 65536,
            "compatibility_version": 65536,
            "fileoff": 3032
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/PrivateFrameworks/Calculate.framework/Versions/A/Calculate",
            "timestamp": 2,
            "current_version": 65536,
            "compatibility_version": 65536,
            "fileoff": 3144
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices",
            "timestamp": 2,
            "current_version": 3276800,
            "compatibility_version": 65536,
            "fileoff": 3248
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore",
            "timestamp": 2,
            "current_version": 68352,
            "compatibility_version": 66048,
            "fileoff": 3360
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation",
            "timestamp": 2,
            "current_version": 94240768,
            "compatibility_version": 19660800,
            "fileoff": 3456
        },
        {
            "type": "load_dylib",
            "name": "/usr/lib/libobjc.A.dylib",
            "timestamp": 2,
            "current_version": 14942208,
            "compatibility_version": 65536,
            "fileoff": 3552
        },
        {
            "type": "load_dylib",
            "name": "/usr/lib/libSystem.B.dylib",
            "timestamp": 2,
            "current_version": 82051072,
            "compatibility_version": 65536,
            "fileoff": 3608
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit",
            "timestamp": 2,
            "current_version": 101255680,
            "compatibility_version": 2949120,
            "fileoff": 3664
        },
        {
            "type": "load_dylib",
            "name": "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation",
            "timestamp": 2,
            "current_version": 94241024,
            "compatibility_version": 9830400,
            "fileoff": 3752
        },
        {
            "type": "function_starts",
            "dataoff": 181952,
            "datasize": 560,
            "addresses": [],
            "fileoff": 3856
        },
        {
            "type": "data_in_code",
            "dataoff": 182512,
            "datasize": 24,
            "fileoff": 3872
        },
        {
            "type": "code_signature",
            "dataoff": 188224,
            "datasize": 11280,
            "fileoff": 3888
        }
    ],
    "hsize": 32
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment