This tool is before I do ios reverse analysis, readily write a small tool, although now is not how to maintain, but here or take out a simple introduction.

At the beginning, the background of writing this tool is mainly because I want to do some plug-in development on the jailbroken ios system, so I need to analyze the call rules of some private API and pass parameters.

Although static analysis can be done through IDA, some requirements still need the convenience of dynamic analysis, and at that time, THE ARM F5 plug-in of IDA had not been released, so we could only use manual reverse ARM analysis, and the workload was quite large.

Therefore, it is possible to dynamically track the oc code call logic on ios. There is always a way to approach objC based on runtime.

Initially, I focused on the objc_msgSend interface, to which all OC calls would eventually be routed, so I wrote a GDB script to dynamically trace this interface:

define to 
b objc_msgSend
c
set $__i = 0
while ($__i < $arg0)
printf "%d: [%s %s]\n", $__i, (char*)object_getClassName($r0), (char*)$r1
set $__i++
c
end
end
Copy the code

Add the script API definition to the.gdbinit file, then attach GDB to the specified system process and execute:

You can trace the next 100 objc_msgSend calls and print out the detailed objC method call names.

However, after using this method for a period of time, I found that the effect and experience of this trace method are not very good. It is rather slow, and the UI can almost be stuck. After all, it is a global hook.

I had no choice but to think of something else, so I started working on objC’s Runtime interface

The imp address of the method can be overwritten directly, and the imp address of the method can be replaced directly. This is actually very common now, basically, an ios hook article will be introduced

I not only need to use this to realize batch automatic trace of all methods of a class, but also need to be able to automatically trace out all the parameter data of these method calls, which is the difficulty.

After all, if I can only trace the name of the method called, in fact, it is not very useful, I still need to spy on the incoming parameters of each call, so that I can see the execution status of an APP and system process at a glance in real time, as well as what was done.

Such as:

  1. To trace the system’s itunestore process, I simply disassemble the program through IDA or use class-dump to see what classes it uses.

Then configure some useful looking classes names that need to be traced:

Modify the itrace.xml configuration file to add the name of the class requiring hook:Copy the code

Note: try not to hook frequently called classes, such as UIView NSString, otherwise it will be very stuck, operation will not be convenient. Note: If you hang a class and print parameter information during the process, you can add args= “0” attribute after the corresponding class name to prohibit printing parameter information, which will stabilize the point. If you want all classes to not print parameter information, you can set it directly:

Upload all files in the itracer directory to/TMP on ios using the mobile assistant tool:

    /tmp/itracer
    /tmp/itrace.dylib
    /tmp/itrace.xml
Copy the code

Enter the itracer directory:

Modify execution permission:

Run the program:

$./itracer Springboard (Spingboard is the name of the process to be mounted, supporting simple fuzzy matching)Copy the code

  1. Xcode-windows menu -Organizer-Console = xcode-Windows menu -Organizer-Console
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownloadQueue downloads]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownloadManager downloads]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownloadManager _copyDownloads]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownloadQueue _sendDownloadStatusChangedAtIndex:]: 0
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownloadQueue _messageObserversWithFunction:context:]: 0x334c5d51: 0x2fe89de0
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownloadQueue downloads]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownloadManager downloads]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownloadManager _copyDownloads]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownload cachedApplicationIdentifier]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownload status]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [SSDownload cachedApplicationIdentifier]
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [CPDistributedNotificationCenter postNotificationName:userInfo:]: SBApplicationNotificationStateChanged: {
          SBApplicationStateDisplayIDKey = "com.apple.AppStore";
          SBApplicationStateKey = 2;
          SBApplicationStateProcessIDKey = 5868;
          SBMostElevatedStateForProcessID = 2;
      }
    Jan 21 11:12:58 unknown SpringBoard[5706] : [itrace]: [3edc9d98]: [CPDistributedNotificationCenter postNotificationName:userInfo:toBundleIdentifier:]: SBApplicationNotificationStateChanged: {
          SBApplicationStateDisplayIDKey = "com.apple.AppStore";
          SBApplicationStateKey = 2;
          SBApplicationStateProcessIDKey = 5868;
          SBMostElevatedStateForProcessID = 2;
      }: null
    Jan 21 11:12:59 unknown SpringBoard[5706] : [itrace]: [105d7000]: [SSDownloadManager _handleMessage:fromServerConnection:]: 0xe6920b0: 0xe007040
    Jan 21 11:12:59 unknown SpringBoard[5706] : [itrace]: [105d7000]: [SSDownloadManager _handleDownloadStatesChanged:]: 0xe6920b0
    Jan 21 11:12:59 unknown SpringBoard[5706] : [itrace]: [105d7000]: [SSDownloadManager _copyDownloads]
    Jan 21 11:12:59 unknown SpringBoard[5706] : [itrace]: [105d7000]: [SSDownload persistentIdentifier]
    Jan 21 11:12:59 unknown SpringBoard[5706] : [itrace]: [105d7000]: [SSDownload _addCachedPropertyValues:]: {
          I = SSDownloadPhaseDownloading;
      }
    Jan 21 11:12:59 unknown SpringBoard[5706] : [itrace]: [105d7000]: [SSDownload _applyPhase:toStatus:]: SSDownloadPhaseDownloading: 
    Jan 21 11:12:59 unknown SpringBoard[5706] : [itrace]: [105d7000]: [SSDownloadQueue downloadManager:downloadStatesDidChange:]: : (
          ": -4085275246093726486"
      )
Copy the code

From the above log, you can see that many of the parameters of the call pass data information, of course, there are still many defects and limitations

For example: can’t get a return value, can’t trace too many classes (more than a few hundred, otherwise it might be unstable)

If you are interested in this, you can modify the code, help me optimize ha, ha.

Finally, I’ll talk briefly about some of itRace’s features:

  • Batch trace all invocation flows of a specified class object in ios
  • Supports ios for ARMv6, ARMV7, ARM64 and MAC for x86, X64
  • Automatically probes parameter types and prints details for all parameters
  • Added support for ARM64, just tunable stability to be tested. There is no time to do the arm64 process injection, the substrate hookprocess is currently used, so you need to install libsubstrate first. Dylib armV7 version is completely substrate independent.
  • The ARM64 version has slightly improved the printing of parameter information.

The runtime interface method_getTypeEncoding is used to get the prototype of the parameters in each method called, and then parse it to get the actual number of parameters and the type information of each parameter. For targeted printing output.

Specifically how to deal with, here is not to say, interested students can look at the source code.

If you want to compile this project, which is also based on Xmake and is already indexed by Homebrew, you just need to execute:

$ sudo brew install xmake
$ xmake
Copy the code

It will compile. 🙂

Related articles

  • Xmake V2.0.4 released!
  • Xmake supports vs2002- VS2015 project file generation