前言
上一篇文章 iOS 逆向 – LLDB 中讲述了 lldb
的一些基础用法 , 并没有涉及太多其他内容 , 逆向过程中常用的动态调试方法其实还有一些 , 本文针对上篇文章和实际逆向中的运用进行一个补充 .
主要针对 Chisel
以及 Cycript
两个部分 .
如果篇幅不长 , 我们来讲一讲自定义 cy
指令.
逆向调试注意
-
有部分同学反应重签名微信应用被封号的情况 . 这里说明一下 , 微信 / 抖音 等应用是有防护和监测操作的 , 网上流传部分激活成功教程微信防护的
logos
代码 , 笔者测试效果不是百分百 , 有需要的小伙伴可以评论留言 . -
调试别人应用本身是会造成类似问题的 , 因此尽量不要登录个人使用账号 , 如非必须登录 , 不要登录账号 .
-
确实需要登录 , 登录一个小号 , 另外提前准备好另一个账户去解封 .
-
在越狱环境下 , 使用插件的方式调试 , 无须重签名 , 被封号的几率是很低的 .
-
最后再强调一次 : 玩逆向只是为了更好地防护 .
Chisel
概述
Chisel 也是 Facebook
发布的一个 lldb
的插件 , 能够做到帮助调试和提供用户自定义指令集的功能 . 接下来会具体阐述 .
安装
命令 : brew install chisel
( 还没有安装 HomeBrew 的自行安装 )
安装后使用 : brew list
查看安装结果
配置
如何配置 ?
1 — 打开下载目录
- 先找到下载的文件 :
cd /usr/local/Cellar/chisel
open .
, 找到fblldb.py
脚本文件.
cmd + opt + c
拷贝文件路径.
2 — lldb配置脚本路径加载
- 如果你的用户家目录下没有
.lldbinit
文件 , 请查阅上一篇文章 iOS 逆向 – LLDB 中最后讲自动启用加载指令所述 , 使用vim
自行创建即可 .
vim .lldbinit
s
进入编辑模式- 添加加载指令 :
command script import /usr/local/Cellar/chisel/1.8.1/libexec/fblldb.py
( 路径换成你自己的 )
ESC
,:wq
保存退出
使用
测试配置结果
先来简单试一下配置成功了没 .
注意 : 如果是正在运行的工程 , 那你需要使用 command source ~/.lldbinit
, 来重新加载一下 lldb
配置文件 .
随便打开一个工程 , 进入断点模式 , 输入 pviews
.
pviews
就是 Chisel
提供的一个查看视图层级的命令 . 以上看到 , 我们已经配置成功了 .
常用指令
为了模拟逆向过程中实际动态调试场景 . 我使用了我之前使用 MonkeyDev
重签名的微信应用来演示指令 , 对重签名不熟悉的同学可以阅读一下 重签应用调试与代码修改 (Hook) , 与 shell 脚本自动重签名与代码注入 , 这两篇文章 .
MonkeyDev
的安装和使用我们就不多赘述了 , 毕竟重签名原理理解了 , Monkey
其本质上也是利用脚本自动重签名 , 然后 代码注入 hook
部分集成了 Cydia Substrate
来做的.
我们所需要做的只是把砸过壳的 ipa
或者 app
包 放到指定文件夹下即可完成重签名和代码注入 . 非常方便.
如果同学们关于 MonkeyDev
使用有问题可以留言告知 .
运行工程 .
pviews 图层层级
打开注册页面 , 暂停 . 进入断点模式 ,
- 指令 :
pviews
- 结果 :
- 说明 :
pviews
可以帮助我们很清楚的看出图层逻辑层级关系以及内存地址 .
pvc 视图层级
-
指令 :
pvc
-
结果 :
-
说明 :
pvc
可以帮助我们很清楚的看出视图控制器层级关系以及内存地址 .
pactions 事件查找
使用 pviews
, 随便找到一个按钮 , 复制其内存地址 .
- 指令 :
pactions 0x10b06e5e0
- 结果 :
- 说明 :
pactions
可以拿到button
的target
以及action
, 在逆向时需要方法hook
经常会使用.
presbonder 响应链
使用 pviews
, 随便找到一个按钮 , 复制其内存地址 .
- 指令 :
presbonder 0x10b06e5e0
- 结果 :
- 说明 :
presbonder
可以查看完整的响应链.
pclass 继承链
使用 pclass
, 随便找到一个类 , 复制其内存地址 .
- 指令 :
pclass 0x10b910600
- 结果 :
- 说明 :
pclass
可以查看完整的继承链.
pmethods 查看类方法 / 实例方法
- 指令 :
pmethods 0x106b57bc0
- 结果 :
- 说明 :
pmethods
可以查看类完整的类方法和实例方法.
pinternals 查看成员变量
- 指令 :
pinternals 0x10b660df0
- 结果 :
fv / fvc
- 指令 :
fvc -v 0x10b8fe000
- 结果 :
- 说明 :
- 通过内存地址查看类名 ( po 也可以 ) . , 视图控制器用
fvc
, 视图用fv
. fv + 类名
反之是一样的 , 回去工程搜索这个类 打印其内存地址 .
- 通过内存地址查看类名 ( po 也可以 ) . , 视图控制器用
重点 : taplog
- 指令 :
taplog
- 说明 :
taplog
输入后会退出断点模式 , 再点击屏幕上任何可响应视图 , 会自动进入lldb
模式并打印按钮. - 结果 :
重点 : flicker
- 指令 :
flicker 0x11827c040
- 说明 : 通过内存地址 , 在断电模式下调用该指令会闪烁
view
, 非常方便调试 , 以及确定该内存地址是否为我们想找到的那个视图 .
重点 : vs
- 指令 :
vs 0x11827c040
- 说明 : 通过内存地址 , 进入调试模式 , 当前view会被添加红色以便查看 .
- 结果 :
(lldb) vs 0x1120f3390
Use the following and (q) to quit.
(w) move to superview // 来到当前视图的父视图
(s) move to first subview // 来到当前视图的第一个子视图
(a) move to previous sibling // 来到当前视图同级关系下的前一个视图
(d) move to next sibling // 来到当前视图同级关系下的后一个视图
(p) print the hierarchy // 打印当前视图的层级结构
<FixTitleColorButton: 0x1120f3390; baseClass = UIButton; frame = (20 112; 374 47); clipsToBounds = YES; opaque = NO; autoresize = W; layer = <CALayer: 0x1118c0900>>
- 退出 vs 调试模式 ,
q
指令 .
提示
最后三条指令在逆向过程中非常常用 , 大家多加练习与掌握 .
lldb_commands 插件
这个 LLDB
插件叫 lldb_commands
. 地址为 github.com/DerekSeland…
安装
- 直接
Clone
或者下载 , 把lldb_commands
文件夹保存起来 , 我这边是放到/usr/local/Cellar
里
- 来到家目录 , 找到
.lldbinit
, 添加一条指令 :
command script import /usr/local/Cellar/lldb_commands/dslldb.py
路径换成自己的 lldb_commands
文件夹路径即可 .
工程来到 lldb
模式下 , 输入 search UIView
, 即可测试有没有配置成功 .
常用指令
methods 快速定位方法
找到视图控制器地址 , 使用 methods 查看其所有的实例方法和属性 .
注意 : 由于逆向时 方法的符号是没有恢复的 , 因此根据类名和方法名下断点会失败 .
函数调用栈
由于符号并没有恢复 , 因此 bt
指令查看函数调用栈时 , 会出现以下情况 .
( 后续会讲如何利用工具恢复 Mach-O 的符号 )
那么此时 , 利用 lldb_commands
提供的 sbt
指令 , 会帮助恢复一些符号 , 以便于查看方法名称 .
Mach-O Section 查看
Section
指令可以让我们快速查看Mach-O
有哪些Section
段 .
Section
可添加其他指令来查看Mach-O
具体内容 .
# Dump the Mach-O segments to the main executable
(lldb) section
# Dump the Mach-O segments to UIKit
(lldb) section UIKit
# Dump the Mach-O sections of the __TEXT segment of UIKit
(lldb) section UIKit __TEXT
# Get the load address of all the hard-coded uint8_t * strings in the UIKit binary
(lldb) section UIKit __TEXT.__cstring -l
# Get the entitlements for the executable (simulator only, entitlements for actual app in __LINKEDIT)
(lldb) section __TEXT.__entitlements
# Get all the load address to the lazy symbol stubs in the main executable
(lldb) section __DATA.__la_symbol_ptr -l
效果如下 , 大家可以结合 MachOView
来查看结果.
Cycript
概述
Cycript 是由 Cydia
( 熟悉越狱的同学应该都很清楚 ) 创始人 Saurik
推出的一款脚本语言,Cycript
混合了 OC
、 JavaScript
语法的解释器,这意味着我们能够在一个命令中使用 OC
或者 JavaScript
,甚至两者并用。
它能够挂钩 正在运行的进程,能够在运行时修改很多东西。
到官网点击 Download SDK
即可下载 .
安装
- 将下载后的文件夹放入
/opt/
里即可 , 也可以自行选择位置 .
- 配置环境变量 .
- 注意 : 这里根据你使用的是
zsh
还是bash
去相应的资源文件配置 (家目录下的.zshrc
/.bash_profile
) . - 笔者由于在
.zshrc
中也配置了bash_profile
的引用 , 因此两处来配置这个环境变量都是可以的.
配置内容:
- 添加 :
export CY=/opt/cycript_0.9.594/
, 换成你自己的路径. - export PATH= 中添加
:$CY
重启 iTerm
, 输入 cycript
, 即可查看 .
如果有遇到 ruby
环境不对的同学 , 去下载对应版本的即可 . /System/Library/Frameworks/Ruby.framework/Versions
使用
在越狱环境下 , 是可以在 Cydia
直接安装 Cycript
插件的.
越狱手机截图上传有点麻烦 , 直接拍的.. 瑕疵请忽略 , 看个意思
那么非越狱环境下 , 就要借助 Cycript
提供的 iOS Framework
, 注入进去了 . 而且在 MonkeyDev
中 , 是默认已经做好了 Cycript
的注入的 .
而且添加了 默认 6666
端口号的监听 .
也就是说只要用 MonkeyDev
来重签跑起来的程序进程 , 6666
端口就可以附加使用了 ( 当然 , 在 Monkey
里代码可以自己定义端口号 ) .
好了 说了这么多 , 开始使用.
- 1 . 保证电脑和手机在同一个局域网内 ( 因为要做端口映射 )
- 2 . 运行
MonkeyDev
重签名程序 / 或者直接打开以前重签好的工程 , 无须Xcode
运行也可以 - 3 . 终端输入
cycript -r 192.168.0.116:6666
- 换成你自己的手机
ip
地址 - 另外 , 请不要将应用程序放到后台 , 会影响附加.
- 换成你自己的手机
出现以下 , Congratulations , you’re good to go !
提示
使用 tab
键 , 写代码可以补全 .
UIWindow.keyWindow()
查看当前 Window
.
UIApplication sharedApplication
指令 : [UIApplication sharedApplication ]
可简写为 UIApp
自定义变量
指令 : 自己 var
一个对象 , 而后我们就可以使用 .
另外注意 : 只要 APP
进程没有挂 , 这个变量是一直存在的 .
# + 地址可以直接使用
#
+ 对象地址 可以直接调用对象的方法
查看视图层级
UIWindow.keyWindow().recursiveDescription().toString()
随便找一个 , 例如注册页面有一个 .text
为 +86
的 label
, 拿到其内存地址 ,
命令 :
#0x10b95d800.text = "hhh"
显示结果
基于这种直接修改进程内存的方式 , 大家可以自己去玩一玩 . 比如登录了修改一下钱包余额 , 然后改一改 frame
, 练习一下 .
以下指令结果我就不一一贴图了 , 文章太长 , 不便阅读 , 大家自己尝试 .
获取页面上所有控件
choose(UIButton)
choose(UILabel)
隐藏 / 显示状态栏
[UIApp setStatusBarHidden:YES]
APP角标
[UIApp setApplicationIconBadgeNumber: 99]
获取Bundle ID
APPID
结果 :
@"com.libin.LBMonkeyApp"
页面层级
pviews()
pvcs()
根据按钮地址获取按钮 target & Action
pactions (#0x10b29da40)
结果 :
"<WCAccountRegisterViewController: 0x10b9d9800> onAgreementCheckBoxClick:"
根据按钮地址获取响应链
rp(#0x10b29da40)
退出cy 调试模式
control
+ d
注意:
pviews
/ pvc
/ pactions
/ rp
这些指令是 Monkey
在 MDConfig.plist
中额外封装了自定义的 cy
源的 . 也就是说使用越狱环境原本的 cycript
插件是没有这些指令可用的 .
那么我们闲着也是闲着 , 我们也来自己写一个 cy
源来玩一下 ?
自定义 cy 指令
-
在我们的
monkey
工程主工程target
中新建一个空文件, 我这里取名lb.cy
. -
Build Phases
–Copy Files
, 引入这个文件 -
在空文件添加我们想自己定义的指令 . 可以参照 Monkey 原本提供的那两个来写 raw.githubusercontent.com/AloneMonkey…
这里我写了一些我常用的指令 , 比如获取
APPID
/APPPATH
, 当前跟视图 , 当前页面 这些 , 我贴在下面供大家参考 , 也可以拿去直接用 . -
重新运行工程 .
-
输入我们自定义的指令 例如 :
LBCurrentVC()
-
提示没找到指令 , 因为我们还没有引入 ,
monkey
那两个在config
中会自动引入. -
@import lb
-
再次输入
LBCurrentVC()
, 得到结果.
//IIFE 匿名函数自执行表达式
(function(exports){
APPID = [NSBundle mainBundle].bundleIdentifier,
APPPATH = [NSBundle mainBundle].bundlePath,
//如果有变化,就用function去定义!!
LBRootvc = function(){
return UIApp.keyWindow.rootViewController;
};
LBKeyWindow = function(){
return UIApp.keyWindow;
};
LBGetCurrentVCFromRootVc = function(rootVC){
var currentVC;
if([rootVC presentedViewController]){
rootVC = [rootVC presentedViewController];
}
if([rootVC isKindOfClass:[UITabBarController class]]){
currentVC = LBGetCurrentVCFromRootVc(rootVC.selectedViewController);
}else if([rootVC isKindOfClass:[UINavigationController class]]){
currentVC = LBGetCurrentVCFromRootVc(rootVC.visibleViewController);
}else{
currentVC = rootVC;
}
return currentVC;
};
LBCurrentVC = function(){
return LBGetCurrentVCFromRootVc(LBRootvc());
};
})(exports);
小提示
-
使用
cycript
某一个控件 / 对象 内存地址时 , 要注意其生命周期 , 例如用一个label
的内存地址调试 , 你页面退出 , 又重进 , 是重新创建了对象的 , 以前的内存地址也会无法再使用 . 不要忘记这点 . -
cycript
使用需要同局域网每次要连接 , 或者其他我们需要自定义的初始化动作 , 我们可以将其写到一个脚本中 , 配置到zsh
/bash
环境变量中即可 , 大家可以玩一玩 , 有问题大家一起探讨一下 . -
逆向过程中 ,
View Debug
和cycript
调试界面是非常常用的手段 , 因此 , 希望大家能熟练掌握这些技巧 .
今天的文章iOS 逆向 – lldb高级篇 Chisel 与 Cycript分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14230.html