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.

3
  • 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, 2016 at 9:29
  • Have anything public? Oct 12, 2016 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. Oct 16, 2016 at 6:07

1 Answer 1

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.

2
  • 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. Oct 16, 2016 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, 2016 at 5:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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