iOS逆向开发(4):注入目标函数 | fishhook | MobileSubstrate | MSHookFunction | iOSOpenDev
从获得APP的所有类声明,到锁定目标类与函数,现在是时候注入函数了。
所谓“注入函数”,小程的意思是让APP执行到小程写的代码中,跟“钩子”的概念一致。小程把个叫作iOS上的hook的技术。
本文介绍iOS注入函数的办法。
在借助框架之前,先介绍一个简单的注入办法,你可以“感性”地认识到“动态绑定”所带来的注入。
(一)动态绑定的一个示例
(1)锁定注入点
随便找一个APP,classdump拿到所有类的结构信息。
比如,“微信”有一个类是这样声明的:

这个类继承于UIViewController,也就是有viewDidLoad这个消息处理函数。这里演示把MMUIViewController::viewDidLoad函数给替换掉,让它执行到新的函数中。
(2)写注入代码
先找一个熟悉的编辑器,创建一个文件,命名为hookwx.m,然后在里面添加这样的代码:

然后是编译的事。可以直接使用xcode来编译出来.o文件,也可以用clang来编译出来.o文件。比如,小程演示时使用的是iphone4手机,也就是armv7指令集,所以可以这样编译出obj文件:
clang -c hookwx.m -arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk
再使用ld来链接成动态库(dylib):
ld -dylib -lsystem -lobjc -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/ -o hookwx.dylib hookwx.o -framework Foundation -framework UIKit -ios_version_min 6.0
以上编译链接命令的参数跟小程使用的sdk版本有关,你如果尝试的话应该选择对应的参数。
(3)拷贝dylib到DynamicLibraries
scp hookwx.dylib root@192.168.1.100:/Library/MobileSubstrate/DynamicLibraries/
这时,还要创建一个plist,来指定让哪个APP来加载这个dylib(对于ios8.0以后的系统需要指定哪个APP),具体操作参照上一篇文章--介绍reveal的使用时创建了plist,就是这个操作了。“微信”的bundleID是“com.tencent.xin”或“com.tencent.xin1”,指定让它加载这个dylib(可指定若干个bundleID)。
记得把plist文件也拷贝到DynamicLibraries目录中。
(4)验证效果
启动“微信”,使用socat观察log输出,可以看到:
Dec 2 11:22:05 810 MicroMessenger[974] <Warning>: =======in initialize=================
...
Dec 2 11:24:48 810 MicroMessenger[974] <Warning>: -------------in new_viewDidLoad----------
也就是,“微信”加载了小程写的dylib,而且也执行到新的函数中。
以上的例子,只是“感性地”知道注入的办法,而在实际使用场景,更应该借助一些成熟的可以做到注入的框架。
小程较常见的两个框架,一个叫fishhook,一个叫MobileSubstrate。
fishhook,是facebook的一个开源工具,可以在运行时修改目标函数的地址,让控制点执行到自己的代码。因为需要知道目标函数的名字,这对于c运行时库的函数来说是适用的,或者对于能定位到函数名的情况也是适用的,但对于连名字都拿不到的情况(比如只能定位到代码地址)就不适用。如果只能拿到函数的地址,那可以考虑用MobileSubstrate的MSHookFunction来做到注入。
MobileSubstrate(也叫CydiaSubstrate,以下简称为MS),最大的一个作用,是可以动态绑定新的执行函数,这个功能已经能满足我们大部分的需求。比如,MS提供的函数MSHookMessageEx,可以用来对oc代码进行hook,原理上利用了oc的runtime特性(运行时替换执行函数)。
MS提供的函数MSHookFunction,可以用来对c代码进行hook,比如很多APP在写文件时都会用到write或fwrite函数,那通过对这两个函数进行hook,就能看到写入文件的数据,可以这样写代码:

但直接使用MS的函数,并不是本文介绍的重点。从“实用”的角度,小程要介绍的是iOSOpenDev的使用。
(二)iOSOpenDev的使用
theos跟iOSOpenDev,都是对MS库进行封装的开发工具包,这样的工具包可以简化开发的操作。这里介绍iOSOpenDev的使用。
安装iOSOpenDev后,就可以使用xcode来完成插件的开发,或者简单地生成dylib库。
(1)安装iOSOpenDev
包装包地址:
http://iosopendev.com/download/
如果你安装成功,则不用参考小程失败的例子。
以下是小程安装失败并动手解决的例子。
安装时失败,/var/log/system.log里面记录着“安装器遇到了一个错误,导致安装失败。请联系软件制造商以获得帮助。”。
虽然安装失败,但是在/opt下面还是创建了三个目录(红框内):

在iOSOpenDevSetup/bin里面已经有一个shell脚本:iod-setup,这个是安装的脚本。
直接运行iod-setup来安装:sudo ./iod-setup base
发现总是在下载某个东西时失败,打开iod-setup来定位,发现有三个downloadGithubTarball的地方,
直接注释掉,然后手动去下载这三个东西,并拷贝到iOSOpenDev目录:
分别下载下面三个地址的zip包:
https://github.com/kokoabim/iOSOpenDev
https://github.com/kokoabim/iOSOpenDev-Xcode-Templates
https://github.com/kokoabim/iOSOpenDev-Framework-Header-Files
解压上面下载的zip包,拷贝:
sudo cp -r iosopendev-master/* /opt/iosopendev/
在iosopendev目录里面,sudo mkdir templates,然后:
sudo cp -r iosopendev-xcode-templates-master/* /opt/iosopendev/templates
在iosopendev目录里面,sudo mkdir frameworks,然后:
sudo cp -r iosopendev-framework-header-files-master/* /opt/iosopendev/frameworks
再次安装:
sudo ./iod-setup base
指定最新xcode sdk:
sudo ./iod-setup sdk -sdk iphoneos
小程还遇到另一种情况:在一台imac上,xcode8.3.2,安装包失败后,直接sudo ./iod-setup base,成功。
所以,上面不成功的情况,有可能是从github下载时网络上失败导致。
最终安装成功,表现为:
1.
~/library/developer/xcode 里面会多出
Templates/iosopendev
2.
打开 ~/.bash_profile
会看到:
export iOSOpenDevPath=/opt/iOSOpenDev
export iOSOpenDevDevice=
export PATH=/opt/iOSOpenDev/bin:$PATH
3.
启动xcode,新建工程,多出一个“iOSOpenDev”的模板。
就算使用iOSOpenDev,也有必要安装theos,否则编译时会有提示:
Preparing to run Xcode Build Phase for Logos Processor...
Failed to locate Logos Processor. Is Theos installed? If not, see http://iphonedevwiki.net/index.php/Theos/Getting_Started.
安装theos很简单(可以安装完iOSOpenDev后,再安装theos):
brew install dpkg ldid
sudo Git clone --recursive https://github.com/theos/theos.git /opt/theos
(2)使用iOSOpenDev的示例
创建项目,iOSOpenDev -> Logos Tweak (安装后会有图标)。
在项目中,可以找到一个后缀为xm的文件,这个文件就是写代码的地方。iOSOpenDev会根据xm的内容编译到mm中(xm不是必须要有的,但xm的语法比mm中的好懂多了)。
xm文件里面的#error会提示你拷贝个libsubstrate.dylib过来。到/opt/iosopendev/lib里面把libsubstrate.dylib拉到项目的Frameworks目录。
再拉进一个UIKit.framework,因为SpringBoard在UIKit里面声明,而这个例子就是对SpringBoard进行hook。
SpringBoard是系统的组件,在启动机子时加载。
清空xm文件,写代码:

小程这里用的UIAlertView是旧sdk支持的,如果是新版本的sdk,应该使用新的“提示框”类。
编译,成功的话,会生成对应的动态链接库,即xx.dylib。然后是plist文件,在项目中找到xx.plist,对它进行修改,指定让哪一个APP启动时加载这个dylib。
然后,把dylib与plist拷贝到DynamicLibraries目录(小程有多次提到了)。其实,xcode可以在编译后自行拷贝到手机,只需要这样配置下项目(当然也要保证电脑可以ping到手机):
在build settings页面,查找iOSOpenDevDevice,把内容设置为IP,比如:192.168.1.101 ,让xcode知道往哪台手机安装应用。然后编译并安装到手机:Project->Build For->Profiling。
注意,编译时,目标设备哪一项,应该选择Generic iOS Device, 否则会遇到一堆错误(选择真机或模拟器都可能一堆编译错误)。
安装后可以到cydia的“已安装”中看有没有你的应用,也可以ssh到手机后查看:
dpkg -l
重启机子(killall springboard),启动时会看到弹出的alertview。
总结一下,本文内容较多,但主体是iOSOpenDev的使用,这个是注入APP的有效的工具。

iOS逆向开发(4):注入目标函数 | fishhook | MobileSubstrate | MSHookFunction | iOSOpenDev的更多相关文章
- iOS逆向开发(8):微信自动添加好友
这一次,小程演示怎么让一个APP自动地运行,从而代替手工的操作.同样以"微信"以例,实现在一个微信群里面,对所有的成员,自动地一个一个地发出添加好友的请求. 知识点还是之前介绍的东 ...
- iOS逆向开发(1):基础工具 | ssh | scp | socat
小白:小程,我一直想问,什么是逆向来着?是逆向行驶吗? 小程:理解为逆向行驶也没错.一般的项目是从无到有,而逆向是从已有的状态入手,分析出已有的流程与结构的手段. iOS上的逆向开发,是一件有趣的事情 ...
- iOS逆向开发(6):微信伪造位置
仍然以微信为例,实战地练习一下使用Reveal.iOSOpenDev等工具注入APP的流程,积累经验.这一系列的文章都是学习过程的总结,不带任何商业目的. 本文解决一个问题:如何伪造一个经纬度,在微信 ...
- iOS逆向开发(5):微信强制升级的突破 | 多开 | 微信5.0
接下来的几篇文章,小程以微信为例,实战地演示一下:如何注入iOS的APP.其中使用到的知识,基本在前面的文章中都有介绍到. 小白:小程,我想用回旧版本的微信! 小程:为什么要用旧版本微信呢? 小白:你 ...
- iOS逆向开发(3):锁定APP的目标类与函数 | reveal | lldb | debugserver | 远程调试
之前介绍了怎么获取APP的所有类的结构信息,这个有什么用呢?用处大了,比如以这一步为基础,下一步通过注入来做更多研究工作. 注入的最小单位是函数,实际上,编译执行的程序在编译后,类就不复存在了,留下来 ...
- iOS逆向开发(0):修改二进制代码与重签名 | hopper | codesigh
小白:小程,你知道有些iOS程序是没人性的吗?老是不按我的意愿来运行! 小程:我怎么知道你的意愿就是有人性的? 本文解决一个问题:修改别人的二进制程序并运行起来. 让别人的程序按你的意愿来运行,文明一 ...
- iOS逆向开发(2):获取APP的类声明 | class-dump | dumpdecrypted
之前介绍了怎么操作越狱的iOS设备(以下简称为手机),但简单操作手机并不是目标,小程的目标是手机上特定的APP,比如微信.淘宝.QQ音乐等等,因为小程可以从这些APP上拿到一些有用的信息或资源--比如 ...
- iOS逆向开发(7):微信伪装他人
上一节小程介绍了微信在进入"附近的人"时修改位置信息的办法,这一次,小程来修改"自己"的信息,伪装成别人. 但是,这里的伪装只是"本地的伪装" ...
- Hook原理--逆向开发
今天我们将继续讲解逆向开发工程另一个重要内容--Hook原理讲解.Hook,可以中文译为“挂钩”或者“钩子”,逆向开发中改变程序运行的一种技术.按照如下过程进行讲解 Hook概述 Hook技术方式 f ...
随机推荐
- vue,react,angular
一.Vue.js: 其实Vue.js不是一个框架,因为它只聚焦视图层,是一个构建数据驱动的Web界面的库. Vue.js通过简单的API(应用程序编程接口)提供高效的数据绑定和灵活的组 ...
- 阿里云 ECS centos java timer进程异常/混乱......的解决方法
之前就知道timer进程长久运行容易出问题,所以一直对timer进行了很长一段时间的日志监控和数据库记录,大概观察了几个月,没发现过问题....然后就没管理了,数据库记录也没做了,昨天这问题就来了,t ...
- 洛谷 p2440木材加工
#include <iostream>#include <cstring>using namespace std;const int N = 1e5 + 100;int a[N ...
- Navicat连接oracle库报错的处理方法
1.oracle客户端版本:11.2.0 64X navicat premium客户端:12.0. 64X 2.安装后,打开连接,输入连接信息,点击保存,提示oracle library is no ...
- kSum问题总结
1.2Sum 题目: 方法一:两次迭代 public class TwoSum { public static int[] twoSum(int[] nums, int target) { int[] ...
- Think in java(1)
OOP编程思想认为万事万物皆对象,而在设计类(class)的时候,就是从我们生活中或者某些事物中抽象出一个具有共同属性,共同行为的描述(类).在实际的开发中,我们一般会不自觉的这样做:假设有一个人 ...
- jQuery常用选择器总结
jQuery常用选择器总结: 我们都知道jQuery是JavaScript(JS)的框架,它的语法简单使用方便,被广大开发人员青睐.现在我就它常用的并且十分强大的选择器的方式,做一个总结.鉴于它的选择 ...
- Node.js的安装以及npm的基础使用
索引: Node.js的安装以及Node.js的模块管理Node.js开发环境搭建以及对ES6的支持Node.js构建Vue.js项目Vue.js单文件组件的开发基于Vue.js的UI组件(Eleme ...
- Photon自定义加载Resource之外的资源
PhotonNetwork.cs 结尾添加如下代码: #region >>> Photon自定义异步加载GameObject public delegate void CustomL ...
- 大叔学ML第五:逻辑回归
目录 基本形式 代价函数 用梯度下降法求\(\vec\theta\) 扩展 基本形式 逻辑回归是最常用的分类模型,在线性回归基础之上扩展而来,是一种广义线性回归.下面举例说明什么是逻辑回归:假设我们有 ...