8

I am learning to disassemble and analyze objective-c binaries. One of my frustrations is that in Hopper, and IDA, it seems that the proper cross-references and control flow are not preserved. I believe this is because of Objective-C's message passing technique.

For instance, here is a keygenme I am working on: enter image description here

As you can see it is very hard to follow. Everything seems to coalesce on message send, with very little indication of where control flow actually begins. For instance, I am trying to determine what calls mk. Obviously it is being routed through message send, but where does the call originate? Of course, the cross references IDA provides seem to stop at any Objective-C function - making it hard to determine who is calling it.

I have tried this plugin: https://github.com/zynamics/objc-helper-plugin-ida

But it results in "nothing to patch."

Does IDA have a feature to help with this? How might I trace through this by hand if need be?

Some have already suggested that I just resolve this through dynamic analysis, but I'd prefer to understand the proper way to analyze it statically.

  • I've been working on a project with the specific goal to reconstruct objective-C control flow. Debugging is a completely different task than reconstruction, because debugging will always only follow one possible path of execution. – Nordwald Oct 12 '16 at 9:29
  • Have anything public? – baordog Oct 12 '16 at 10:37
  • @Div it is not always possible to step through code with a debugger, for example, when analyzing system frameworks for an iOS version that doesn't have a jailbreak available. – Brennan Vincent Oct 16 '16 at 6:07
1

Sadly, there is no out-of-the-box solution. Even in academic research, most projects tackling this issue are heavily restricted.

To be able to reconstruct the control flow graph, you would need information about all possible values for the arguments of objc_msgSend in order to figure out which function is invoked on which object. This problem is potentially unsolvable but can be approximated, for example using backward-slicing and taint analysis.

That being said, you should be able to reconstruct most calls in benign software using this method. Based on the recovered parameters, you can insert function stubs and redirect the call in order to generate a more expressive CFG.

  • From my anecodtal experience looking at disassembled objc code: 99.99% of the time, the self and _cmd arguments to a particular objc_msgSend call are always the same and do not depend on the control flow up to that point. In fact, the majority of the time, the selector is loaded into x1 right before the objc_msgSend call. I don't see why it wouldn't be easy to get this right at least a lot of the time, if not all. – Brennan Vincent Oct 16 '16 at 6:06
  • Just play some mind games and I'm pretty sure you'll find a dozen examples, why this is not possible in any case. Just ask yourself what would you do if you try to obfuscate these calls. there is no magic... pointer analiasing and obfuscation were there before Objective-C. A vast portion of reverse engineering does not concern benign software. – Nordwald Oct 17 '16 at 5:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.