iOS逆向工程实战篇

1. 备忘录增长字数统计功能

实现的功能:

在导航栏上实时显示备忘录的字数.数组

功能分析:

  • 编辑界面是一个View, 能够经过nextResponder找到它的Controller, 再经过Controller访问备忘录数据, 能够在初始化编辑界面的时候初始化标题字数.xcode

  • 咱们要作到标题字数随着内容的编辑而改变. 因此咱们要实时注意protocol中的方法有没有这类方法.服务器

  • 最后经过Controller的title属性设置标题.app

功能实现:

  1. 首先定位备忘录的可执行文件

关闭无用App, 打开备忘录, ssh到iOS, 利用ps命令看看当前的进程. 由于是系统App, 因此在/Applications/路径下查询, 以便咱们查找.ssh

ps -e | grep /Applications/
复制代码

能够看到MobileNotes这个App貌似是咱们的备忘录. 咱们验证一下, 经过killall掉它, 看看打开的备忘录会不会关闭. 经过验证MobileNotes果真关闭了.工具

咱们把MobileNotes的可执行文件/Applications/MobileNotes.app/MobileNotes 拷贝到电脑中.测试

  1. 导出MobileNotes的头文件

由于MobileNotes不是从App Store下载的App, 没有加壳, 因此能够直接使用 class-dumpspa

  1. 此次咱们用可视化工具FLEXLoader找到咱们备忘录界面的Controller;

而后咱们经过cycript验证ICTextViewController是否是咱们的目标Controller. 这里咱们能够经过设置Controller的Title属性来观察变化.3d

执行后并无发现界面的标题有任何变化.代理

咱们经过FLEXLoader的views功能查看UI层级, 选择当前控件的上一层控件的小图标点进去.

能够看到当前选中控件的Controller是ICNoteEditorViewController, 我想咱们应该试试它. 一样执行上面设置title代码, 观察标题.

能够看到当前的标题发生了改变. 因此当前的Controller是 ICNoteEditorViewController.

既然找到了咱们要hook的类, 那么咱们就能够打开ICNoteEditorViewController这个.h文件.

观察.h文件, 寻找咱们的目标信息.

发现了咱们的目标控件 textView. 而后经过textView便可以获取当前输入内容的长度. 而后设置到title上.

咱们在继续看发现了textView的代理方法.

这个方法咱们很熟悉, 就是当textView的内容改变的时候会走到这里, 而后咱们在这个方法内根据textView的长度去设置title便可. 这里验证当输入内容的时候走不走这个方法能够经过不少方式验证, 这里我是经过简单的hook方法并打印, 而后经过xcode查看打印的值确认的. 还有经过lldb和IDA打断点到目标方法上, 而后触发断点也是能够判断的.不事后一种方法稍微要求高一些.这里咱们没有用.

以上是我分析后的结果.

编写Tweak:

这个例子很简单, 全部操做都在一个类中完成.

上面的111是我手速快输入错了, 因此从新输入便可.

tweak的代码

这个.h文件的目的仅仅是为了让tweak经过编译不报错. 存放在工程里便可.

这个是Makefile 的内容:

图中和建立工程的名字不同是由于时间缘由, 我没有把以前的图换掉, 直接用的老图. 不过不影响流程.

安装使用:

接下来咱们安装这个tweak

而后打开备忘录

能够看到咱们的tweak生效了. title随着咱们的内容增减而变化.

因为时间问题分析过程可能少了不少, 我的感受作逆向开发, 最重要的就是分析过程, 因此后面有时间会补上分析过程.

若是不想用这个tweak, 能够到这里把它干掉!


2. 将目标电子邮件标记为已读

实现的功能:

在Mail界面上增长编辑白名单的按钮.

每次当Mail的收件箱收到新邮件时, 就会自动把白名单外的邮件标记为已读.

功能分析:

功能实现:

首先定位到Mail的可执行文件并class-dump它.

仍是老样子经过ps命令很简单的就定位到了Mail的可执行文件

而后导出它的头文件:

接下来就是寻找到咱们安放编辑按钮的位置:

咱们把这个编辑白名单的按钮加到上图的位置.

此次咱们经过Reveal查找上图的Controller.

首先定位到最好找到的TableView, 而后查看右侧 MailboxPickerController便是咱们要找的Controller, 为了保险起见, 咱们经过cycript测试一下.

首先注入到 MobileMail 进程. 而后经过Reveal上提供的Controller地址设置rightBarButtonItems. 设置成功后出现如咱们上图的那样:

