一般来说,软件逆向工程可以看作系统分析
和代码分析
两个阶段的有机结合。在系统分析
阶段,我们从整体上观察目标程序的行为特征,文件的组织架构,从而找到我们感兴趣的地方。代码分析
阶段,利用各种工具对程序本身的二进制文件进行分析,从而了解目标软件的实现,进而借鉴其设计思路、内部算法、反思教训等。
1.设备越狱 通过爱思
、PP助手
、同步助手
、unc0ver
等工具,对已经备份过的设备进行越狱;
2.安装插件 2.1.OpenSSH OpenSSH 会在 iOS 设备上安装 SSH 服务,从而给外界提供了一个通过 SSH 接入 iOS 设备的途径。常用的有两个命令:
ssh
,用于远程登录:
1 $ ssh root@192 .168.31 .242
scp
,用于远程拷贝文件:
1 2 3 4 // 本地拷贝到手机 $ scp /path/ localFile root@192.168 .31.242 :/path/ remoteFile // 手机拷贝到本地 $ scp root@192.168 .31.242 :/path/ remoteFile /path/ localFile
使用 Cydia 在线源直接搜索 OpenSSH 即可找到并安装。
注意:iOS设备上有 root
和mobile
两个用户,在安装完 SSH 后记得修改默认登录密码“alpine”,防止病毒通过 ssh 以 root 用户身份登录设备。安装SSH和修改密码的方法,一般在Cydia的首页都有说明,可按照说明一步步操作即可。
2.2.Cycript Cycript 是逆向工程中用来进行动态分析的利器,能够让开发人员在命令行下和应用交互,在执行时查看和改动应用,如帮助我们在运行时查看应用视图层级、函数等信息。
从 Cydia 自带源Cydia/Telesphoreo
下载安装。
在 官网 中找到cycript_0.9.501_iphoneos-arm.deb
和libffi_1:3.0.10-5_iphoneos-arm.deb
这两个安装包,下载到 MacOS 上。用 sftp 上传上面两个文件到设备上:
1 2 3 $ sftp root@192.168 .31.242 sftp> put cycript_0.9.501 _iphoneos-arm.deb sftp> put libffi_1:3.0 .10 -5 _iphoneos-arm.deb
上传进度100%后,用 dpkg -i来安装deb包:
1 2 $ ssh root@192 .168.31 .242 ~ root
ssh登录后,输入以下命令:
执行 cycript,如果出现cy#符号,则安装完毕:
3.dumpdecrypted.dylib 从 Github 上下载 dumpdecrypted 源码:
1 2 3 4 5 $ git clone https://gi thub.com/stefanesser/ dumpdecrypted.git dumpdecrypted Cloning into 'dumpdecrypted' ... remote: Counting objects: 31 , done. remote: Total 31 (delta 0 ), reused 0 (delta 0 ), pack-reused 31 Unpacking objects: 100 % (31 /31 ), done.
进入dumpdecrypted
目录查看有哪些文件:
1 2 3 $ cd dumpdecrypted/$ ls Makefile README dumpdecrypted.c
编译 dumpdecrypted.dylib
1 2 3 4 5 6 7 $ make `xcrun --sdk iphoneos --find gcc` -Os -Wimplicit -isysroot `xcrun --sdk iphoneos --show-sdk-path ` -F`xcrun --sdk iphoneos --show-sdk-path `/System/Library/Frameworks -F`xcrun --sdk iphoneos --show-sdk-path `/System/Library/PrivateFrameworks -arch armv7 -arch armv7s -arch arm64 -c -o dumpdecrypted.o dumpdecrypted.c 2018 -07 -27 22 :09 :19.065 xcodebuild[1941:437762] [MT] PluginLoading: Required plug-in compatibility UUID 426 A087B-D3AA-431 A-AFDF-F135EC00DE1C for plug-in at path '~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/VVDocumenter-Xcode.xcplugin' not present in DVTPlugInCompatibilityUUIDs `xcrun --sdk iphoneos --find gcc` -Os -Wimplicit -isysroot `xcrun --sdk iphoneos --show-sdk-path ` -F`xcrun --sdk iphoneos --show-sdk-path `/System/Library/Frameworks -F`xcrun --sdk iphoneos --show-sdk-path `/System/Library/PrivateFrameworks -arch armv7 -arch armv7s -arch arm64 -dynamiclib -o dumpdecrypted.dylib dumpdecrypted.o ld: warning: directory not found for option '-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/PrivateFrameworks' ld: warning: directory not found for option '-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/PrivateFrameworks' ld: warning: directory not found for option '-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/PrivateFrameworks'
make
命令执行完之后会在当前目录下生成一个dumpdecrypted.dylib
文件,这就是后面用来砸壳用的榔头。
1 2 3 $ ls Makefile dumpdecrypted.c dumpdecrypted.o README dumpdecrypted.dylib
4.定位进程 关闭设备中所有的应用,打开央视影音
(Cbox)。
通过ssh,以 root 身份登录设备:
1 $ ssh root@192 .168.31 .242
用adv-cmds
命令行插件自带的ps
命令,定位央视影音
进程:
1 2 3 4 5 6 7 8 9 10 11 ~ root# ps -e | grep /var/ 5193 ?? 0 :01.90 /var/ containers/Bundle/ Application/BE3F444E-5002-40A6-AFF3-71DB398DAB18/M obileMail.app/MobileMail 5195 ?? 6 :05.27 /var/ containers/Bundle/ Application/B3248F78-A0C2-4965-8E2F-B3CEE38E71C0/ DYZB.app/DYZB 5218 ?? 12 :15.94 /var/ containers/Bundle/ Application/9437BC53-681D-4F41-889C-5DE6DAAD33CD/ Cbox.app/Cbox 5317 ?? 0 :40.58 /var/ containers/Bundle/ Application/6EE6BF3A-94DB-4356-811C-5CD35CEAD4CC/ XMFilmTelevision.app/XMFilmTelevision 5860 ?? 0 :00.58 /private/ var/containers/ Bundle/Application/ C73F08EB-2 C9B-4169 -9 C2C-8 E933417465B/BlockerTest.app/ PlugIns/Blocker.appex/ Blocker 5861 ?? 0 :25.78 /private/ var/containers/ Bundle/Application/ EA8607BE-AD62-4179 -B060-E939B00FD212/Shadowrocket.app/ PlugIns/Today.appex/ Today 5862 ?? 0 :00.84 /private/ var/containers/ Bundle/Application/ B6364A33-5 BEF-4059 -8491 -EF8DB484176C/Shortcuts.app/ PlugIns/ShortcutsWidget.appex/ ShortcutsWidget 5863 ?? 0 :01.37 /private/ var/containers/ Bundle/Application/ B2D9F8D2-3853 -4 BE6-8500 -8 D4FE4140A4E/Weather.app/ PlugIns/WeatherAppTodayWidget.appex/ WeatherAppTodayWidget 6034 ?? 0 :00.16 /private/ var/containers/ Bundle/Application/ C73F08EB-2 C9B-4169 -9 C2C-8 E933417465B/BlockerTest.app/ PlugIns/Tunnel.appex/ Tunnel 6247 ttys000 0 :00.02 grep /var/
第一行的数字是进程对应的PID,最后一行就是进程所在的目录。使用ps -e
命令时终端里会列出一堆系统进程和应用,它们往往以/usr/
和/System/
开头,而我们下载的应用一般以/var/
开头,所以这里可以添加一个过滤条件ps -e | grep /var/
,这样结果就简化许多。
因为设备上只打开了一个应用,所以含有/var/containers/Bundle/Application/
字样的结果就是storeApp可执行文件的全路径,这里我需要记录下来的是央视影音
这个进程:
1 /var/ containers/Bundle/ Application/9437BC53-681D-4F41-889C-5DE6DAAD33CD/ Cbox.app/Cbox
5.Documents 目录 通过cycript -p
命令监听 Cbox
进程:
也可以通过Cbox
的PID
来监听:
接着在cy#
后面输入:
1 cy# [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask ]
这一步是用 Cycript 找出Cbox
的Documents
目录,输出结果:
1 #"/var/mobile/Containers/Data/Application/D02582B3-66 D3-4 EF1-A6C2-6129 D4E1B9CA/Documents/"
这里/var/mobile/Containers/Data/Application/D02582B3-66D3-4EF1-A6C2-6129D4E1B9CA/Documents/
就是我们要找的目录,Ctrl + D
退出 Cycript 模式。
6.拷贝动态库 将步骤#3 中编译的dumpdecrypted.dylib
拷贝到刚才的Documents
目录下:
1 $ scp /Users /davidli/Documents /dumpdecrypted/dumpdecrypted.dylib root@192 .168.31 .242 :/var/mobile/Containers/Data/Application/D02582B3- 66 D3-4 EF1-A6C2 -6129 D4E1B9CA/Documents /
另外,你也可以使用iTools
或者iFunBox
等工具来完成。
7.砸壳 从应用商店下载的应用是被苹果特殊加密过的,可执行文件被套上了一层保护壳,想 dump 出它的头文件等,需要先解密应用的可执行文件,这个过程就被称为砸壳
。
dumpdecrypted
就是一款有名的砸壳软件,其工作原理是:将应用运行起来(iOS系统会先解密应用可执行文件再启动),然后遍历 Load Command
中所有 LC_ENCRYPTION_INFO
或 LC_ENCRYPTION_INFO_64
指令的信息,将对应解密后的数据从内存中 dump 出来,复写到 mach-o 文件中,得到一个新的可执行程序。
1 2 ~ root# cd /var/m obile/Containers/ Data/Application/ D02582B3-66 D3-4 EF1-A6C2-6129 D4E1B9CA/Documents/ root# DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/ containers/Bundle/ Application/9437BC53-681D-4F41-889C-5DE6DAAD33CD/ Cbox.app/Cbox
这里的DYLD_INSERT_LIBRARIES
是一个环境变量,我们的dumpdecrypted.dylib
就是要通过这个环境变量注入到应用中。
上述命令执行完毕后会在当前目录生成Cbox.decrypted
,即砸壳之后 App 的可执行文件。
1 2 root Cbox.decrypted dumpdecrypted.dylib ...
8.拷贝.decrypted 将 Cbox.decrypted 拷贝到自己的电脑上:
1 $ scp root@192 .168.31 .242 :/var/mobile/Containers/Data/Application/D02582B3- 66 D3-4 EF1-A6C2 -6129 D4E1B9CA/Documents /Cbox .decrypted /Users /davidli/Documents /decrypted
9.反汇编 接下来就可以对此砸壳后的文件进行静态分析了,如用class-dump
导出 App 的头文件、用 Hopper Disassembler
查看伪代码。
9.1.class-dump class-dump 是用来 dump 目标对象的 类、分类、协议信息的工具,这一点与otool
类似。它利用 OC 语言的 runtime 特性,将存储在 Mach-O 文件中的头文件信息提取出来,并生成对应的.h文件。在 传送门 下载最新安装包,然后把class-dump
文件放到/usr/local/bin
目录下, 在终端输入class-dump
,显示class-dump
的版本后,就可以正常使用 class-dump 命令了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ class -dumpclass -dump 3.5 (64 bit) Usage: class -dump [options] <mach-o-file > where options are: -a show instance variable offsets -A show implementation addresses --arch <arch > choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64, armv6, armv7, armv7s, arm64) -C <regex> only display classes matching regular expression -f <str> find string in method name -H generate header files in current directory, or directory specified with -o -I sort classes, categories, and protocols by inheritance (overrides -s) -o <dir > output directory used for -H -r recursively expand frameworks and fixed VM shared libraries -s sort classes and categories by name -S sort methods by name -t suppress header in output, for testing --list -arches list the arches in the file , then exit --sdk-ios specify iOS SDK version (will look in /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS<version >.sdk --sdk-mac specify Mac OS X version (will look in /Developer/SDKs/MacOSX<version >.sdk --sdk-root specify the full SDK root path (or use --sdk-ios/--sdk-mac for a shortcut)
使用 class-dump 导出二进制文件中的.h
1 class -dump [--arch armv7] -H -s /目标二进制文件路径 -o / 导出目录
导出的文件列表如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 $ lsAAAlertItem . hAACloseNotifyReq . hAACloseNotifyRes . hAACloseReq . hAACloseRes . hAALaunchByMoneyReq . hAALaunchByMoneyRes . hAALaunchByPersonReq . hAALaunchByPersonRes . hAALaunchItem . hAAListRecord . hAAOperationReq . hAAOperationRes . hAAPayReq . hAAPayRes . hAAPaySuccReq . hAAPaySuccRes . hAAPayUrgeReq . hAAPayUrgeRes . hAAPayer . hAAQueryDetailReq . hAAQueryDetailRes . hAAQueryListReq . hAAQueryListRes . hAARealNameItem . h ABNewPersonViewControllerDelegate-Protocol . h ABPeoplePickerNavigationControllerDelegate-Protocol . h ...
9.2.Hopper class-dump 只能查看目标 APP 的头文件,无法查看.m 文件和具体的代码,所以就需要使用到反汇编器。这里介绍的是Hopper Disassembler
,它是一款二进制反汇编器,能反编译出二进制文件中的所有函数和实现,包括伪代码以及控制流图(Control Flow Graph),支持 ARM 指令集并针对 OC 做了优化。官网 传送门 ,下载试用版就够用了。
将目标二进制文件拖到 Hopper Disassembler
面板中:(如果是第三方市场下载的越狱应用,须将.ipa
文件后缀改为.zip
,解压后在/Payload
目录下找到.app
文件,右键 显示包含内容
即可看到目标二进制文件)
选择需要反编译的架构之后点OK
,接下来 Hopper 就会自动加载二进制文件的各个segment
。加载完成后即可看到如下界面:
左边是符号 Label 等区域,中间是 ARM 的汇编代码,右边是相关信息栏。
在 Label 区搜索栏中输入想要的函数名,双击搜索结果列表中对应的行即可自动跳转到该方法的内存地址处。不过这里显示的都是 ARM 汇编指令,其中还包括了很多r0~r8
等寄存器,阅读性不高。所以可以使用上面提到的伪代码功能,快捷键 Option + Enter
或者点击右上角面板中的 if(b)f(x)
按钮即可自动弹出伪代码视图,这些就是具体的代码逻辑:
ps: Hopper 除了可以查看汇编代码以外,还可以直接对 Mach-O 文件进行修改,然后重新生成二进制文件,替换原二进制文件后重新打包即可实现某些特殊目的,如去广告、微信自动抢红包、VIP加速等。这些内容及ARM汇编指令待后面继续研究。。
相关参考:
#©沙梓社·吴航【iOS应用逆向工程】
#©iosre论坛