OJTool - Putting the J into otool(1)

What is this?

You may be familiar with my jtool, in which case you know one of its many limitations is that I have not, am not, and probably will not implement Intel disassembly for it. That's how it is when you insist on writing your own disassembler and not use radare/capstone/whatever-open-source.

Apple's otool(1) is flimsy (at best). Sometimes it gets literals, and sometimes it doesn't. As of 10.12, it's more the latter than the former. Yes, you can use Hopper/IDA/etc, but sometimes for quick command line disassembly (... | grep...) nothing beats otool. But it has this ANNOYING xxxx(%rip) notation, and so go figure what that IP-relative address is, right?

So I wrote a simple filter for it, which runs the real tool, and then caches the output, looks for the xxx%(rip) and resolves it by getting the IP value from the next line (i.e. next instruction), then doing a simple hex addition.

That alone is , IMHO, useful, and really something that should have been implemented by some switch (disclaimer - maybe it is? I didn't bother to sift through otool past -tV much). But then I figured, why not combine it with jtool? Observe:

Zephyr:Work morpheus$ otool -tV /bin/ls | tail -10
00000001000043f1        pushq   %rbp
00000001000043f2        movq    %rsp, %rbp
00000001000043f5        movq    0xc14(%rip), %rax
00000001000043fc        movq    (%rax), %rcx
00000001000043ff        leaq    0xb20(%rip), %rdi
0000000100004406        movl    $0x3e, %esi
000000010000440b        movl    $0x1, %edx
0000000100004410        callq   0x1000044f2
0000000100004415        movl    $0x1, %edi
000000010000441a        callq   0x1000044b6
Zephyr:Work morpheus$ ./otoolfilt /bin/ls | tail -10
00000001000043f1        pushq   %rbp
00000001000043f2        movq    %rsp, %rbp
00000001000043f5        movq    0x100005010, %rax
00000001000043fc        movq    (%rax), %rcx
00000001000043ff        leaq    0x100004f26, %rdi ;  usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]\r;
0000000100004406        movl    $0x3e, %esi
000000010000440b        movl    $0x1, %edx
0000000100004410        callq   0x1000044f2
0000000100004415        movl    $0x1, %edi
000000010000441a        callq   0x1000044b6

This wouldn't be necessary if otool's literal detection (you know, the ## literal pool for .. comments) would work every time. Only it does sometimes, and doesn't most of the time as of 10.12. So rather than try to fix the bug somehow it was easier to adapt the filter to do that, too

New Features (4/29/2017)

A picture is worth a thousand words:

Obj-C and companion file support (05/26/2017)

A question in one of my trainings which had to do with reversing a MacOS App had me introduce two quick hacks to ojtool which add significant functionality:

  • Objective-C support: With or without a companion file, ojtool will now get all the __DATA.__objc* section data and the __got. NOTE THIS IS A HACK OF SORTS, AND SLOWS OJTOOL DOWN A BIT but is worth it:
  • Companion file support: jtool still won't do Intel disassembly, but you can force a companion file to be created using jtool --jtooldir dir -d __DATA.__const binary > /dev/null. This companion file will then be picked up by ojtool if JTOOLDIR= is specified (or if you're in the same directory). That way, set up your own symbols, including for global vars, and symbolicate Intel binaries the same way you would ARM ones!
  • Where to get it:

    Available as source here: http://newosxbook.com/src.jl?tree=listings&file=otoolfilt.c

    Comments/Feedback

    Btw, MOXiI Vols I and III are both out. But you probably know this already.