创建一个工程AntiHookDemo
,页面中有两个按钮btn1
和btn2
:
image.png
对应两个事件:
- (IBAction)btn1Click:(id)sender {
NSLog(@"click btn1");
}
- (IBAction)btn2Click:(id)sender {
NSLog(@"click btn2");
}
FrameWork
动态库)这个时候要使用fishhook
防护,在FrameWork
中写防护代码。基于两点:
Framework
在主工程+ load
执行之前执行+ load
。Framework
也在防护代码之后。创建一个HookManager
Framework
,文件结构下:
image.png
AntiHookManager.h
:
#import <Foundation/Foundation.h>
#import <objc/message.h>
//暴露给外界使用
CF_EXPORT void (*exchange_p)(Method _Nonnull m1, Method _Nonnull m2);
@interface AntiHookManager : NSObject
@end
AntiHookManager.m
:
#import "AntiHookManager.h"
#import "fishhook.h"
@implementation AntiHookManager
+ (void)load {
//基本防护
struct rebinding exchange;
exchange.name = "method_exchangeImplementations";
exchange.replacement = hp_exchange;
exchange.replaced = (void *)&exchange_p;
struct rebinding bds[] = {exchange};
rebind_symbols(bds, 1);
}
//指回原方法
void (*exchange_p)(Method _Nonnull m1, Method _Nonnull m2);
void hp_exchange(Method _Nonnull m1, Method _Nonnull m2) {
//可以在这里进行上报后端等操作
NSLog(@"find Hook");
}
@end
HookManager.h
中导出头文件:
#import <HookManager/AntiHookManager.h>
然后将AntiHookManager.h
放入public Headers
:
image.png
修改主工程的ViewController.m
如下:
#import <HookManager/HookManager.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
exchange_p(class_getInstanceMethod(self.class, @selector(btn2Click:)),class_getInstanceMethod(self.class, @selector(test)));
}
- (void)test {
NSLog(@"self Hook Success");
}
- (IBAction)btn1Click:(id)sender {
NSLog(@"click btn1");
}
- (IBAction)btn2Click:(id)sender {
NSLog(@"click btn2");
}
@end
在工程中Hook
自己的方法,这个时候运行主工程:
AntiHookDemo[1432:149145] click btn1
AntiHookDemo[1432:149145] self Hook Success
btn2
能够被自己正常Hook
。
APP
文件夹以及Payload
文件夹,拷贝AntiHookDemo.app
到APP/Payload
目录,压缩zip -ry AntiHookDemo.ipa Payload/
生成.ipa文件
。appResign.sh
重签名脚本以及yololib
注入工具到根目录。HPHook
注入Framework
。HPHook
代码如下:
#import "HPInject.h"
#import <objc/message.h>
@implementation HPInject
+ (void)load {
method_exchangeImplementations(class_getInstanceMethod(objc_getClass("ViewController"), @selector(btn1Click:)), class_getInstanceMethod(self, @selector(my_click)));
}
- (void)my_click {
NSLog(@"inject Success");
}
@end
编译运行:
AntiHookDemo[1437:149999] find Hook
AntiHookDemo[1437:149999] click btn1
AntiHookDemo[1437:149999] self Hook Success
首先是检测到了Hook
,其次自己内部btn2 hook
成功了,`btn1
hook没有注入成功。到这里暴露给自己用和防止别人
Hook都已经成功了。对于三方库中正常使用到的
Hook可以在防护代码中做逻辑判断可以加白名单等调用回原来的方法。如果自己的库在
image
list最后一个那么三方库其实已经
Hook`完了。
当然只Hook
method_exchangeImplementations
不能完全防护,还需要Hook
class_replaceMethod
以及method_setImplementation
。
这种防护方式破解很容易,一般不这么处理:
1.在Hopper
中可以找到method_exchangeImplementations
,直接在MachO
中修改这个字符串HookManager
中就Hook
不到了(这里会直接crash
,因为viewDidLoad
中调用了exchange_p
,对于有保护逻辑的就可以绕过了,并且method_exchangeImplementations
没法做混淆)
image.png
2.可以很容易定位到防护代码,直接在防护代码之前Hook
,或者将fishhook
中的一些系统函数Hook
也能破解。本质上是不执行防护代码。
MonkeyDev
是逆向开发中一个常用的工具
MonkeyDev。能够帮助我们进行重签名和代码注入。
theos安装 (Cydia Substrate
就是 theos
中的工具)
sudo git clone --recursive https://github.com/theos/theos.git /opt/theos
配置环境变量
#逆向相关配置
#export THEOS=/opt/theos
#写入环境变量
#export PATH=$THEOS/bin:$PATH
运行nic.pl
查看theos
信息。
image.png
`error Cowardly refusing to make a project inside $THEOS
(/opt/theos/)出现这个错误则是
export`配置有问题。
指定Xcode
sudo xcode-select -s /Applications/Xcode.app
安装命令
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-install)"
这里是安装Xcode
插件。安装完成后重启Xcode
在Xcode
中会出现MonkeyDev
对应的功能:
image.png
MonkeyApp
:自动给第三方应用集成Reveal
、Cycript
和注入dylib
的模块,支持调试dylib
和第三方应用,支持Pod
给第三放应用集成SDK
,只需要准备一个砸壳后的ipa
或者app
文件即可。MonkeyPod
:提供了创建Pod的项目。CaptainHook Tweak
:使用CaptainHook
提供的头文件进行OC
函数的Hook
以及属性的获取。Command-line Tool
:可以直接创建运行于越狱设备的命令行工具。Logos Tweak
:使用theos
提供的logify.pl
工具将.xm
文件转成.mm
文件进行编译,集成了CydiaSubstrate
,可以使用MSHookMessageEx
和MSHookFunction
来Hook OC
函数和指定地址。卸载命令
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-uninstall)"
更新命令
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-update)"
错误处理
1.MonkeyDev
安装出现:Types.xcspec not found
添加一个软连接:
sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/PrivatePlugIns/IDEOSXSupportCore.ideplugin/Contents/Resources /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications
https://github.com/AloneMonkey/MonkeyDev/issues/266
创建一个MonkeyDemo
工程:
image.png
工程目录如下:
image.png
在工程目录下有一个TargetApp
目录,直接将微信8.0.2版本拖进去:
image.png
编译运行工程:
image.png
这个时候就重签名成功了。相比用脚本自己跑方便很多,也能避免很多异常。
用MonkeyDemo
注入一下AntiHookDemo
,将AntiHookDemo
编译生成的App
加入MonkeyDemo
的TargetApp
中:
image.png
在MonkeyDemo
工程MonkeyDemoDylib->Logos
目录,.xm
文件可以写OC
、C++
、C
:
image.png
将MonkeyDemoDylib.xm
的type
改为Objective-C++ Preprocessed Source
:
image.png
这里面的默认代码就是Logos
语法:
image.png
将.xm
默认打开方式修改为Xcode
后重启Xcode
就能识别代码了,否则就还是默认文本文件。将默认的代码删除,写Hook
btn1Click
的代码:
#import <UIKit/UIKit.h>
//要hook的类
%hook ViewController
//要hook的方法
- (void)btn1Click:(id)sender {
NSLog(@"Monkey Hook Success");
//调用原来的方法
%orig;
}
%end
直接运行工程后点击btn1
:
AntiHookDemo[9306:5972601] find Hook
AntiHookDemo[9306:5972601] find Hook
AntiHookDemo[9309:5973617] Monkey Hook Success
AntiHookDemo[9350:5987306] click btn1
image.png
这个时候就Hook
成功了,并且检测到了Hook
。这里没有防护住是因为Monkey
中用的是getImp
和setImp
。
对AntiHookManager
做下改进:
AntiHookManager .h
:
#import <Foundation/Foundation.h>
#import <objc/message.h>
//暴露给外界使用
CF_EXPORT void (*exchange_p)(Method _Nonnull m1, Method _Nonnull m2);
CF_EXPORT IMP _Nonnull (*getImp_p)(Method _Nonnull m);
CF_EXPORT IMP _Nonnull(*setImp_p)(Method _Nonnull m, IMP _Nonnull imp);
@interface AntiHookManager : NSObject
@end
AntiHookManager .m
:
#import "AntiHookManager.h"
#import "fishhook.h"
@implementation AntiHookManager
+ (void)load {
//基本防护
struct rebinding exchange;
exchange.name = "method_exchangeImplementations";
exchange.replacement = hp_exchange;
exchange.replaced = (void *)&exchange_p;
struct rebinding setIMP;
setIMP.name = "method_setImplementation";
setIMP.replacement = hp_setImp;
setIMP.replaced = (void *)&setImp_p;
struct rebinding getIMP;
getIMP.name = "method_getImplementation";
getIMP.replacement = hp_getImp;
getIMP.replaced = (void *)&getImp_p;
struct rebinding bds[] = {exchange,setIMP,getIMP};
rebind_symbols(bds, 3);
}
//指回原方法
void (*exchange_p)(Method _Nonnull m1, Method _Nonnull m2);
IMP _Nonnull (*getImp_p)(Method _Nonnull m);
IMP _Nonnull(*setImp_p)(Method _Nonnull m, IMP _Nonnull imp);
void hp_exchange(Method _Nonnull m1, Method _Nonnull m2) {
//可以在这里进行上报后端等操作
NSLog(@"find Hook");
}
void (hp_getImp)(Method _Nonnull m) {
NSLog(@"find Hook getImp");
}
void (hp_setImp)(Method _Nonnull m, IMP _Nonnull imp) {
NSLog(@"find Hook setImp");
}
@end
这个时候控制台输出:
AntiHookDemo[1488:207119] find Hook getImp
AntiHookDemo[1488:207119] find Hook
AntiHookDemo[1488:207119] find Hook getImp
AntiHookDemo[1488:207119] find Hook
AntiHookDemo[1488:207119] click btn1
点击btn1
也没有Hook
到了。在这里运行时有可能Crash
在JSEvaluateScript
的时候,直接删除App
重新跑一次就可以了。
libsubstrate.dylib
解析的,
其实这里.xm
文件是被libsubstrate.dylib
解析成MonkeyDemoDylib.mm
中的内容(.xm
代码是不参与编译的):
image.png
MSHookMessageEx
底层用的是setImp
和getImp
对OC
进行Hook
的。
错误问题
1.`Signing for "MonkeyDemoDylib" requires a development team. Select a
development team in the Signing & Capabilities editor.`
直接在该target
的build settings
中添加CODE_SIGNING_ALLOWED=NO
image.png
https://iosre.com/t/xcode11-monkeydev/17021
2.`Failed to locate Logos Processor. Is Theos installed? If not, see
https://github.com/theos/theos/wiki/Inst allation.`
出现这个错误一般是theos
没有安装好。或者路径配置的有问题。
3.library not found for -libstdc++
需要下载对应的库到XCode
目录中。参考:[https://github.com/longyoung/libstdc.6.0.9-if-help-
you-give-a-
star](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Flongyoung%2Flibstdc.6.0.9-if-
help-you-give-a-star)
4.`The WatchKit app’s Info.plist must have a WKCompanionAppBundleIdentifier
key set to the bundle identifier of the companion app.`
删除DerivedData
重新运行。
5.`This application or a bundle it contains has the same bundle identifier as
this application or another bundle that it contains. Bundle identifiers must
be unique.`
这种情况大概率是手机上之前安装过相同bundleId
的App
安装不同版本导致,需要删除重新安装。还有问题的话删除DerivedData
改bundleId
。
6.`This app contains a WatchKit app with one or more Siri Intents app
extensions that declare IntentsSupported that are not declared in any of the
companion app's Siri Intents app extensions. WatchKit Siri Intents extensions'
IntentsSupported values must be a subset of the companion app's Siri Intents
extensions' IntentsSupported values.`
需要删除com.apple.WatchPlaceholder
(在/opt/MonkeyDev/Tools
目录中修改pack.sh
):
rm -rf "${TARGET_APP_PATH}/com.apple.WatchPlaceholder" || true
然后删除DerivedData
重新运行。
LLVM Profile Error: Failed to write file "default.profraw": Operation not permitted
undefined这个说明App
内部做了反调试防护。直接在Monkey
中开启sysctl
:rebind_symbols((struct rebinding[1]){{"sysctl", my_sysctl, (void*)&orig_sysctl}},1);
8.`Attempted to load Reveal Library twice. Are you trying to load dynamic
library with Reveal Framework already linked?`
直接删除dylib
中Other Linker Flags
的设置即可(可能的原因是手机端已经导入了这个库):
⚠️遇见莫名其妙的错误建议删除DerivedData
重启Xcode
重新运行。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。