> 文章列表 > 16、CycriptLogos

16、CycriptLogos

16、CycriptLogos

一、Cycript

  • Cycript是由Cydia创始人Saurik推出的一款脚本语言,Cycript混合了OC、JavaScript语法的解释器,这意味着我们能够在一个命令中使用OC或者JavaScript,甚至两者并用.它能够挂钩正在运行的进程,能够在运行时修改很多东西.
    • 官网下载/ MonkeyDev自动配置下载
    • 是一种脚本语言,混合了多种语法.(混合了多种语法的解释器),所以可以兼容
    • Cycript可以附加到进程,动态调试应用的

1.1 安装

  • 下载后使用Cycript可执行文件、MonkeyDev安装成功后可不用配置.bash_profile/.zshrc路径,因为MonkeyDev中有

1.2 基本使用

  • cy文件
    • Cycript是一门脚本语言,它可以加载封装好的.cy文件
    • 将常用的Cycript功能封装到.cy文件中,便于调试
    • 非越狱设备,导入.cy文件
      • 利用MonkeyDev工具导入.cy文件
      • MonkeyDev本身集成了Cycript.我们只需要将.cy文件,通过Xcode导入Frameworks目录即可
    • 进入Cycript环境
$ cycript
cy#
    • 退出环境: control +d
  • MonkeyDev中集成了Cycript,使用MonkeyDev重签名应用,会自动注入libcycript.dylib相关文件
  • 当Cycript注入到目标应用,应用进程就会调用Cycript的方法,开启相应的端口,以供第三方监听
  • 第三方可通过端口链接进程,进入cy环境,HOOK当前进程中的内存数据

1.3 使用实战

  • 附加进程
    • 使用MonkeyDev的Demo安装并运行wx8.0.2.ipa
    • 让手机与Mac处于同一网络环境,来到终端,使用设备ip+端口号(默认6666)附加进程
    • 未链接成功时:
      • cyConnect.sh脚本中代码: cycript -r 192.168.124.12:6666
sh cyConnect.sh
*** _syscall(connect(socket_, info->ai_addr, info->ai_addrlen)):/Users/monkey/Documents/Cycript_Project/src/Console.cpp(306):CYSocketRemote [errno=61]
    • 如下显示则表明附加成功
$ cycript -r 192.168.124.12:6666
cy# 
  • 获取keyWindow
cy# UIWindow.keyWindow()
#"<iConsoleWindow: 0x111760ba0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x28347a1f0>; layer = <UIWindowLayer: 0x283b5ed20>>"
  • 获取UIApplication单例对象
cy# UIApp
#"<UIApplication: 0x1117241e0>"
  • 设置当前附加程序App角标数量
cy# [UIApp setApplicationBadgeString: @"999"]
  • 退出后台、设置完当前代码后、可以看到角标数量

  • 但是回到前台时,该角标就会清零,因为修改的是内存中的代码.
  • 再比如修改聊天界面上一个人的名字: “Gray皓白”

    • 通过Cycript链接着运行中的App、
    • 搜索当前界面的UILabel、然后根据关键字“Gray”找到这个label对象地址0x122907c40.
    • 将text内容改为Gray
