[TOC]
本篇主要制作微信的 tweak,实现在非越狱版的手机上进行 hello World 弹窗,从而熟悉 iOS 逆向相关的工具(不包含lldb远程调试、反汇编技术等),以及了解 tweak 的主要流程(其实就是如何制作插件的过程)。
warm:本篇只是我在操作过程中的一点总结,并不深入讲解原理。若想深入了解可以查看iOS应用逆向工程 第2版或者看文章最后的参考文档。
基本原理: 通过 app 启动时调用我们注入的动态库,从而进行 hook 。而之所以能够执行我们注入的动态库,是因为使用了mobilesubstrate
这个库,这个库能在程序运行的时候动态加载我们注入动态库。而非越狱手机里面是没有的,所以我们需要直接将这个库打包进 ipa 中,使用它的 API 实现注入。mobilesubstrate
库在下面的 github 中有提供,即是libsubstrate.dylib
.
本demo的github地址 : TKDemo
其中 /others 提供了 libsubstrate.dylib
与 本人写的 autoInsertDylib.sh
脚本,autoInsertDylib.sh
是用来实现注入动态库一体化。
以下部分工具(例如 claa-dump 、insert_dylib)可使用Xcode进行编译(command + b),然后在工程目录下的Products中拷贝目标文件,放在 /usr/local/bin
目录中,方便在 Termimal 中使用。
主要流程: 砸壳 ==> 获取ipa ==> 制作tweak ==> 查看(更改)依赖库 ==> 注入动态库 ==> 打包重签名 ==> 安装
实现在越狱手机上远程进行ssh服务
OpenSSH 在 Cydia 中安装 OpenSSH
// 指令 ssh user@iOSIP $ ssh mobile@192.168.1.6
// 指令 scp /path/to/localFile user@iOSIP:/path/to/remoteFile scp ~/Desktop/1.png root@192.168.1.6:/var/tmp/
注意,OpenSSH 默认登录密码为 alpine ,iOS 上的用户只有 root 与 mobile,修改密码使用passwd root(mobile)
用来在越狱手机上获取ipa
PS:可直接使用PP助手下载越狱版本的 ipa 文件(我就是这么懒得)
$ git clone https://github.com/KJCracks/Clutch $ cd Clutch // 使用 Xcode 进行build,得到可执行文件 $ xcodebuild -project Clutch.xcodeproj -configuration Release ARCHS="armv7 armv7s arm64" build
scp Clutch/clutch root@<your.device.ip>:/usr/bin/
clutch -i
列出当前安装的应用,再使用clutch -d 序列号(或者bundle id)
进行砸壳$ ssh root@<your.device.ip> $ clutch -i // 列出当前安装的应用 $ clutch -d bundle id (序列号) // 砸壳
clutch 将砸过后的 ipa 文件放到了/private/var/mobile/Documents/Dumped/
$ scp root@<your.device.ip>:/private/var/mobile/Documents/Dumped/xx.ipa ~/Desktop
dump 目标对象的 class 信息的工具。
将 demo.app 的头文件导出到~/Document/headers/
中
class-dump -S -s -H demo.app -o ~/Document/headers/
制作我们要注入的 dylib 动态库
本文章使用的是 theos
PS:也可以使用iOSOpenDev
iOSOpenDev 集成在 Xcode 中,提供了一些模板,可直接使用 Xcode 进行开发。只是这个工具停止更新,对高版本的 Xcode 不能很好地支持。本人装了多次老是失败,虽然最后在 Xcode 中有看到该工具,也不确定是否安装成功。若装失败可参考iOSOpenDev Wiki
从 github 下载至opt/theos/
brew install dpkg ldid export THEOS=/opt/theos sudo git clone --recursive https://github.com/theos/theos.git $THEOS sudo chown -R $(id -u):$(id -g) /opt/theos
可配置环境变量,vi ~/.bash_profile
,在 .bash_profile 文件的最后加入(否则每次重启Terminal都要重新export)
export PATH=/opt/theos/bin:$PATH export THEOS=/opt/theos
使用 nic.pl
创建 tweak若提示无此命令请根据上一步骤配置环境变量,或者不嫌麻烦使用/opt/theos/bin/nic.pl
根据提示选择 iphone/tweak,接着分别输入
如下所示:
完成后会看到四个文件(make 后将生成 .theos 、obj 文件夹).Makefile TKDemo.plist Tweak.xm control
ARCHS = armv7 arm64
TARGET = iphone:latest:8.0
Logos
和C/C++
语法,可以让我们不用去写一些 runtime 方法(.x 文件支持Logos语法,.xm 文件支持Logos和C/C++语法。
%hook
%end
结尾。%orig
%hook
内部使用,执行 hook 住的方法原代码。%new
%hook
的内部使用,给 class 添加新方法,与class_addMethod
相同。class_addMethod
为动态添加。%c
objc_getClass
、NSClassFromString
%hook
、%log
、%orig
等都是mobilesubstrate
的MobileHooker
模块提供的宏,除此之外还有%group
%init
、%ctor
等,其实也就是把method swizzling
相关的方法封装成了各种宏标记,若想深入了解,请左转 Google
熟悉各种语法之后便可以进行编写代码了,其中MMUIViewController
为微信的基础的ViewController。我们通过 hook viewDidApper:
来进行 hello World 弹窗。
使用make
进行编译
若想重新编译记得先make clean
(感谢我的嵌入式老师,让我还记得这个)make
后在当前文件夹下面将生成两个文件夹:.theos
与 obj
,其中我们编译完成的动态库就在.thoes/obj/debug
的下面,与工程名相同。
若编译的时候提示找不到 common.mk
或者是 tweak.mk
,请根据上述步骤(4.1 安装并配置 theos)重新 export theos,或写入至~/.bash_profile,或更改Makefile的文件,将$(THEOS)/makefiles
与 $(THEOS_MAKE_PATH)
替换成opt/theos/makefiles
查看执行文件所依赖的库文件
otool -L TKDemo.dylib
若发现有依赖 /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate
使用 install_name_tool 更改依赖。
CydiaSubstrate 只有越狱的手机上才有,因此需要我们手动更改并导入。
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/libsubstrate.dylib tkchat.dylib // install_name_tool -change 需要替换的库 @loader_path/需要引用的库 需要更改的dylib
把我们写的动态库注入到要 hook 的二进制文件
先将 ipa 文件解压,在解压后的/Payload
目录中,将app可执行文件拷贝出来。再将我们编写的动态库与libsubstrate.dylib 拷贝至app的包内容中。
执行命令:./insert_dylib 动态库路径 目标二进制文件
./insert_dylib @executable_path/xxxx.dylib xxxx // @executable_path 是一个环境变量,指的是二进制文件所在的路径
之所以能够不使用./是因为已经将 insert_dylib 导入到/usr/local/bin目录中
注入成功后将app目录中的 WeChat 删除,将 WeChat_patched 改为WeChat。
warm :使用 insert_dylib 时若出现 error 记得修改权限, chmod 777 insert_dylib
使用图形化打包签名工具 ios-app-signer
选择相应的证书与 Provisioning Profile 文件进行打包。
友情提示:如果证书没有支持 watch,请删除 app 中的watch相关的文件。
证书的话可以用 Xcode 新建个 Project (个人开发者证书7天后过期),在手机上运行下即可生成。导入时记得到真机上需要有相应的Provisioning Profile 文件。可在 Xcode-Window-Devices,双指点击设备查看Provisioning Profile文件,点击下面的 +
进行安装。
也可使用PP助手进行安装。
最后就是我们的 hello World
由于以上的操作(查看更改依赖库、注入动态库)都类似且繁琐,个人懒癌,就写了这个sh。
warm !!!
warm !!!
warm !!!
该脚本的中insert_dylib
路径使用的是/usr/local/bin
(请看前言),请根据自身环境更改脚本中的insert_dylib
路径,以免错误。
iOS App Singer
本人放在了/Applications/
中,若Applications中没有,则在脚本执行完手动打开。
使用:
./autoInsertDylib.sh ipa路径 libsubstrate.dylib路径 要注入的dylib路径
autoInsertDylib.sh 内容
# !/bin/bash SOURCEIPA="$1" LIBSUBSTRATE="$2" DYLIB="$3" if [ ! -d ~/Desktop/tk-tweak-temp-folder/ ]; then echo "在 Desktop 创建tk-tweak-temp-folder" mkdir ~/Desktop/tk-tweak-temp-folder else rm -rf ~/Desktop/tk-tweak-temp-folder/* fi cp "$SOURCEIPA" "$DYLIB" "$LIBSUBSTRATE" ~/Desktop/tk-tweak-temp-folder/ echo "正将" ${SOURCEIPA##*/} ${DYLIB##*/} ${LIBSUBSTRATE##*/} "拷贝至~/Desktop/tk-tweak-temp-folder" cd ~/Desktop/tk-tweak-temp-folder/ otool -L ${DYLIB##*/} > depend.log grep "/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate" depend.log >grep_result.log if [ $? -eq 0 ]; then echo "发现有依赖于 CydiaSubstrate, 正将其替换为 libsubstrate" install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/libsubstrate.dylib ${DYLIB##*/} else echo "没有发现依赖于CydiaSubstrate" fi echo "解压" ${SOURCEIPA##*/} unzip -qo "$SOURCEIPA" -d extracted APPLICATION=$(ls extracted/Payload/) cp -R ~/Desktop/tk-tweak-temp-folder/extracted/Payload/$APPLICATION ~/Desktop/tk-tweak-temp-folder/ echo "注入" ${DYLIB##*/} "到" $APPLICATION cp ${DYLIB##*/} ${LIBSUBSTRATE##*/} $APPLICATION/ echo "删除" ${APPLICATION##*/} "中 watch 相关文件" rm -rf ~/Desktop/tk-tweak-temp-folder/$APPLICATION/*watch* rm -rf ~/Desktop/tk-tweak-temp-folder/$APPLICATION/*Watch* echo "是否注入" ${DYLIB##*/} ":(Y/N)" insert_dylib @executable_path/${DYLIB##*/} $APPLICATION/${APPLICATION%.*} > insert_dylib.log echo "注入成功" cd $APPLICATION rm -rf ${APPLICATION%.*} mv ${APPLICATION%.*}_patched ${APPLICATION%.*} echo "正将" ${APPLICATION%.*}_patched "覆盖为" ${APPLICATION%.*} cd ~/Desktop/tk-tweak-temp-folder/ echo "删除临时文件" rm -rf ${SOURCEIPA##*/} ${DYLIB##*/} ${LIBSUBSTRATE##*/} extracted insert_dylib.log depend.log grep_result.log echo "打开 tk-tweak-temp-folder 文件夹" open ~/Desktop/tk-tweak-temp-folder open /Applications/iOS/ App/ Signer.app
以上就是整个 iOS 逆向的主要流程(虽然hook的代码很渣),其中注入动态库与打包重签名的工具不止一种,可以根据自己的爱好网上查找。本人也是踩了不少坑不断摸索来的,比如由于tweak工程名的问题,导致使用 iOS App Signer
打包重签名的一直error:
Error verifying code signature。希望能给刚入iOS 逆向坑的人一点帮助,文章中如有错误欢迎指出。由于涉及只是工具的使用,涉及到的原理比较薄弱,若想深入了解可以去阅读下参考文档。