6.3.2 Change process execution flow
Why do we need to change process execution flow? Commonly it’s because the code we
want to debug could only be executed in specific conditions, which are hard to meet in the
original execution flow. Under such circumstances, we have to change the flow to redirect the
process to execute the target code for debugging. Reads awkward? Let’s see an example.
// clang -arch armv7 -isysroot `xcrun --sdk iphoneos --show-sdk-path` -framework
Foundation -framework UIKit -o MainBinary main.m
#include <stdio.h>
#include <dlfcn.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
extern void ImportantAndComplicatedFunction(void)
{
NSLog(@"iOSRE: Suppose I'm a very important and complicated function");
}
int main(int argc, char **argv)
{
if ([[[UIDevice currentDevice] systemVersion] isEqualToString:@"8.1.1"])
ImportantAndComplicatedFunction();
return 0;
}
Save this snippet as main.m, and compile it with the sentence in the comments, then copy
MainBinary to “/var/tmp/” on iOS:
snakeninnys-MacBook:6 snakeninny$ scp MainBinary root@iOSIP:/var/tmp/
MainBinary 100% 49KB
48.6KB/s 00:00
Run it:
FunMaker-5:~ root# /var/tmp/MainBinary
FunMaker-5:~ root#
Because I’m using iOS 8.1, there is no output for sure. What if I am interested in
ImportantAndComplicatedFunction but don’t have iOS 8.1.1 in hand? Then I have to
dynamically change the execution flow to make this function get called. I’ll show you how,
please keep focused. Drag and drop MainBinary into IDA, then locate to the branch before
ImportantAndComplicatedFunction, as shown in figure 6-52.