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 ...
随机推荐
- py3.0第五天,常用模块
本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configpars ...
- 1123. Is It a Complete AVL Tree (30)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...
- k8s初始化搭建方法
http://www.cnblogs.com/cocowool/p/kubeadm_install_kubernetes.html https://www.kubernetes.org.cn/doc- ...
- Code First的实体继承模式
Entity Framework的Code First模式有三种实体继承模式 1.Table per Type (TPT)继承 2.Table per Class Hierarchy(TPH)继承 3 ...
- spring的一个小例子(二)--解析前面的小例子
接上篇:http://www.cnblogs.com/xuejupo/p/5236448.html 首先应该明白,一个web项目,web.xml是入口. 然后下面来分析上篇博客中出现的web.xml: ...
- HTML的Tomcat
修改D:\software\apache-tomcat-8.0.44\webapps\ROOT\WEB-INF\web.xml: <?xml version="1.0" en ...
- js 控制光标到指定位置
js控制光标到指定节点位置(适用于富文本编辑器中) function placeCaretAtEnd(el) { //传入光标要去的jq节点对象 el.focus(); if (typeof wind ...
- oracle创建新用户和用户表空间
.首先,创建(新)用户: create user username identified by password; username:新用户名的用户名 password: 新用户的密码 也可以不创建新 ...
- sshd_config 配置文件参数详解
sshd_config配置详解 名称sshd_config - OpenSSH SSH 服务器守护进程配置文件 大纲/etc/ssh/sshd_config 描述sshd(8) 默认从 /etc/ss ...
- 1.Float精度在JS的解决方法
最近做了一个有关折扣价的计算的功能,所有的运算都是在前台通过js来做,做完之后经过手工核算发现了一个问题,当时做的一个例子是10*0.94,按照我们正常的思维,这个结果应该是9.4,但是在js中的计算 ...