cy# choose(UILabel)
[#"<MMUILabel: 0x121253a10; baseClass = UILabel; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x28075f930>>",#"<MMUILabel: 0x12126eba0; baseClass = UILabel; frame = (0 0; 0 0); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280747480>>",#"<MMUILabel: 0x121270a50; baseClass = UILabel; frame = (0 0; 0 0); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280747660>>",#"<MMUILabel: 0x121272900; baseClass = UILabel; frame = (0 0; 0 0); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280747700>>",#"<MMUILabel: 0x1212747b0; baseClass = UILabel; frame = (0 0; 0 0); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280744730>>",#"<MMCPLabel: 0x1212b5e50; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280730cd0>>",#"<MMUILabel: 0x1212eb8f0; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807845a0>>",#"<MMUILabel: 0x1212f97e0; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280784c80>>",#"<MMUILabel: 0x110c4bce0; baseClass = UILabel; frame = (-22.6667 7.33333; 67 21); text = '\\xe6\\x94\\xb6\\xe5\\x8f\\x96\\xe4\\xb8\\xad\\xe2\\x80\\xa6'; hidden = YES; userInteractionEnabled = NO; tag = 102; layer = <_UILabelLayer: 0x2804feb20>>",#"<MMUILabel: 0x110c86ea0; baseClass = UILabel; frame = (11 7.5; 8 15); text = '7'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280483ac0>>",#"<MMUILabel: 0x110c89200; baseClass = UILabel; frame = (0 0; 0 0); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804ac320>>",#"<MMUILabel: 0x110c8adb0; baseClass = UILabel; frame = (10.5 7.5; 9 15); text = '4'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804ac5f0>>",#"<MMCPLabel: 0x110ccf970; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe5\\xa4\\xa9\\xe6\\xb4\\xa5-\\xe5\\x88\\x98\\xe6\\xb4\\xaa\\xe6\\xb6\\x9b'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807659f0>>",#"<MMUILabel: 0x110cecf00; baseClass = UILabel; frame = (184.667 40; 69 17); text = '\\xe6\\xad\\xa3\\xe5\\x9c\\xa8\\xe5\\x8a\\xa0\\xe8\\xbd\\xbd\\xe2\\x80\\xa6'; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804f16d0>>",#"<MMCPLabel: 0x123107700; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe5\\xa4\\xa9\\xe6\\xb4\\xa5-\\xe5\\x88\\x98\\xe6\\xb4\\xaa\\xe6\\xb6\\x9b'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280730230>>",#"<MMCPLabel: 0x123108910; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280731cc0>>",#"<MMCPLabel: 0x12310d440; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe7\\xad\\x94\\xe7\\x96\\x91\\xe2\\x80\\x94jz'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280730460>>",#"<MMCPLabel: 0x12310e650; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280730f00>>",#"<MMUILabel: 0x12318f140; baseClass = UILabel; frame = (-38 1.33333; 35 21); text = '\\xe5\\xba\\x95\\xe5\\xb1\\x82'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280732990>>",#"<MMUILabel: 0x12318f430; baseClass = UILabel; frame = (-33.3333 22.3333; 67 12); text = '\\xe5\\xa4\\xa7\\xe5\\xb8\\x88\\xe7\\x8f\\xad\\xe4\\xb8\\x89\\xe6\\x9c\\x9f1\\xe7\\xbe\\xa4'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280732c10>>",#"<MMCPLabel: 0x1231b1030; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe7\\xad\\x94\\xe7\\x96\\x91\\xe2\\x80\\x94jz'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280731d60>>",#"<MMUILabel: 0x1231b8b30; baseClass = UILabel; frame = (0 0; 41 21); text = '(313)'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807329e0>>",#"<MMCPLabel: 0x122907640; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe5\\xa4\\xa9\\xe6\\xb4\\xa5-\\xe5\\x88\\x98\\xe6\\xb4\\xaa\\xe6\\xb6\\x9b'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280795630>>",#"<MMCPLabel: 0x122907c40; baseClass = UILabel; frame = (65 0; 200 16); text = 'Gray\\xe7\\x9a\\x93\\xe7\\x99\\xbd'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280794be0>>",#"<MMCPLabel: 0x122908240; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280794d70>>",#"<MMUILabel: 0x122913840; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807b9860>>",#"<MMCPLabel: 0x122918230; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe7\\xad\\x94\\xe7\\x96\\x91\\xe2\\x80\\x94jz'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280794410>>",#"<MMUILabel: 0x12292fd00; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807b9220>>",#"<MMCPLabel: 0x122933120; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe7\\xad\\x94\\xe7\\x96\\x91\\xe2\\x80\\x94jz'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280794690>>",#"<MMCPLabel: 0x122938770; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280794910>>",#"<MMUILabel: 0x12295b160; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807b3d40>>",#"<MMCPLabel: 0x12295fc50; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807957c0>>",#"<MMUILabel: 0x1229780a0; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280760000>>",#"<MMUILabel: 0x12297a0c0; baseClass = UILabel; frame = (0 0; 0 0); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280797ca0>>",#"<MMUILabel: 0x12297d350; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807605f0>>",#"<MMUILabel: 0x122981cb0; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280760af0>>",#"<MMUILabel: 0x1229868a0; baseClass = UILabel; frame = (56 48; 0 0); clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280760e60>>",#"<MMCPLabel: 0x1229b1360; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe5\\xa4\\xa9\\xe6\\xb4\\xa5-\\xe5\\x88\\x98\\xe6\\xb4\\xaa\\xe6\\xb6\\x9b'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280764320>>",#"<MMCPLabel: 0x1229b2570; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280764a00>>",#"<MMUILabel: 0x12116cb60; baseClass = UILabel; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x28048e990>>",#"<MMUILabel: 0x12118f9b0; baseClass = UILabel; frame = (0 0; 0 36); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280747f20>>",#"<MMUILabel: 0x12119c430; baseClass = UILabel; frame = (-19 7.33333; 35 21); text = '\\xe5\\xbe\\xae\\xe4\\xbf\\xa1'; userInteractionEnabled = NO; tag = 104; layer = <_UILabelLayer: 0x2807b0820>>",#"<MMUILabel: 0x12119cfa0; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807b8a00>>",#"<MMUILabel: 0x1211a6970; baseClass = UILabel; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807b1130>>",#"<MMCPLabel: 0x1211b81f0; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807660d0>>",#"<MMUILabel: 0x1211d9090; baseClass = UILabel; frame = (12 4; 60 32); text = '\\xe4\\xbd\\xa0\\xe5\\x8f\\xaf\\xe8\\x83\\xbd\\xe8\\xa6\\x81\\xe5\\x8f\\x91\\xe9\\x80\\x81\\xe7\\x9a\\x84\\xe7\\x85\\xa7\\xe7\\x89\\x87:'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280720c80>>",#"<MMCPLabel: 0x1211dad90; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280795090>>",#"<MMUILabel: 0x110d479a0; baseClass = UILabel; frame = (0 -1; 1 20); text = '\\xe5\\xbe\\xae\\xe4\\xbf\\xa1(\\xe6\\x9c\\xaa\\xe8\\xbf\\x9e\\xe6\\x8e\\xa5)'; hidden = YES; userInteractionEnabled = NO; tag = 103; layer = <_UILabelLayer: 0x2804fc140>>",#"<MMUILabel: 0x110d68980; baseClass = UILabel; frame = (-17 0; 35 36); text = '\\xe5\\xbe\\xae\\xe4\\xbf\\xa1'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804ab2f0>>",#"<MMUILabel: 0x110d76ed0; baseClass = UILabel; frame = (0 0; 0 0); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804b7980>>",#"<MMUILabel: 0x110d8bf20; baseClass = UILabel; frame = (-19 7.33333; 35 21); text = '\\xe5\\xbe\\xae\\xe4\\xbf\\xa1'; userInteractionEnabled = NO; tag = 104; layer = <_UILabelLayer: 0x2804fc320>>",#"<MMUILabel: 0x110dab3a0; baseClass = UILabel; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x28075d9a0>>",#"<MMUILabel: 0x110dce470; baseClass = UILabel; frame = (180.667 796; 53 15); text = '\\xe6\\x8c\\x89\\xe4\\xbd\\x8f \\xe8\\xaf\\xb4\\xe8\\xaf\\x9d'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804ff110>>",#"<MMUILabel: 0x110dcfde0; baseClass = UILabel; frame = (176 30; 62 18); text = '\\xe5\\x8a\\xa0\\xe8\\xbd\\xbd\\xe6\\x9b\\xb4\\xe5\\xa4\\x9a'; autoresize = W; userInteractionEnabled = NO; tag = 1680; layer = <_UILabelLayer: 0x2804ff340>>",#"<MMUILabel: 0x110dd7930; baseClass = UILabel; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804fd590>>",#"<MMUILabel: 0x110dda360; baseClass = UILabel; frame = (0 0; 0 36); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804ff890>>",#"<MMUILabel: 0x110deb860; baseClass = UILabel; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2807768f0>>",#"<MMUILabel: 0x122a00710; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280785720>>",#"<MMUILabel: 0x122a2c940; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280784870>>",#"<MMUILabel: 0x122a430f0; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280784c30>>",#"<MMUILabel: 0x122a43830; baseClass = UILabel; frame = (56 48; 0 0); text = ''; clipsToBounds = YES; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280785090>>",#"<MMUILabel: 0x122a99eb0; baseClass = UILabel; frame = (24 -1; 90 36); text = '\\xe8\\xbf\\x9e\\xe6\\x8e\\xa5\\xe4\\xb8\\xad\\xe2\\x80\\xa6'; hidden = YES; userInteractionEnabled = NO; tag = 102; layer = <_UILabelLayer: 0x2807bd7c0>>",#"<MMUILabel: 0x122a9b040; baseClass = UILabel; frame = (0 -1; 1 20); text = '\\xe5\\xbe\\xae\\xe4\\xbf\\xa1(\\xe6\\x9c\\xaa\\xe8\\xbf\\x9e\\xe6\\x8e\\xa5)'; hidden = YES; userInteractionEnabled = NO; tag = 103; layer = <_UILabelLayer: 0x2807bd860>>",#"<MMUILabel: 0x122ab0ba0; baseClass = UILabel; frame = (0 0; 0 0); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280796580>>",#"<MMUILabel: 0x122ab6c70; baseClass = UILabel; frame = (184 12; 46 20); text = '17:40'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280796df0>>",#"<MMCPLabel: 0x122abc110; baseClass = UILabel; frame = (65 0; 200 16); text = '\\xe7\\xad\\x94\\xe7\\x96\\x91\\xe2\\x80\\x94jz'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280764500>>",#"<MMCPLabel: 0x127310960; baseClass = UILabel; frame = (269 0; 414 16); hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2804d5090>>",#"<RichTextView: 0x1123eba00; baseClass = UILabel; frame = (12 10; 104 21); opaque = NO; layer = <YYAsyncLayer: 0x2837f1fb0>>",#"<RichTextView: 0x1125b8000; baseClass = UILabel; frame = (12 10; 21 21); opaque = NO; layer = <YYAsyncLayer: 0x2837f7570>>",#"<RichTextView: 0x112641c00; baseClass = UILabel; frame = (12 10; 70 21); opaque = NO; layer = <YYAsyncLayer: 0x283769590>>",#"<RichTextView: 0x112673a00; baseClass = UILabel; frame = (12 10; 161 21); opaque = NO; layer = <YYAsyncLayer: 0x283768510>>",#"<RichTextView: 0x112680600; baseClass = UILabel; frame = (12 10; 87 21); opaque = NO; layer = <YYAsyncLayer: 0x28376a6a0>>",#"<RichTextView: 0x111373800; baseClass = UILabel; frame = (12 10; 79 21); opaque = NO; layer = <YYAsyncLayer: 0x2837bcd20>>",#"<RichTextView: 0x1113f4600; baseClass = UILabel; frame = (12 10; 171 21); opaque = NO; layer = <YYAsyncLayer: 0x28376d860>>",#"<RichTextView: 0x1115d5200; baseClass = UILabel; frame = (12 10; 70 21); opaque = NO; layer = <YYAsyncLayer: 0x28376e310>>",#"<RichTextView: 0x11171dc00; baseClass = UILabel; frame = (12 10; 40 21); opaque = NO; layer = <YYAsyncLayer: 0x28376f300>>",#"<RichTextView: 0x111763c00; baseClass = UILabel; frame = (12 10; 84 21); opaque = NO; layer = <YYAsyncLayer: 0x283794240>>"]
cy# 0x122907c40.text = @"Gray"
@"Gray"
    • 这个时候就可以看到界面上已经显示了 Gray

    • 当退出当前群聊、再次进入、上次的修改也会消失.修改的是当时当刻、当前内存中的对象
  • 综上: 我们采用Cycript去调试界面、但是这样步骤比较繁琐;
    • 在Xcode中采用 Debug View Hierarchy直接对界面查找元素比较快.
    • 或者通过Reveal查看元素

1.4 Cycript高级用法

  • MonkeyDev中这些就是封装的高级语法

1.5 Cycript封装

//IIFE 匿名函数自执行表达式
(function(exports){APPID = [NSBundle mainBundle].bundleIdentifier,APPPATH = [NSBundle mainBundle].bundlePath,APPHOME = NSHomeDirectory(),//如果有变化,就用function去定义!!HKRootvc = function(){return UIApp.keyWindow.rootViewController;};  HKKeyWindow = function(){return UIApp.keyWindow;};HKGetCurrentVCFromRootVc = function(rootVC){var currentVC;if([rootVC presentedViewController]){rootVC = [rootVC presentedViewController];}if([rootVC isKindOfClass:[UITabBarController class]]){currentVC = HKGetCurrentVCFromRootVc(rootVC.selectedViewController);
}else if([rootVC isKindOfClass:[UINavigationController class]]){currentVC = HKGetCurrentVCFromRootVc(rootVC.visibleViewController);
}else{currentVC = rootVC;
}return currentVC;};HKCurrentVC = function(){return HKGetCurrentVCFromRootVc(HKRootvc());};})(exports);
  • 将该文件拷贝进项目中、
    • Build Phases --> Copy Files --> add

  • 导入文件
