Dump Objective C class hierarchy with frida


#1

frida.re is a pretty good framework for iOS & macOS platform instrument.

Listing all available Objective C classes in frida is easy:

Object.keys(ObjC.classes)

But actually this will return all classes loaded in current process, including system frameworks. If we want something like weak_classdump, to list classes from executable it self only, Objective C runtime already provides such function objc_copyClassNamesForImage.

So here’s the code sharing part:

function hierarchy() {
  var objc_copyClassNamesForImage = new NativeFunction(Module.findExportByName(
    null, 'objc_copyClassNamesForImage'), 'pointer', ['pointer', 'pointer'])
  var free = new NativeFunction(Module.findExportByName(null, 'free'), 'void', ['pointer'])
  var classes = new Array(count)
  var p = Memory.alloc(Process.pointerSize)
  Memory.writeUInt(p, 0)
  var path = ObjC.classes.NSBundle.mainBundle().executablePath().UTF8String()
  var pPath = Memory.allocUtf8String(path)
  var pClasses = objc_copyClassNamesForImage(pPath, p)
  var count = Memory.readUInt(p)
  for (var i = 0; i < count; i++) {
    var pClassName = Memory.readPointer(pClasses.add(i * Process.pointerSize))
    classes[i] = Memory.readUtf8String(pClassName)
  }
  free(pClasses)

  var tree = {}
  classes.forEach(function(name) {
    var clazz = ObjC.classes[name]
    var chain = [name]
    while (clazz = clazz.$superClass)
      chain.unshift(clazz.$className)

    var node = tree
    chain.forEach(function(clazz) {
      node[clazz] = node[clazz] || {}
      node = node[clazz]
    })
  })
  return tree
}

console.log(new Date())
s = hierarchy()
console.log(new Date())
console.log(JSON.stringify(tree, null, 4)

Note that classes may be a huge array and takes a long time to generate the result.

Example output:

➜  /tmp frida Calculator -l lz.js
     ____
    / _  |   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...
2017-10-06 13:49:16.691+08:00
2017-10-06 13:49:16.739+08:00
{
    "NSObject": {
        "NSResponder": {
            "NSView": {
                "NSBox": {
                    "BitFieldBox": {},
                    "KeyboardBackingBox": {}
                },
                "NSVisualEffectView": {
                    "BackgroundView": {}
                },
                "NSControl": {
                    "NSTextField": {
                        "OctetIndicatorField": {},
                        "RightLCDField": {}
                    },
...

#2

frida是个好东东


#3

其实这个纯 OC 也就几行,frida 让快速写小代码段做测试的工作更方便了(不用编译部署)