iOS逆向之四 FishHook的簡單使用

aron1992發表於2019-04-04

iOS逆向之二-FishHook的簡單使用

FishHook用於hook C函式,是Facebook提供的一個動態修改連結mach-O檔案的工具,專案地址:fishhook

官方例子

一個官方的小例子:
用於監控某個程式的檔案的讀寫事件,相當於hook C語言的open/close函式,OC底層是使用C語言實現的,所以hook C語言的open/close函式 可以達到監控程式的檔案操作情況。

#import <dlfcn.h>

#import <UIKit/UIKit.h>

#import "AppDelegate.h"
#import "fishhook.h"

// 定義函式的指標變數,使用者儲存原來的函式指標(函式其實也是一個地址)
static int (*orig_close)(int);
static int (*orig_open)(const char *, int, ...);

// 自定義的close函式
int my_close(int fd) {
  printf("Calling real close(%d)\n", fd);
  return orig_close(fd);
}
 
// 自定義的open函式
int my_open(const char *path, int oflag, ...) {
  va_list ap = {0};
  mode_t mode = 0;
 
  if ((oflag & O_CREAT) != 0) {
    // mode only applies to O_CREAT
    va_start(ap, oflag);
    mode = va_arg(ap, int);
    va_end(ap);
    printf("Calling real open('%s', %d, %d)\n", path, oflag, mode);
    return orig_open(path, oflag, mode);
  } else {
    printf("Calling real open('%s', %d)\n", path, oflag);
    return orig_open(path, oflag, mode);
  }
}
 
