這個是用于瀏覽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