Investigate an Application with an Objective-C Frontend
This article will walk you through investigating an application with an Objective-C frontend using Ocular.
Sample Application
For the examples to follow, we will be working with the Mach-O Browser application, whose repository you can clone via GitHub.
Once you've successfully built macho-browser, you can transform it to a Code Property Graph (CPG):
If you're not using the default install location for Ocular, you may need to change /.shiftleft/ocular to the appropriate path.
Once you have the CPG, start Ocular:
When prompted, load the CPG you generated:
Run workspace
to ensure that your CPG has been loaded. If loaded
is true
, you're ready to proceed with your investigative queries.
Investigative Queries
The following examples will walk you through the basics of querying the CPG to gather information about your application.
Identify functions with more than 4 parameters:
cpg.method.where(_.parameter.size > 4).l
Sort methods by the number of callers and exclude the first 1000 results:
val methodList = cpg.method.map(x => (x.start.callIn.size, x.name)).l.sorted.reverse.take(1000)
Filter for methods that have callers:
methodList.filter(_._1>0).sorted
Filter for methods that do not have callers:
methodList.filter(_._1==0)
Get all of the hard-coded literals in the code:
cpg.literal.code.l
Get all types and associated properties/members in the code:
val typesList = cpg.typeDecl.map { t => (t.name, t.start.member.name.l) }.l
Identify the call site to
malloc
where the first argument contains an arithmetic expression:cpg.call("malloc").filter(_.argument (1).arithmetics ).l
Querying for Method-Specific Information
Let's say that you're interested in a class called LoadCommand and how it is used. You can declare variables containing the class name for easy reuse:
You can pick a class and observe its methods:
The result will look something like the following:
You can get a list of all Objective-C classes (the convention is that class names start with an uppercase later):
You can find where a method is called:
Get subclasses in it's type hierarchy:
Get superclasses in its type hierarchy:
Get all of the NSObject subclasses:
Example: Protecting Against the Billion Laughs Attack
iOS offers you two SDK options for parsing XML: NSXMLParser and libxml2.
If you're using NSXMLParser, you should enable the shouldResolveExternalEntities
property to protect yourself against the Billion Laughs Attack: