iOS 逆向开发20:LLDB 动态调试

iOS 逆向开发 文章汇总

目录

需要补充一个连接


一、LLDB(Low Lever Debug)

默认内置于Xcode中的动态调试工具。标准的 LLDB 提供了一组广泛的命令,旨在与老版本的 GDB 命令兼容。 除了使用标准配置外,还可以很容易地自定义 LLDB 以满足实际需要。LLDB 的官方API文档。

1.1 断点设置

  • 设置断点
    breakpoint set -n testFun
      set 是子命令
      -n 是选项 是--name 的缩写!

breakpoint set --selector touchesBegan:withEvent::根据selector设置断点
breakpoint set --file ViewController.m --selector touchesBegan:withEvent:

  • 添加内存地址断点
    b 0x104C55FA4

  • 查看断点列表
    breakpoint list

  • 删除
    breakpoint delete 组号

  • 禁用/启用
    breakpoint disable 1 禁用组1断点
    breakpoint enable 1 启用

  • 遍历整个项目中满足Game这个字符的所有方法
    breakpoint set -r Game:

1.2 流程控制

  • 继续执行
    continue c
  • 单步运行,将子函数当做整体一步执行
    n next
    ni 单步运行汇编级别
  • 单步运行,遇到子函数会进去
    s
    si 单步运行可跳转指令内部,汇编级别
  • stop-hook
    让你在每次stop的时候去执行一些命令,只对breadpoint,watchpoint

  • 其他命令

执行代码expression
expression 指令,简写p:打印变量的值
po:打印对象信息, expression命令选项:-O 表示调用对象的discraption方法

image list :镜像列表
b -[xxx xxx] :为实例方法添加断点
x :根据内存地址读取内存中的数据。
register read :读取寄存器中的值
register write 写入寄存器
memory read 读取内存值
help breakpoint :查看命令的帮助文档
bt:打印当前堆栈信息
updownframe select 1:上一个、下一个、选择堆栈的frame
frame variable:查看当前方法中的self、_cmd、参数、局部变量
watchpoint set variable p1->_name:观察属性的值变化(相当于KVO)

1.3 Debug时更改一个变量的值

p [params setObject:@"970407" forKey:@"bankCardNo"]
p [self func];//调用方法

1.4 为一组断点添加命令

break command add 1:为第一组断点添加命令,当触发断点时会执行命令

(lldb) break command add 1
Enter your debugger command(s).  Type 'DONE' to end.
> frame  variable
> DONE
(lldb) c
Process 8310 resuming
 frame  variable
(ViewController *) self = 0x000000013f0085d0
(SEL) _cmd = "save:"
(UIButton *) sender = 0x000000013f009ff0

(lldb) 

1.5 为所有断点添加一行命令命令

写法一:
target stop-hook add -o "frame variable"

写法二:

(lldb) target stop-hook add
Enter your stop hook command(s).  Type 'DONE' to end.
> frame variable
> DONE
Stop hook #2 added.
(lldb) 

target stop-hook list:列出stop-hook列表
target stop-hook delete 2:删除指定编号stop-hook

这种方式添加的stop-hook在下次执行后就会清空

1.6 通过文件添加 stop-hook

在Home目录中添加.lldbinit文件,并加入相关的命令即可

这样所有项目中进入断点就会执行.lldbinit文件中的stop-hook命令


二、LLDB动态调试工具

2.1 Chisel

chisel 安装链接,安装后重启Xcode即可使用

pviews查看视图层级:

pvc:查看控制器层级
pclass 类指针:查看当前类的继承关系
pmethods 类指针:查看类中方法
pmethods 类指针:查看当前类的成员属性

fvc -v 控件指针:查找控件属于哪个控制器
fv 控件类名:查找指定控件类的所有实例
flicker 控件指针:让控件在界面上闪两下
vs 控件指针:在指定父控件/子控件/同级控件之间选择。q退出调试状态

其他命令参考官网


2.2 LLDB

链接

  1. 下载LLDB到/opt目录
  2. Open up (or create) ~/.lldbinit
  3. Add the following command to your ~/.lldbinit file: command script import /opt/LLDB/lldb_commands/dslldb.py
  4. 重启Xcode即可使用

search ViewController : 查找指定类的所有实例
methods 类指针:查看类中方法
sbt:查看恢复了方法符号的堆栈信息

其他命令参考官网


三、 Cycript

Cycript是由Cydia创始人Saurik推出的一款脚本语言,Cycript混合了OC、JavaScript语法的解释器,这意味着我们能够在一个命令中使用OC或者JavaScript,甚至两者并用。它能够挂钩正在运行的进程,能够在运行时修改很多东西。(Cycript 也是一款LLDB动态调试工具)

3.1 Cycript安装