int main(int argc, char * argv[])
{
    @autoreleasepool {
        
        // rebind_symbols((struct rebinding[2]){{"close", my_close, (void *)&orig_close}, {"open", my_open, (void *)&orig_open}}, 2);
        // 轉換為:=====>
        
        struct rebinding binds[2];
        // orig_close是一個函式指標,(void *)&orig_close 是一個返回引數,所以用取地址,(void *)&orig_open也是類似的
        struct rebinding bind1 = {"close", my_close, (void *)&orig_close};
        binds[0] = bind1;
        binds[1] = (struct rebinding){"open", my_open, (void *)&orig_open};
        rebind_symbols(binds, 2);
        
        // Open our own binary and print out first 4 bytes (which is the same
        // for all Mach-O binaries on a given architecture)
        int fd = open(argv[0], O_RDONLY);
        uint32_t magic_number = 0;
        read(fd, &magic_number, 4);
        printf("Mach-O Magic Number: %x \n", magic_number);
        close(fd);
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
複製程式碼

執行專案,可以看到以下的日誌,這是一個iOS專案,這些日誌記錄了一個簡單的IOS專案執行檔案的操作記錄。

Calling real open('/Users/aron/Library/Developer/CoreSimulator/Devices/51EAB81B-E4BF-4A9A-A007-CEA9A9A3278F/data/Containers/Bundle/Application/32081135-98DF-415D-AFEB-C87E7B584F6C/FishHookDemo.app/FishHookDemo', 0)
Mach-O Magic Number: feedfacf 
Calling real close(3)
Calling real open('/Users/aron/Library/Developer/CoreSimulator/Devices/51EAB81B-E4BF-4A9A-A007-CEA9A9A3278F/data/Containers/Bundle/Application/32081135-98DF-415D-AFEB-C87E7B584F6C/FishHookDemo.app/Info.plist', 0)
Calling real close(3)
Calling real open('/Users/aron/Library/Developer/CoreSimulator/Devices/51EAB81B-E4BF-4A9A-A007-CEA9A9A3278F/data/Containers/Bundle/Application/32081135-98DF-415D-AFEB-C87E7B584F6C/FishHookDemo.app/FishHookDemo', 0)
Calling real close(3)
Calling real open('/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/ColorSync/Profiles/sRGB Profile.icc', 0)
Calling real close(5)
Calling real open('/Users/aron/Library/Developer/CoreSimulator/Devices/51EAB81B-E4BF-4A9A-A007-CEA9A9A3278F/data/Containers/Bundle/Application/32081135-98DF-415D-AFEB-C87E7B584F6C/FishHookDemo.app/FishHookDemo', 0)
Calling real close(5)
...
複製程式碼

Tweak外掛上使用FishHook

可以把這段程式碼移植到tweak外掛上,xm檔案支援logos/c/c++/OC語法,所以移植的過程很方便。下面的例子展示的是把這段程式碼注入到 今日頭條 中,使用class-dump查詢 今日頭條 的入口類是 AppDelegate ,所以把這段程式碼注入到 - (BOOL)application:(id)arg1 didFinishLaunchingWithOptions:(id)arg2 方法中就行了。

tweak.xm 原始檔:

#include "fishhook.h"
#import <dlfcn.h>


static int (*orig_close)(int);
static int (*orig_open)(const char *, int, ...);

int my_close(int fd) {
    NSLog(@"Calling real close(%d)\n", fd);
    return orig_close(fd);
}

int my_open(const char *path, int oflag, ...) {
    va_list ap = {0};
    mode_t mode = 0;
    
    if ((oflag & O_CREAT) != 0) {
        // mode only applies to O_CREAT
        va_start(ap, oflag);
        mode = va_arg(ap, int);
        va_end(ap);
        NSLog(@"Calling real open('%s', %d, %d)\n", path, oflag, mode);
        return orig_open(path, oflag, mode);
    } else {
        NSLog(@"Calling real open('%s', %d)\n", path, oflag);
        return orig_open(path, oflag, mode);
    }
}


%hook AppDelegate
- (BOOL)application:(id)arg1 didFinishLaunchingWithOptions:(id)arg2 {

    // fishfook use
    struct rebinding binds[2];
    // orig_close是一個函式指標,(void *)&orig_close 是一個返回引數,所以用取地址,(void *)&orig_open也是類似的
    struct rebinding bind1 = {"close", (void *)my_close, (void **)&orig_close};
    binds[0] = bind1;
    binds[1] = (struct rebinding){"open", (void *)my_open, (void **)&orig_open};

    // rebind_symbols((struct rebinding[2]){{"close", my_close, (void *)&orig_close}, {"open", my_open, (void *)&orig_open}}, 2);
    // 轉換為:
    rebind_symbols(binds, 2);

    return %orig; 
}

%end
複製程式碼

對應的make檔案,注意需要引入FishHook的原始檔fishhook.c


#編譯debug或者release
DEBUG = 0
    
#越獄iPhone的ip地址
# 需要新增到環境變數中才能生效,命令: "export THEOS_DEVICE_IP=192.168.8.220"
#THEOS_DEVICE_IP = 192.168.1.122
THEOS_DEVICE_IP = 192.168.8.215

#指定支援的處理器架構
ARCHS = armv7 arm64

#指定需要的SDK版本iphone:Base SDK:Deployment Target
#最新的SDK,程式釋出在iOS8.0以上
TARGET = iphone:latest:8.0

include /opt/theos/makefiles/common.mk

TWEAK_NAME = TouTiaoNewsTweak
TouTiaoNewsTweak_FILES = Tweak.xm fishhook.c

include $(THEOS_MAKE_PATH)/tweak.mk

#make clean
clean::
	rm -rf ./packages/*

after-install::
	install.exec "killall -9 News"
複製程式碼

啟動 今日頭條 App,可以監控到該程式的所有的檔案操作記錄

Sep  4 21:00:41 iPhone News[1366]: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Sep  4 21:00:41 iPhone News[1366]: Calling real open('/var/mobile/Containers/Data/Application/9462F701-C44A-49BF-83AF-335EDCC9F6B0/Library/Caches/LauchProcess/launchPatch.js', 0)
Sep  4 21:00:41 iPhone News[1366]: Calling real open('/var/mobile/Containers/Data/Application/9462F701-C44A-49BF-83AF-335EDCC9F6B0/Library/Caches/LauchProcess/activePatch.js', 0)
Sep  4 21:00:41 iPhone News[1366]: Calling real open('/var/mobile/Containers/Data/Application/9462F701-C44A-49BF-83AF-335EDCC9F6B0/Library/Application Support/com.crashlytics/CLSUserDefaults.plist', 0)
Sep  4 21:00:41 iPhone News[1366]: Calling real close(4)
Sep  4 21:00:41 iPhone News[1366]: Calling real open('/var/mobile/Containers/Bundle/Application/7891D858-95FA-4EFF-A1BA-83DCC8099FB6/News.app/News', 0)
Sep  4 21:00:41 iPhone News[1366]: Calling real close(4)
Sep  4 21:00:41 iPhone News[1366]: Calling real open('/var/mobile/Containers/Bundle/Application/7891D858-95FA-4EFF-A1BA-83DCC8099FB6/News.app/AppIcon-News60x60@2x~ipad.png', 0)
複製程式碼

總結

FishHook實現的程式檔案監控只是一個FishHook一個簡單例子,還可以監控程式的其他操作,可以作為逆向的另一個切入點。

相關文章