这个是用于浏览mac os app页面布局的利器。
下载地址:
http://www.interface-inspector.com/
软件是收费的,当然也可以破解。作者没有做特别复杂的防逆向手段,这里提供3种破解思路。对于其他类似应用,大家可以举一反三。
1.注入破解
内容如下:
#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));
}
注入之后,发现软件虽然已经授权了,但是却没有办法正常attach应用。
看下系统日志
是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.利用静态patch方式破解
下载app,将Interface Inspector.app/Contents/MacOS/Interface Inspector 这个二进制拖进hopper。
先去掉签名校验
在hopper的搜索框里输入finishL ,找到
我们需要干掉的2个地方就这这2个函数里。
先进void -[SMAppDelegate applicationWillFinishLaunching:]
看下下图圈起来的位置:
就是调用codeSignState 方法,返回值与0x2比较。
jne就是 jump not equal,不等于0x02,就跳往 loc_100024851
loc_100024851 是什么?就是签名不对的错误消息。
接下来就是把这段逻辑干掉,方法很多。可以吧jne改成je,我这里是直接把跳转语句nop掉了。
操作过程:鼠标选中jne loc_100024851这条汇编
hopper上面菜单选择Modify->NOP Region
处理完签名校验,接下来处理Licence
很容易在 -[SMAppDelegate applicationDidFinishLaunching:]:中找到这一段:
调用了:[[SMLicenseManager sharedInstance]isLicensed]
我们只需要改isLicensed 这个方法,让他返回true就行了。
搜索SMLicenseManager这个类,找到isLicensed函数。
选中汇编,修改为 mov rax,0x01,然后把不需要的代码nop掉。
然后选中刚才nop的位置,Modify->Assemble instruction
修改为:
把多出来的4个点也nop掉。
最终
将修改后的可执行文件,导出,替换旧的。如果有弹出框移除签名,点移除。
点击执行替换后的app,成功了!
3,打内存补丁
原理是先注入模块,然后在main函数开始之前,用静态函数搜索内存里的目标位置,把相应的二进制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字节
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