$ sh cyConnect.sh
cy# @import hank
{}
cy# APPID //Bundle ID
cy# APPHOME //HomeDirectory
cy# HKCurrentVC() //当前控制器
cy# pvcs() //当前控制器层级结构
  • 官网中有详细的使用语法案例:Cycript

二、Logos

  • Logos是一个基于Perl正则表达式的预处理器,它使用优雅的类似Objective-C的语法简化了为OC方法和C函数创建挂钩所需的样板代码.它最常与Theos构建系统一起使用,该系统最初是为创建越狱调整而开发的.Logos曾经与Theos集成在同一个Git仓库中,但现在已经从Theos解耦到它自己的仓库中.
  • Logos语法,其实是CydiaSubstrate框架提供的一组宏定义.便于开发者使用宏进行HOOK操作,语法简单,功能强大且稳定.

2.1 案例使用

  • 创建一个普通项目的iOS LogosDemo、随便写点代码
- (void)loginButtonEvent:(UIButton *)sender {[self postUID:self.uid.text PWD:self.pwd.text];
}
- (void)postUID:(NSString *)uidPWD:(NSString *)pwd{if ([uid isEqualToString:@"Holo"] && [pwd isEqualToString:@"123456"]) {UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"登录成功" message:nil preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction * cancel = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleCancel) handler:nil];[alertVC addAction:cancel];[self showViewController:alertVC sender:nil];}else{UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"登录失败" message:nil preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction * cancel = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleCancel) handler:nil];[alertVC addAction:cancel];[self showViewController:alertVC sender:nil];}
}
    • 编译运行Demo、取出MachO文件、来到终端:
      • 通过class-dump取出Headers