官网: http://www.cycript.org/
下载后使用Cycript这个可执行文件,将cycript文件夹放在 /opt/cycript
如果出现dyld: Library not loaded: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.2.0.0.dylib
解决方法:将/opt/MonkeyDev/bin/cycript拷贝到/opt/cycript/cycript

为了方便使用,可以在~/.zshrc中配置环境变量(如果配置了MonkeyDev/bin/就不用配置cycript了)。

参照[iOS 逆向开发17:HOOK原理下(HOOK OC方法)]( 文章中五、使用MonkeyDev进行重新签名和代码注入内容创建MonkeyApp:CycriptDemo,并重签名一个APP。

可以看到IPA包内容中的FrameWorks中注入了libcycript.dylib。运行App后进程就可以调用这个库中的一些方法,来开启相应的端口让别人监听。别人就可以通过这个端口链接这个进程进入cy#环境HOOK当前进程中的数据。

3.2无线网络链接手机

真机运行CycriptDemo,Mac和手机链接同一个WIFi。终端执行以下命令
cycript -r 手机IP地址:6666
真机回到CycriptDemo界面终端就会输出cy#表示链接成功

3.3 Cycript常用命令

  • 进入Cycript环境
    cycript

  • 附加进程(连接手机调试)
    cycript –r ip:port

  • 退出Cycript环境
    Ctrl + D

  • Cycript 调试命令
    pviews():查看视图层级
    pvcs():查看控制器层级(这两个命令是/Monkey项目/Config/MDConfig.plist中配置后网络加载的.cy文件,如果无法使用可以参照四、Cycript 高级用法下载.cy文件手动加载到项目中)
    UIWindow.keyWindow():获取keyWindow
    var keyWindow = UIWindow.keyWindow():定义变量
    [UIApplication sharedApplication]UIApp:获取Application单例对象
    keyWindow.recursiveDescription():查看视图层级(循环打印子视图)
    keyWindow.recursiveDescription().toString():格式化打印(遇到\n换行)
    # 对象地址:拿到该对象,可用于调用方法
    * 对象地址:可以取出对象的成员变量
    choose(UIButton):查询当前进程中该类型的对象。


四、 Cycript 高级用法

  • Cy文件
    Cycript是一门脚本语言,它可以加载封装好的.cy文件。
    我们会将常见的Cycript常用功能封装到.cy文件中,便于调试。

  • 非越狱中导入.cy文件
    利用MonkeyDev工具导入.cy文件,MonkeyDev本身集成了Cycript。我们只需要将.cy文件通过xcode导入Framworks目录即可。(操作如上面3.1)

4.1 封装.cy文件

  • Home文件夹中创建常用的Shell文件夹LCJShell
  • 创建cyConnect.sh用于连接手机
cd LCJShell
vi cyConnect.sh
cycript -r 192.168.6.30:6666
  • 在/.zshrc配置环境变量,让cyConnect.sh在任何目录环境都可以使用
  • source ~/.zshrc重新加载即可使用
  • sh cyConnect.sh执行连接手机

4.2 修改界面上的数据

cy# choose(UILabel)
cy# #0x15adcbd60.text = @"¥999999.99"

使用Debug View Hierarchy查看界面上的控件指针最方便

4.2 封装.cy文件并配置到项目中供调试时使用

  • 创建differ.cy文件,添加如下代码
// IIFE 匿名函数自执行表达式

(function(exports){
 
 APPID = [NSBundle mainBundle].bundleIdentifier,
 APPPATH = [NSBundle mainBundle].bundlePath,
 APPHOME = NSHomeDirectory(),
 
 //如果有变化,就用function去定义!!
 CJRootvc = function(){
     return UIApp.keyWindow.rootViewController;
 };  

CJPviews = function(){
    return UIApp.keyWindow.recursiveDescription().toString();
};

CJPvcs = function(){
    return UIWindow.keyWindow().rootViewController._printHierarchy().toString();
};
 
 CJKeyWindow = function(){
     return UIApp.keyWindow;
 };
 
  CJGetCurrentVCFromRootVc = function(rootVC){
    var currentVC;
        if([rootVC presentedViewController]){
        rootVC = [rootVC presentedViewController];
    }
 
    if([rootVC isKindOfClass:[UITabBarController class]]){
            currentVC = CJGetCurrentVCFromRootVc(rootVC.selectedViewController);
        }else if([rootVC isKindOfClass:[UINavigationController class]]){
            currentVC = CJGetCurrentVCFromRootVc(rootVC.visibleViewController);
        }else{
            currentVC = rootVC;
    }
    return currentVC;
 };
 
 CJCurrentVC = function(){
    return CJGetCurrentVCFromRootVc(CJRootvc());
 };
 
 })(exports);
  • differ.cy拖到项目中
  • differ.cy拷贝到APP包内Frameworks中
  • 重新运行项目并连接手机:@import differ表示引入自定义的.cy文件
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容