破解InterfaceInspector的3種方法

這個是用于瀏覽mac os app頁面布局的利器。
下載地址:

http://www.interface-inspector.com/

軟件是收費(fèi)的,當(dāng)然也可以破解。作者沒有做特別復(fù)雜的防逆向手段,這里提供3種破解思路。對于其他類似應(yīng)用,大家可以舉一反三。

1.注入破解

內(nèi)容如下:

#import "Main.h"
#import <objc/runtime.h>
#import <objc/message.h>

@implementation NSObject (InterfaceInspectorFramework)
    
#pragma mark - SMLicenseManager
- (BOOL)hook_isLicensed {
    return YES;
}
#pragma mark - NSBundle
- (int)hook_codeSignState {
    return 0x02;
}

@end

static void __attribute__((constructor)) initialize(void) {
    CBHookInstanceMethod(SMLicenseManager, @selector(isLicensed), @selector(hook_isLicensed));
    CBHookInstanceMethod(NSBundle, @selector(codeSignState), @selector(hook_codeSignState));
}

注入之后,發(fā)現(xiàn)軟件雖然已經(jīng)授權(quán)了,但是卻沒有辦法正常attach應(yīng)用。
看下系統(tǒng)日志


是interface-inspector依賴了一個注入庫,注入庫里的一個方法過時了(在mac OS Sierra下)。
具體看這個帖子:

http://www.th7.cn/system/mac/201611/188607.shtml

去github上下載一份源碼編譯一下。

https://github.com/rentzsch/mach_inject

編譯出mach_inject_bundle.framework文件放在/Library/Frameworks/mach_inject_bundle.framework目錄下,替換掉舊的。

好了,再次使用interface-inspector注入app,成功了。

2.利用靜態(tài)patch方式破解

下載app,將Interface Inspector.app/Contents/MacOS/Interface Inspector 這個二進(jìn)制拖進(jìn)hopper。

先去掉簽名校驗(yàn)
在hopper的搜索框里輸入finishL ,找到


我們需要干掉的2個地方就這這2個函數(shù)里。
先進(jìn)void -[SMAppDelegate applicationWillFinishLaunching:]

看下下圖圈起來的位置:


就是調(diào)用codeSignState 方法,返回值與0x2比較。
jne就是 jump not equal,不等于0x02,就跳往 loc_100024851

loc_100024851 是什么?就是簽名不對的錯誤消息。

接下來就是把這段邏輯干掉,方法很多。可以吧jne改成je,我這里是直接把跳轉(zhuǎn)語句nop掉了。
操作過程:鼠標(biāo)選中jne loc_100024851這條匯編

hopper上面菜單選擇Modify->NOP Region

處理完簽名校驗(yàn),接下來處理Licence
很容易在 -[SMAppDelegate applicationDidFinishLaunching:]:中找到這一段:

調(diào)用了:[[SMLicenseManager sharedInstance]isLicensed]
我們只需要改isLicensed 這個方法,讓他返回true就行了。
搜索SMLicenseManager這個類,找到isLicensed函數(shù)。

選中匯編,修改為 mov rax,0x01,然后把不需要的代碼nop掉。



然后選中剛才nop的位置,Modify->Assemble instruction



修改為:

把多出來的4個點(diǎn)也nop掉。


最終

將修改后的可執(zhí)行文件,導(dǎo)出,替換舊的。如果有彈出框移除簽名,點(diǎn)移除。

點(diǎn)擊執(zhí)行替換后的app,成功了!

3,打內(nèi)存補(bǔ)丁

原理是先注入模塊,然后在main函數(shù)開始之前,用靜態(tài)函數(shù)搜索內(nèi)存里的目標(biāo)位置,把相應(yīng)的二進(jìn)制patch掉。
方法如下:

#import <dlfcn.h>
#import <stdlib.h>
#import <string.h>
#import <sys/types.h>
#import <mach-o/dyld.h>
#import <mach-o/loader.h>
#import <mach-o/nlist.h>
#include <sys/sysctl.h>
#include <mach/mach.h>


//patch_mem(g_xxAddr,0x00000000);
static void patch_mem(uintptr_t p,unsigned int data){//patch 8字節(jié)
    int page = getpagesize();
    uintptr_t address = (uintptr_t)(p);
    uintptr_t base = address/page * page;
    mach_port_t self = mach_task_self();
    kern_return_t error;
    if((page - (uintptr_t)(p) - base)<12){
        page *= 2;
    }
    if((error = vm_protect(self,base,page,FALSE ,VM_PROT_READ|VM_PROT_WRITE|VM_PROT_COPY))){
        return;
    }
    
    *(unsigned int *) p = data;
    if((error = vm_protect(self,base,page,FALSE,VM_PROT_READ|VM_PROT_EXECUTE))){
        return;
    }
}

static void __attribute__((constructor)) initialize_mem_patch(void) {
    const struct mach_header *mhp = _dyld_get_image_header(0);
    BOOL is64bit = mhp->magic == MH_MAGIC_64 || mhp->magic == MH_CIGAM_64;
//    uintptr_t module_base_cursor = (uintptr_t)mhp + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
    uintptr_t module_base_cursor = (uintptr_t)mhp;
    if (is64bit) {
        uintptr_t targetCursor = module_base_cursor + 0x2447E;
        patch_mem(targetCursor,0x441f0f66);//將baseModel偏移0x2447E的位置nop掉。
        uintptr_t licenceTarget = module_base_cursor + 0x10fe7b;
        patch_mem(licenceTarget,  0x01c0c748);//mov rax,0x01
    }
}

參考文章:
http://iosre.com/t/mac-app-ui-interface-inspector-reveal-mac/3453
http://www.th7.cn/system/mac/201611/188607.shtml

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容