美文网首页ios逆向与安全
iOS逆向与安全:基础篇

iOS逆向与安全:基础篇

作者: 繁华落尽丶lee | 来源:发表于2018-10-31 10:40 被阅读137次

    前言

    从本篇文章开始,笔者会整理iOS逆向相关的笔记。作为一位新人,希望通过整理笔记能够更好的理解和掌握知识。作为新人能力有限,在行文时难免出现错误欢迎批评和指正。

    前期准备:

    • 一台越狱的iOS设备,笔者使用iPad mini2系统iOS9.2.1(推荐使用iOS9.1或者可以完美越狱的系统)
    • 一台电脑,笔者使用的是MacBook Pro
    • 一条数据线

    如何越狱

    网上有很多教程帮助你来越狱,这里推荐两个网站:

    注意:在购买iOS设备时直接购买对应版本的系统,由于苹果官方关闭降级通道所以无法刷固件降级。

    越狱成功后,桌面上会出现一个叫做Cydia的应用,它是越狱后的App Store可以安装各种第三方的软件,比如:插件、补丁、APP等。该应用的作者Jay Freeman(saurik),一位骨灰级大神。

    必装插件或补丁

    • Apple File Conduit 2:可以访问整个iOS设备的文件系统。作者是Jay Freeman
    • AppSync unified: 可以绕过系统验证,随意安装、运行破解的IPA安装包。
    • PP助手: 一个应用商店,可以自由安装海量APP。
    • OpenSSH: 用于远程登录iOS设备。

    Mac 必备

    • iFunBox: 管理文件系统。
    • PP助手:一个应用商店。
    • iTerm2: 一款优秀的命令行工具
    • Alfred: 便捷搜索,自定义工作流,调高效率的工具

    配置远程登录

    SSH:Secure Shell的缩写,安全外壳协议,是一种可以为远程登录提供安全保障的协议。使用SSH可以把所有传输的数据进行加密,防止中间人攻击、DNS欺骗和IP欺骗。
    OpenSSH: 是SSH协议的免费开源实现。通过它让Mac登录iOS设备,在Cycript中搜索安装。

    使用密码登录

    如果iOS设备上已经安装了OpenSSH,此时就可以通过Mac终端登录iOS设备。前提,iOS设备和Mac需要处于相同WiFi环境下。在设置中查看iOS设备的IP地址。打开终端输入:

    ssh root@iOS设备IP地址
    // 回车,会提示时候建立连接输入yes即可。之后提示输入密码,默认密码是`alpine`。
    

    iOS设备上有两个默认账号:root,mobile。

    • root:最高权限账户,$HOME是/var/root。或者通过终端输入pwd查看。
    • mobile:普通权限账户,只能操作一些普通文件,$HOME是/var/mobile
    • mobile登录方式:ssh mobile@服务器地址。初始密码alpine
    • 修改root密码:passwd,修改mobile用户密码:passwd mobile

    公钥登录

    上面的密码登录方式比较麻烦,在每次登录时都需要输入密码。SSH提供了公钥登录,以省去密码的步骤。下面来看看公钥登录流程:
    将电脑端的SSH公钥保存在iOS设备中,登录时iOS设备端会向电脑端发送一个随机字符串,登录用户通过自己的私钥加密后发送给iOS端,iOS端通过事先存储好的公钥解密,如果解密成功,证明用户是可信的。

    查看$HOME/.ssh/目录,是否有id_rsa私钥和id_rsa.pub公钥,如果没有使用ssh-keygen生成。

    上传公钥到远程设备,通过ssh-copy-id命令。

    ssh-copy-id -i $HOME/.ssh/id_rsa.pub root@地址
    

    该条命令的作用是将id_rsa.pub公钥追加到iOS设备的$HOME/.ssh/authorized_keys文件中。

    cat $HOME/.ssh/authorized_keys //查看文件内容
    

    通过USB登录设备

    在WiFi不稳定的情况下,通过WiFi登录会非常的卡顿。可以通过接口转发的方法,使用USB SSH登录,保证连接的稳定性。

    方法很简单,首先安装libimobiledevice,然后使用里面提供iproxy把本地端口(例如:2222)映射到设备的TCP端口22,就可以通过本地的2222端口建立连接了。

    brew install libimobiledevice
    iproxy 2222 22
    ssh root@localhost -p 2222
    

    如果,每次输入iproxy 2222 22进行接口转换比较麻烦,可以将其配置到电脑的开机启动项中。创建~/Library/LaunchAgents/com.usbmux.iproxy.plist,填入一下:

    运行命令launchctl load ~/Library/LaunchAgents/com.usbmux.iproxy.plist使之生效。

    每次输入ssh root@localhost -p 2222也很麻烦,可以通过指定一个名称进行SSH连接,打开$HOME/.ssh/config文件,没有创建一个,写入一下内容。

    Host ipad 
    Hostname localhost
    User root
    Port 2222 
    

    通过以上配置,在终端输入ssh ipad即可登录iOS设备了。

    砸壳

    App Store下载应用都会进行加密,破解加密称为砸壳。本节记录在学习砸壳中遇到的问题和解决方法。

    三种砸壳方案:

    这三种方案网上很多教程,下面整理的是第三种方案简单高效。

    配置环境

    iOS设备和电脑都需安装Frida

    iOS设备安装Frida,打开Cydia添加软件源https://build.frida.re,之后搜索Frida安装。电脑端通过pip命令sudo pip install frida安装。

    接下来,克隆frida-ios-dump库到本地。仓库有两个分支分别对应python2.xpython3.x,需要根据本地Python版本来判断。

    // Mac终端
    python -V
    // 笔者:Python 3.6.3 :: Anaconda custom (64-bit)
    

    由于笔者配置的Python 3.x,切换到3.x分支安装firda-ios-dump依赖。在frida-ios-dump仓库目录下运行下面命令。

    sudo pip install -r requirements.txt --upgrade
    

    安装结束后,将越狱设备通过USB连上电脑进行端口映射:

    iproxy 2222 22
    

    到此配置结束,如果一切顺利就可以进行砸壳了。

    进行砸壳

    frida-ios-dump目录下,使用命令./dump.py -l查看应用名称和Bundle ID,通过命令./dump.py + 程序名字 or BundleID即可砸壳。当程序执行完,在当前目录中会出现一个xxx.ipa

    不过,通往成功的道路永远不是一帆风顺的,在运行./dump.py命令是出现了错误Waiting for USB device...。在这个issue中给出了解决方案。

    推荐文章一条命令完成砸壳

    Reveal配置

    Reveal是一款用于查看程序界面结构和调试界面的工具,可以在开发中动态修改调试代码修改程序的样式,也可以注入到第三方APP查看应用的界面结构。

    本节将会学习如何在越狱设备和非越狱设备上查看应用的结构。

    越狱设备集成Reveal

    笔者在越狱设备集成Reveal遇到了一个问题,新版的RevealServerFramework而旧版的是dylib,两者集成方式不同,但是网上很多资料都是过时的,所以这里给出新版的集成方式。

    首先在Cydia下载Reveal2Loader插件。插件安装后进入设置找到Reveal-->Enabled Applications选择要查看的App。例如:简书

    电脑端安装Reveal软件,正常情况下,打开手机上的简书APP会在Reveal中看到下图,点击进入即可查看界面结构。

    有时会出现RevealServer.framework版本问题,电脑端点击Help->Show Reveal Library in FinderFramework拷贝到手机Library/Frameworks目录下替换原来的。

    非越狱设备集成Reveal

    如果在开发中集成Reveal直接使用CocoaPods即可,在Podfile文件加入以下内容:

    //只在Debug模式下开启
     pod 'Reveal-SDK', :configurations => ['Debug']
    

    之后运行pod install即可集成。

    如果想在非越狱设备查看其它App的界面结构,需要使用MonkeyDev工具辅助完成。
    首先安装MonkeyDev,安装在GitHub仓库有文档。

    非越狱设备集成Reveal还需要目标App的脱壳ipa包。具体步骤查看文章:

    Cycript配置

    Cycript是允许开发者使用Objective-C++Javascript组合语法查看及修改运行时APP内存信息的工具。

    在越狱设备上安装

    Cycriptsaurik提供的工具,在Cydia中搜索Cycript并安装即可。

    安装完成后,用SSH登录设备输入cycript命令,就可以进入交互界面。

    在越狱设备上,可以使用一些命令注入目标进程,调试目标函数。下面例子:脚本注入到SpringBoard(桌面)中,使其弹出一个提示框。

    iPad:~ root# cycript -p SpringBoard
    cy# var alert = [[UIAlertView alloc] initWithTitle:@"Hello" message:@"Hello, wold!" delegate:nil cancelButtonTitle: @"cancel" otherButtonTitles: nil]
    #"<UIAlertView: 0x1348bd1f0; frame = (0 0; 0 0); layer = <CALayer: 0x1321c89b0>>"
    cy# [alert show]
    

    这是《iOS应用逆向与安全》中给出的一个简单的例子。

    Cycript分析应用

    上面例子中使用了一条命令cycript -p SpringBoard,通过该命令可以调试指定APP。该命令有两种使用方式,除了上面的cycript -p 程序名称,还可以通过cycript -p 程序进程ID。注意这里的程序的名称并不是APP的名称。

    查看程序的名称和进程ID可以通过安装一个插件adv-cmds。通过它使用ps命令查看当前运行程序的进程ID及可执行文件的路径。

    安装完成后,通过ps -A命令查看当前设备的进程ID和可执行文件的路径。同时,支持关键词搜索ps -A | grep 关键词

    例如,查看简书的路径和进程ID

    简书

    由于程序的进程ID是会发生变换的推荐使用名称。

    下面就以简书为例,学习如何使用cycript的使用。

    查看应用信息

    cy# NSHomeDirectory() // 沙盒路径
    cy# NSBundle.mainBundle().bundleIdentifier //BundleID
    cy# NSBundle.mainBundle().bundlePath //mainBundlePath
    cy# NSSearchPathForDirectoriesInDomains (NSDocumentDirectory , NSUserDomainMask , YES)[0] // Document Path
    cy# NSSearchPathForDirectoriesInDomains (NSCachesDirectory , NSUserDomainMask , YES)[0] // cache Path
    

    查看APPApplication信息,例如:查看简书的Application对象,为自定义的HGApplication

    cy# UIApp 
    # "<HGApplication: 0x154d49910>" 
    

    查看rootViewController

    cy# UIApp.keyWindow .rootViewController
    #"<HGTabBarController: 0x155006200>"
    

    还可以使用地址查看信息。例如:查看HGTabBarControllerview

    cy# #0x155006200.view
    #"<UILayoutContainerView: 0x154fca480; frame = (0 0; 1024 768); autoresize = W+H; layer = <CALayer: 0x154f65a20>>"
    

    另外Cycript提供了choose()函数选择某个类的实例数组。例如:学习简书中所有的Button类的所有实例数组。

    cy# choose(UIButton)
    [#"<UIButton: 0x157210600; frame = (0 8.5; 685 16); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x15705f020>>",
    #"<HGAvatarButton: 0x15724ead0; baseClass = UIButton; frame = (16 14.5; 45 45); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1572088b0>>".....]
    

    以上是cycript的基本用法。

    cycript高级用法

    每次要输入那么多的代码是在有点麻烦,能不能将常用的代码封装起来呢?答案是肯定的。

    Cycript本身是支持加载自己的脚本的,可以通过@import命令加载。例如:加载mjscript脚本。

    cy# @import mjcript
    

    关于如何将自己学的脚本添加到手机上查看【越狱-逆向】基于Cycript实现的一些实用函数文档,对如何添加,如何使用写的比较详细,这里就不再重复赘述。

    Class-dump

    本节学习如何使用工具导出第三方App的头文件,学习前需要补充点基础知识。

    Mach-O文件

    想让程序在设备上运行起来,需要将写好的代码生成可执行文件这样才能被操作系统所理解。比如,在Linux下可执行文件的格式是ELF,在Window中可执行文件是PE32/PE32+,而在MACiOS中是Mach-O格式。

    Mach-O的组成结构如下图:

    图片来自《Mach-O 文件格式探索》

    可以看的出 Mach-O 主要由 3 部分组成:

    • Mach-O 头(Mach Header):这里描述了 Mach-O 的 CPU 架构、文件类型以及加载命令等信息;
    • 加载命令(Load Command):描述了文件中数据的具体组织结构,不同的数据类型使用不同的加载命令表示;
    • 数据区(Data):Data 中每一个段(Segment)的数据都保存在此,段的概念和 ELF 文件中段的概念类似,都拥有一个或多个 Section ,用来存放数据和代码。

    如何获取Mach-O文件,在App Store中下载应用.ipa改成.zip格式,之后解压缩会在里面发现一个应用同名的文件。
    下面是简书的Mach-O文件:

    Class-dump使用

    class-dump的作用就是把Mach-O文件的class信息导出来生成头文件。

    下载后将其中的class-dump拷贝到/usr/local/bin目录下,就可以在终端使用class-dump命令。

    终端输入class-dump

    class-dump 3.5 (64 bit) (Debug version compiled Sep 17 2017 16:24:48)
    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 for /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS<version>.sdk
                           or /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS<version>.sdk)
            --sdk-mac      specify Mac OS X version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX<version>.sdk
                           or /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 mach-o路径 -o 头文件存储路径

    以简书App为例,使用之前砸壳的ipa文件,找到里面的Mach-O文件。

    class-dump -H Hugo -o ./Header
    

    在当前目录中会生成Header文件夹,里面包含所有的头文件。

    参考文章

    相关文章

      网友评论

        本文标题:iOS逆向与安全:基础篇

        本文链接:https://www.haomeiwen.com/subject/qabotqtx.html