本帖最后由 zhangdexi 于 2024-03-17 22:24 编辑
关于AnyGo for Mac是一款专门设计用于iOS设备的虚拟定位软件。 通过连接到Mac,用户可以轻松地修改iPhone或iPad上的GPS位置,无需越狱。 环境/软件分析打开软件后有一个检测是否国区, 如果是则直接退出 目录全局搜索,匹配到以下资源文件 "%@ is not served in current region." = "%@不在该地区服务";
之后在 hopper 中搜索 is not served in current region, 得到下图的引用; 0000000100088e18 db "%@ is not served in current region.", 0
调用类objc_cls_ref_GlobalFunction的俩个方法 isForTest 与 isInChina , 来判断是否弹框, 然后退出; 这里我们不用管 isForTest, 大概率是软件作者测试用的, 由于是 isInChina objc 的原生方法, 可用 method_exchangeImplementations 来交换方法, 替换成我们自己的, 来达到 hook 的目的; method_exchangeImplementations 是 Objective-C 中的一个函数,它允许你交换一个类中两个方法的实现。 这在方法混合(method swizzling)中非常有用,方法混合是一种在运行时对方法实现进行操作的技术,通常用于调试或在不使用子类化的情况下扩展现有类的功能。
+ (int)hk_isInChina { NSLog(@">>>>>> Swizzled hk_isInChina method called"); NSLog(@">>>>>> self.className : %@", self.className); return 0; }
[MemoryUtils hookClassMethod: objc_getClass("GlobalFunction") originalSelector:NSSelectorFromString(@"isInChina") swizzledClass:[self class] swizzledSelector:@selector(hk_isInChina) ];
之后打补丁,dylib 注入,重启 APP; 此刻 APP 可以正常打开了, 然后我们尝试连接手机修改位置;提示要购买; 根据提示全局搜素资源文件, 匹配到以下资源文件 "You are using the trial version. Please buy the full version to remove the limitations." = "您正在使用试用版。请购买完整版本以解除限制。";
之后在 hopper 中搜索 buy the full version to remove the limitations; 定位到了函数 / home.php?mod=space&uid=341152 RegisterLimitWinCtr / -(void)awakeFromNib 之后, 便查不到引用了; 我们在函数 awakeFromNib 下一个断点; 然后重启 APP, 让程序断下来,之后查看 堆栈 (通常只看主程序领空下的); 将这几个程序领空的栈帧地址挨个在 hopper 中打开分析; 看到#8堆栈里有一个关键函数; /* @class MapViewCtr */ -(int)setAllowOperation:(int)arg2 { var_50 = arg0; r13 = [arg2 retain]; rax = [RegisterManager shareManager]; rax = [rax retain]; r14 = [rax isRegistered]; [rax release]; rax = [r13 objectForKey:@"pathType"]; rax = [rax retain]; var_40 = [rax intValue]; [rax release]; var_48 = r13; if (r14 != 0x0) {
}else { // 弹框 }
r14 = [[RegisterManager shareManager]] isRegistered 这里我们只需要让 r14 也就是 isRegistered 返回 true 即可跳过弹框; 与前面一样, 由于是 objc 的原生方法, 直接用 method_exchangeImplementations 机制来 hook - (BOOL)hk_isRegistered { NSLog(@">>>>>> Swizzled hk_isRegistered method called"); return YES; }
[MemoryUtils hookInstanceMethod: objc_getClass("RegisterManager") originalSelector:NSSelectorFromString(@"isRegistered") swizzledClass:[self class] swizzledSelector:@selector(hk_isRegistered) ];
之后打包,dylib 注入, 重启; 启动后,发现试用购买的提示已经没有了, 但是修改手机位置的时候还是报错; 全局扫描资源文件: "You have exceeded the number of allowed installations." = "您已超出设备台数限制。"; 000000010009a2a1 db "You have exceeded the number of allowed installations."
查看引用;发现有三个地方;把这三个地方全部下断点;然后连接手机修改位置 程序最终在这里断下来了; 麻烦来了, 这里的代码里也没有逻辑判断的地方,而且这个方法查不到引用的地方; 堆栈数据也分析不出来有用的信息; 由于我们上一步断点断在了 ConnectViewCtr, 所以我们直接点类一样的倒数第二个引用进去,切到假码; r12 = [[RegisterManager shareManager] retain]; rax = [r13 device]; rax = [rax retain]; r15 = rax; rax = [rax UDID]; rax = [rax retain]; var_29 = [r12 isOverDevicesLimit:rax]; [rax release]; [r15 release]; [r12 release]; [rbx release]; if (var_29 == 0x0) goto loc_10003a8f1;
看到这一句 r12 isOverDevicesLimit:rax], 顿时豁然开朗, 拉屎都通畅了,不多说,按照前面的姿势,直接 hook; - (BOOL)hk_isOverDevicesLimit { NSLog(@">>>>>> Swizzled hk_isOverDevicesLimit method called"); return NO; }
[MemoryUtils hookInstanceMethod: objc_getClass("RegisterManager") originalSelector:NSSelectorFromString(@"isOverDevicesLimit:") swizzledClass:[self class] swizzledSelector:@selector(hk_isOverDevicesLimit) ];
最后打包,dylib 注入, 重启, 连接手机,改一个 南极洲 看看效果吧;
下方隐藏内容为本帖所有文件或源码下载链接:
游客你好,如果您要查看本帖隐藏链接需要登录才能查看,
请先登录
|