接下来咱们用相同的方法寻找收件箱列表的Controller.

MailboxContentViewController

而后用一样的方法测试下MailboxContentViewController 是否是咱们的目标Controller.

而后咱们去MailboxContentViewController这个头文件查找咱们须要的信息.

和以前同样, 首先查看协议中有没有蛛丝马迹. 很快我发现了MessageMiniMallObserver 这个协议有咱们须要的东西.

从方法名字上看LoadMessages FinishedFetch MessageCountDidChanged 方法可能会在刷新完成先后调用.

为何选择这三个方法呢?

由于咱们作开发的时候通常获取的页面数据, 在刷新中是能够获取到的. 因此咱们重点测试下这个三个方法, 有没有咱们想要的东西.

而后咱们利用LLDB在这个三个方法上打断点.

经过IDA查看三个方法的基地址, 而后加上ASLR, 过程以前作过, 这里就不一一写出来了.

打完断点以后, 咱们下拉刷新来触发断点:

能够看到触发的断点地址正是 FinishedFetch方法ASLR偏移后的地址, 并且每次都是只走这个方法.

而后我删除一封邮件立刻就触发了断点, 正是方法MessageCountDidChanged:

经过测试发现 :

  • FinishedFetch方法每次刷新完成的时候都会走. 也就是在服务器成功取得邮件后获得调用.

  • MessageCountDidChanged方法每次有删除邮件或者有新邮件的时候才会触发.

  • 这里咱们选择MessageCountDidChanged方法做为寻找全部邮件的方法.

设置断点到MessageCountDidChanged方法, 删除已有的一封邮件触发断点:

而后咱们看看它的参数:

能够发现参数的类型的NSConcreteNotification 自定义的抽象通知类, 继承自Notification.

而name是MiniMallMessageCountDidChange, object是MessageMiniMall对象. userInfo是一些改动的信息.

而后咱们寻找MessageMiniMall的头文件继续寻找咱们须要的信息.

这里文件内容有些多, 就不所有截取了. 能够发现MessageMiniMall类继承自NSObject, 而后结合名字很容易就猜出来当前类是负责处理数据的M.

通过查找发现 - (id)copyAllMessages; 方法颇有多是获取所有邮件的方法.

这里咱们测试下:

能够看到执行了copyAllMessages方法的返回值是一个集合类型而且集合中的元素是MFLibraryMessage类型的对象.

能够看到集合中有4个元素, 正是咱们邮箱中的四封邮件. 所以copyAllMessages就是拿到全部邮件的方法.

同时咱们在头文件中发现方法 - (void)markMessagesAsViewed:(id)arg1; 经过语义可知道应该是设置消息为已读的方法. 而参数也应该是含有MFLibraryMessage类型对象的数组.

到目前为止咱们知道一封邮件就是一个MFLibraryMessage对象. 咱们在头文件中没有找到这个类文件. 因此它应该来自一个外部的dylib.(Message.framework)

经过MFLibraryMessage.h头文件并无发现发件人地址等信息. 不过发现了- (id)copyMessageInfo; 这个方法. 试一下看看他返回什么.

一个MFMessageInfo对象. 咱们感受去这个头文件中看看. 可是通过查找发现并无咱们想要的信息. 咱们继续查看MFLibraryMessage.h发现它继承自MFMailMessage这个类, 咱们赶忙打开看看这个类.

经过观察发现这个类中有咱们邮件中经常使用的词汇.summary subject sender cc bcc 等. 不过有的属性确没见到getter. 咱们继续查找它的父类MFMessage文件看看, MFMessage是MIME.framework的类.

能够看到这里有咱们须要的信息, 而后咱们经过LLDB查看一下具体的值.

能够肯定这个类里面有咱们须要的信息.

而后验证一下以前寻找的 markMessagesAsViewed 是否是咱们要找的标记邮件为已读的方法.

经过IDA查找markMessagesAsViewed的地址.而后打断点.在把邮箱中的邮件设置为已读试试这个断点有没有触发.

能够看到确实触发了断点, 说明这个方法就是咱们要找的.而后咱们看看这个方法的参数:

没错就是MFLibraryMessage对象组成的NSSet.

下面就能够开始编写咱们的Tweak了.

编写Tweak:

安装使用:

设置白名单, 使得除了白名单外的全部邮件都设置为已读. 这里随便写一个.

而后删除一封邮件看看效果:

能够看到当邮件数量改变时, 收件箱中不在白名单中邮件已变成了已读.

相关文章
相关标签/搜索