class-dump -H LogosDemo -o LogosDemoHeaders/
    • 执行结果如下

    • 这个时候我们需要对该LogosDemo进行重签名、对它进行方法的HOOK操作、
      • HOOK的时候,需要注入一个动态库,load中写一堆HOOK代码
  • 然而回想到MonkeyDev的作用
    • 1、重签名
    • 2、代码注入
    • 3、HOOK注入
  • 此时此刻,我们创建一个MonkeyApp项目、然后将LogosDemo的包放入TargetApp文件夹下.运行LogosMonkey项目、
    • 接下来,根据LogosDemo头文件,我们想要改变登录的状态、开始做HOOK操作
      • 来到LogosMonkeyDylib.xm文件中、删除所有示例代码

      • 稍微写点HOOK后的代码
//告诉当前,ViewController是继承于UIViewCotnroller的
@interface ViewController : UIViewController
@property (nonatomic,strong)UITextField *uid;
@property (nonatomic,strong)UITextField *pwd;
@end;%hook ViewController
//HOOK的方法
- (void)loginButtonEvent:(id )sender {NSString *str = [NSString stringWithFormat:@"%@-%@",self.uid.text,self.pwd.text];UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"HOOK Success!!!" message:str preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction * cancel = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleCancel) handler:nil];[alertVC addAction:cancel];[self showViewController:alertVC sender:nil];
}%end
  • 运行项目、输入账号密码、点击登录、这个时候,我们可以看到我们自己写的HOOK弹窗.操作成功

  • 综上: 这就是简单的利用MonkeyDev中的Logos进行HOOK的操作.

2.2 Logos语法

2.2.1 Logos Tips

  • “LogosMonkeyDylib.xm”后缀名为
    • .x 表示支持logos和C语法
    • .xm表示支持logos、C以及C++语法

2.2.2 Logos语法分为三大类:

  • Block level
    • 这一类型的指令会开辟一个代码块,以 %end结束
    • %group、%hook、%subclass、%end
  • Top Level
    • 这个TopLevel指令不放在BlockLevel中
    • %config、%hookf、%ctor、%dtor
  • Function Level
    • 这一块的指令就放在方法中
    • %init、%class、%c、%orig、%log
  • 常用语法
    • %hook: HOOK某个类里面的某个方法
%hook ClassName
-(void)instanceMethod { }
+(void)classMethod{ }
%end
    • %new: 为某个类添加新方法,在%hook和%end中使用
%hook ClassName
// 添加一个类方法
%new
+(void)newClassMethod{}
//添加一个对象方法
%new
-(void)newInstanceMethod{}
%end
    • %group用来将代码分组.开发中hook代码会很多,这样方便管理Logos代码
%group group1
%hook ClassName%end
%end
    • %ctor(constructor):构造函数、用于确定加载哪个组.和%init结合用
    • %init: 用来初始化某个组
    • %log: 能够输出日志,输出方法调用的详细信息
    • %orig(original): 这个就是保持原有的方法实现,如果原来的方法有返回值,那么%orig就有返回值的
    • %c: 类似getClass函数,获得一个类对象.一般用于调用类方法

