3

I'm trying to reverse a compiled tweak. As a first step, I want to find out all the functions it hooks. I can find all the calls to substrate framework functions, but I didn't figure out which functions are hooked (r0). What is the best way to do this?

  1. How can I start an app using gdb instead of attaching to a running process. The straightforward way results in a SIGABRT and the call stacks look something like

    #0  0x39ee91f0 in __pthread_kill ()
    #1  0x39f53796 in pthread_kill ()
    #2  0x39e99fdc in abort ()
    #3  0x33bdec10 in GSRegisterPurpleNamedPort ()
    #4  0x33bde890 in _GSEventInitialize ()
    #5  0x31604f38 in UIApplicationMain ()
    #6  0x0022d97c in ?? ()
    #7  0x000910c8 in ?? ()
    
  2. I tried to write a tweak to hook into the substrate framework functions, e.g. MSHookFunction.

    #include <CydiaSubstrate.h>
    
    void (*oldMSHookFunction)(void *, void *, void **);
    
    void newMSHookFunction(void *symbol, void *hook, void **old) {
        printf("CC_HOOKED\n");
        oldMSHookFunction(symbol, hook, old); 
     }
    
    __attribute__((constructor)) static void initialize() {
        NSLog(@"CC_LOADED");
        MSHookFunction(MSHookFunction, &newMSHookFunction, &oldMSHookFunction);
     }
    

With syslog, I found that my tweak is successfully loaded with CC_LOADED printed and there were other tweaks loaded after mine. However, no CC_HOOKED is printed out. What happened ?

perror
  • 19,083
  • 29
  • 87
  • 150
c c
  • 141
  • 1
  • 5
  • The second way hooks successfully. printf doesn't print to syslog. Still don't know how to fix the first way. – c c Sep 01 '14 at 21:55

2 Answers2

1
#include "substrate.h"
#include <dlfcn.h>

void resolveSymbol(const void *addr) {
    Dl_info info;
    if (dladdr(addr, &info)) {
        NSLog(@"<hooksubstrate> Resolved symbol at address %p: dli_fname %s, dli_fbase %p, dli_sname %s, dli_saddr %p", addr, info.dli_fname, info.dli_fbase, info.dli_sname, info.dli_saddr);
    }
    else {
        NSLog(@"<hooksubstrate> Can't resolve symbol at address %p", addr);
    }
}

void (*oldMSHookFunction)(void *, void *, void **);

void newMSHookFunction(void *symbol, void *hook, void **old) {
    NSLog(@"<hooksubstrate> MSHookFunction: symbol %p, new %p, old %p", symbol, hook, old);
    resolveSymbol(symbol);
    resolveSymbol(hook);
    resolveSymbol(old);
    oldMSHookFunction(symbol, hook, old);
}

void (*oldMSHookMessageEx)(Class, SEL, IMP, IMP *);

void newMSHookMessageEx(Class c/*lass*/, SEL s/*elector*/, IMP replacement, IMP *result) {
    NSLog(@"<hooksubstrate> MSHookMessageEx: class %@, selector %@, new %p, old %p", NSStringFromClass(c/*lass*/), NSStringFromSelector(s/*elector*/), replacement, result);
    resolveSymbol((const void *) *replacement);
    resolveSymbol((const void *) result);
    oldMSHookMessageEx(c/*lass*/, s/*elector*/, replacement, result);
}

__attribute__((constructor))
static void initialize() {
    MSHookFunction(MSHookMessageEx, &newMSHookMessageEx, &oldMSHookMessageEx);
    MSHookFunction(MSHookFunction, &newMSHookFunction, &oldMSHookFunction);
    NSLog(@"<hooksubstrate> Hooked into MSHookFunction & MSHookMessageEx");
}

With sample output (for an old version)

> cat /dev/null > /var/log/syslog
> cat /var/log/syslog | grep "Loading"
Sep 12 17:06:54 iPad Clash of Clans[2372]: MS:Notice: Loading: /Library/MobileSubstrate/DynamicLibraries/HookSubstrate.dylib
Sep 12 17:06:54 iPad Clash of Clans[2372]: MS:Notice: Loading: /Library/MobileSubstrate/DynamicLibraries/xxCOCPlugin.dylib
> cat /var/log/syslog | grep "<cc>"
Sep 12 17:06:54 iPad Clash of Clans[2372]: <cc> Hooked into MSHookFunction & MSHookMessageEx
Sep 12 17:06:54 iPad Clash of Clans[2372]: <cc> MSHookFunction: old 0x845fd, new 0x3af4fd
Sep 12 17:06:54 iPad Clash of Clans[2372]: <cc> Resolved symbol at address 0x845fd: dli_fname /var/mobile/Applications/1A631C27-CE93-4845-B7FB-0637D600E10C/Clash of Clans.app/Clash of Clans, dli_fbase 0x4000, dli_sname (null), dli_saddr 0x0
Sep 12 17:06:54 iPad Clash of Clans[2372]: <cc> Resolved symbol at address 0x3af4fd: dli_fname /Library/MobileSubstrate/DynamicLibraries/xxCOCPlugin.dylib, dli_fbase 0x3a7000, dli_sname _Z20func_hook_new_searchi, dli_saddr 0x3af4fd
Sep 12 17:06:54 iPad Clash of Clans[2372]: <cc> MSHookMessageEx: class AppController, selector application:didFinishLaunchingWithOptions:, new 0x3afdb5
Sep 12 17:06:54 iPad Clash of Clans[2372]: <cc> Resolved symbol at address 0x3afdb5: dli_fname /Library/MobileSubstrate/DynamicLibraries/xxCOCPlugin.dylib, dli_fbase 0x3a7000, dli_sname _Z60hook_AppController_application_didFinishLaunchingWithOptionsP11objc_objectP13objc_selectorS0_S0_, dli_saddr 0x3afdb5
c c
  • 141
  • 1
  • 5
  • I find that MSHookFunction sets it's symbol pointer to NULL if it's trying to hook its own address, and forces a crash. Is this a recent safety feature? – GroovyCarrot Apr 12 '15 at 10:17
0

You can find all the hooked Objective C methods in a tweak by first doing a cross reference of _MSHookMessageEx in IDA Pro. In the functions which call _MSHookMessageEx, the method name can be seen loaded into R1, just before the call to _MSHookMessageEx.

To launch an app with gdb, use debugserver. It acts as an endpoint for remote gdb or lldb on iOS. You can find more information about debugserver on this page - http://iphonedevwiki.net/index.php/Debugserver

Also, I would recommend using Theos (http://iphonedevwiki.net/index.php/Theos) to do the function hooking. It makes development of MobileSubtrate tweaks a lot easier.

Judging by your question, I seem to get the idea that you're trying to hook MobileSubtrate's own functions like MSHookFunction. MobileSubstrate is only designed to hook other functions and not itself.

REnoob
  • 56
  • 1
  • 1
    Thanks for your answer. The cool thing about MobileSubstrate is it can hook everything, including MSHookFunction. The problem of the original code is that I should use NSLog instead of printf, and everything else works just fine. – c c Sep 28 '14 at 01:53