2.2.3 Logos语法使用案例

案例1:

    • 比如刚才的案例: 我们使用%group来做不同的事件、那么需要配合 %ctor来使用
#import <UIKit/UIKit.h>
//告诉当前,ViewController是继承于UIViewCotnroller的
@interface ViewController : UIViewController
@property (nonatomic,strong)UITextField *uid;
@property (nonatomic,strong)UITextField *pwd;
@end;%group group1
%hook ViewController
//HOOK的方法
- (void)loginButtonEvent:(id )sender {NSString *str = [NSString stringWithFormat:@"%@ - %@",self.uid.text,self.pwd.text];UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"HOOK Group1 Success!!!" message:str preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction * cancel = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleCancel) handler:nil];[alertVC addAction:cancel];[self showViewController:alertVC sender:nil];
}
%end
%end%group group2
%hook ViewController
//HOOK的方法
- (void)loginButtonEvent:(id )sender {NSString *str = [NSString stringWithFormat:@"%@ - %@",self.uid.text,self.pwd.text];UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"HOOK Group2 Success!!!" message:str preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction * cancel = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleCancel) handler:nil];[alertVC addAction:cancel];[self showViewController:alertVC sender:nil];
}
%end
%end%ctor {%init(group1)
}
    • 编写代码如上、这个时候,运行得出错误
Preparing to run Xcode Build Phase for Logos Processor...
Logos Processor: LogosMonkeyDylib.xm -> LogosMonkeyDylib.mm...
Failed Logos Processor: ~/LogosMonkey/LogosMonkeyDylib/Logos/LogosMonkeyDylib.xm:45: 
error: non-initialized hook group: group2
    • 这里表示、group2没有进行初始化: 也就是一旦写了就要初始化
%ctor {%init(group1) %init(group2)
}
      • 运行后我们可以发现、起作用的是group2的代码: 也就是说代码会覆盖,执行最后一个分组
    • 添加一个版本判断来单向执行
%ctor {NSString *version = [UIDevice currentDevice].systemVersion;if (version.doubleValue >= 13.0) {%init(group2)} else {%init(group1)}
}
  • 注: logos中使用ctor 则也会有 dtor:析构函数,做一些收尾工作,比如应用挂起时的操作

案例2:

    • 常用的语法: %log的使用
%group group1
%hook ViewController
//HOOK的方法
- (void)loginButtonEvent:(id )sender {%log;
}
%end
%end
    • 输出结果为
2023-04-11 21:30:19.813331+0800 LogosDemo[26917:903478] -[<ViewController: 0x127d131d0> loginButtonEvent:<UIButton: 0x127d16750; frame = (50 300; 200 50); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x28044a240>>]
    • 控制器对象: 方法名称 : 方法参数: 调用者.
    • 如此可见: %log相当于LLDB中的po.

案例3

  • %orig: 这个就是保持原有的方法实现,如果原来的方法有返回值,那么%orig就有返回值的
    • 如果原来的方法有返回值,我们用参数接收,在接收参数后对原始值进行操作.
id  result = %orig;
result += 1;

案例4

  • %new的使用: 为某个类添加新方法,在%hook和%end中使用
@interface ViewController : UIViewController
@property (nonatomic,strong)UITextField *uid;
@property (nonatomic,strong)UITextField *pwd;
@end;%group group1
%hook ViewController
//HOOK的方法
- (void)loginButtonEvent:(id )sender {NSString *str = [NSString stringWithFormat:@"%@ - %@",self.uid.text,self.pwd.text];UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"HOOK Group1 Success!!!" message:str preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction * cancel = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleCancel) handler:nil];[alertVC addAction:cancel];[self showViewController:alertVC sender:nil];
}%new
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{[self.view endEditing:YES];
}
%end
%end
    • 键盘弹起后,点击空白区域,键盘回收.

案例5

  • 当想创建一个类方法时,需要在类中声明及实现
@interface ViewController : UIViewController
@property (nonatomic,strong)UITextField *uid;
@property (nonatomic,strong)UITextField *pwd;
//新增声明的类方法
+ (void)hs_classMethod;
@end;
%group group1
%hook ViewController
%new
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{[self.view endEditing:YES];//[self.class hs_classMethod];//通过获取类名 调用类方法[NSClassFromString(@"ViewController") hs_classMethod];
}%new
+ (void)hs_classMethod{NSLog(@"This is a class method");
}
%end
%end
    • 获取类名: NSClassFromString(@"ViewController")
  • 另外: 这个时候我们可以引入 %c 来替代上述的获取类名的方法
%new
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{[self.view endEditing:YES];//通过获取类名 调用类方法[%c(ViewController) hs_classMethod];
}

案例6

  • %hookf官方案例
// Given the function prototype (only add it yourself if it's not declared in an included/imported header)FILE *fopen(const char *path, const char *mode);// The hook is thus made
%hookf(FILE *, fopen, const char *path, const char *mode) {puts("Hey, we're hooking fopen to deny relative paths!");if (path[0] != '/') {return NULL;}return %orig; // Call the original implementation of this function
}// functions can also be looked up at runtime, if, for example, the function is in a private framework
%hookf(BOOL, MGGetBoolAnswer, CFStringRef string) {if (CFEqual(string, CFSTR("StarkCapability"))) {return YES;}return %orig;
}
%ctor() {%init(MGGetBoolAnswer = MSFindSymbol(NULL, "_MGGetBoolAnswer"));
}

三、总结

  • Logos语法其实就是Cydia Substrate框架提供的一组宏定义
  • 语法
    • %hook、%end勾住某个类,在一个代码块中直接写需要勾住的方法
    • %group,%end用于分组: 一般用于不同的系统中做不同的hook内容
      • 每一组都需要 %ctor()函数初始化
      • 通过%init(组名) 进行初始化
    • %log输出方法的详细信息(调用者、方法名、方法参数)
    • %orig调用原始方法.可以传递参数,接收返回值
    • %c类似getClass函数,获得一个类对象
    • %new添加某个方法
  • 关于xm文件, .xm代表支持OC、C/C++语法
  • 编译该文件时,我们需要导入一些头文件,以便编译通过.