iOS应用安全—— 基础篇

越狱

几种类型的越狱:

  • Tethered jailbreaks 不完美越狱,重启后无法保留
  • Semi-tethered jailbreaks 半完美越狱,必须通过连接电脑越狱,设备启动后会自动进入非越狱模式
  • Semi-untethered jailbreaks 半完美越狱,设备启动能自己进入到越狱模式,但内核的代码签名校验不会被自动禁用,需要通过启动一个应用完成
  • Untethered jailbreaks 完美越狱,一次越狱后即可永久越狱

注意:
如果设备已经越狱,切勿升级系统,否则会丢失越狱

根据iOS版本判断设备是否可以越狱:
Can I Jailbreak? https://canijailbreak.com/

几个iPhone越狱相关的资源:

Cydia

通常在越狱完成后会自动安装Cydia,下面介绍几个在Cydia下需要安装的工具:

  1. openssh
    默认的ssh账号是root,默认密码为alpine
  2. Frida
    在Cydia中添加源 https://build.frida.re后直接搜索安装
  3. BigBoss Recommended Tools
    unix命令行工具,iOS系统不提供,如wget, unrar, less,sqlite3等
  4. Class Dump
    提取Mach-O文件信息
  5. Substrate
    Hook工具
  6. AppList
    查询所有安装的app

Needle

Needle是iOS平台上的一套动态测试,由mwr开发,类似于Android平台上的Drozer,但因系统的不同而功能不一。

以下为mac上配置Needle的过程:

  1. 安装依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #Core dependencies
    brew install python
    brew install libxml2
    xcode-select --install

    #Python packages
    sudo -H pip install --upgrade --user readline
    sudo -H pip install --upgrade --user paramiko
    sudo -H pip install --upgrade --user sshtunnel
    sudo -H pip install --upgrade --user frida
    sudo -H pip install --upgrade --user biplist
    #sshpass
    brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/master/Library/Formula/sshpass.rb

    #mitmproxy
    wget https://github.com/mitmproxy/mitmproxy/releases/download/v0.17.1/mitmproxy-0.17.1-osx.tar.gz
    tar -xvzf mitmproxy-0.17.1-osx.tar.gz
    sudo cp mitmproxy-0.17.1-osx/mitm* /usr/local/bin/

    #Download source
    git clone https://github.com/mwrlabs/needle.git
  2. 手机上安装needle代理
    Cydia添加源http://mobiletools.mwrinfosecurity.com/cydia/,搜索NeedleAgent安装即可

  3. 使用needle

    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
    30
    31
    32
    $ python needle.py
    __ _ _______ _______ ______ ______
    | \ | |______ |______ | \ | |______
    | \_| |______ |______ |_____/ |_____ |______
    Needle v1.0 [mwr.to/needle]
    [MWR InfoSecurity (@MWRLabs) - Marco Lancini (@LanciniMarco)]

    [needle] > help
    Commands (type [help|?] <topic>):
    ---------------------------------
    back exit info kill pull reload search shell show use
    exec_command help jobs load push resource set shell_local unset

    [needle] > show options

    Name Current Value Required Description
    ------------------------ ------------- -------- -----------
    AGENT_PORT 4444 yes Port on which the Needle Agent is listening
    APP no Bundle ID of the target application (e.g., com.example.app). Leave empty to launch wizard
    DEBUG False yes Enable debugging output
    HIDE_SYSTEM_APPS False yes If set to True, only 3rd party apps will be shown
    IP 127.0.0.1 yes IP address of the testing device (set to localhost to use USB)
    OUTPUT_FOLDER /root/.needle/output yes Full path of the output folder, where to store the output of the modules
    PASSWORD ******** yes SSH Password of the testing device
    PORT 2222 yes Port of the SSH agent on the testing device (needs to be != 22 to use USB)
    PUB_KEY_AUTH True yes Use public key auth to authenticate to the device. Key must be present in the ssh-agent if a passphrase is used
    SAVE_HISTORY True yes Persists command history across sessions
    SKIP_OUTPUT_FOLDER_CHECK False no Skip the check that ensures the output folder does not already contain other files. It will automatically overwrite any file
    USERNAME root yes SSH Username of the testing device
    VERBOSE True yes Enable verbose output

    [needle] >

iOS目录结构

OS X和iOS目录对比

upload successful

系统目录

  • /Applications:存放所有的系统App和来自于Cydia的App,不包括StoreApp

upload successful

  • /Developer:如果一台设备连接Xcode后被指定为调试机,Xcode就会在iOS中生成该目录
    • /Developer/Applications
    • /Developer/Library
    • /Developer/Tools
    • /Developer/usr

upload successful

  • /Library:存放一些提供系统支持的数据
    • /Library/MobileSubstrate/DynamicLibraries:存放Cydia安装程序的.plist和.dylib文件

upload successful

  • /System/Library:iOS文件系统中最重要的目录之一,存放大量系统组件
    • /System/Library/Frameworks:存放iOS中各种日常使用的framework
    • /System/Library/PrivateFrameworks:存放iOS中未公开的私有framework
    • /System/Library/CoreServices/SpringBoard.app:iOS桌面管理器

upload successful

  • /User:用户目录(mobile用户的home目录),实际指向/var/mobile,存放大量用户数据

upload successful

- /var/mobile/Media/DCIM:存放照片
- /var/mobile/Media/Recording:存放录音文件
- /var/mobile/Library/SMS:存放短信数据库
- /var/mobile/Library/Mail:存放邮件数据
- /var/mobile/Containers:存放Apple Store的App。

upload successful

- /var/mobile/Containers/Bundle:存放所有StoreApp的可执行文件和相关资源
- /var/mobile/Containers/Data:存放所有StoreApp的数据,沙盒目录的真实目录

应用沙盒

iOS系统把每个应用(StoreApp)以及数据都放到一个沙盒(sandbox)里面,应用只能访问自己沙盒目录里面的文件、网络资源等(也有例外,比如系统通讯录、照相机、照片等能在用户授权的情况下被第三方应用访问)

应用沙盒目录结构如下图:

upload successful

沙盒在逻辑上包含两个部分:Bundle ContainerData Container,两者在iOS文件系统中的位置是平行的,分别是/var/mobile/Containers/Bundle和/var/mobile/Containers/Data。

实际开发中,通过NSHomeDirectory()方法获取到沙盒根目录对应的是Data Container的路径。在越狱设备中可以通过ipainstaller工具获得app路径:

1
2
3
4
5
6
7
8
9
iPhone:~ root# ipainstaller -l
...
sg.vp.UnCrackable1

iPhone:~ root# ipainstaller -i sg.vp.UnCrackable1
...
Bundle: /private/var/mobile/Containers/Bundle/Application/A8BD91A9-3C81-4674-A790-AF8CDCA8A2F1
Application: /private/var/mobile/Containers/Bundle/Application/A8BD91A9-3C81-4674-A790-AF8CDCA8A2F1/UnCrackable Level 1.app
Data: /private/var/mobile/Containers/Data/Application/A8AE15EE-DC8B-4F1C-91A5-1FED35258D87

Bundle Container

bundle的概念源自于NeXTSTEP,它是一个按某种标准结构来组织的目录,Bundle中包含了二进制文件及运行所需的资源

正向开发中常见的App和framework都是以bundle的形式存在。在越狱iOS中常见的PreferenceBundle是一种依附于Settings的App,结构与App类似,本质也是bundle。Framework也是bundle,但framework的bundle中存放的是一个dylib(动态库),而非可执行文件。

在正向开发时,我们上传至App Store的ipa(iPhone Application)包,解压后会有一个Payload目录,其内部又包含一个.app目录,这个目录就是一个App的目录结构,也是一个bundle。

Bundle Container位于/var/mobile/Containers/Bundle/Application/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/主要用于存放静态资源,主要包含以下目录和文件:

  • MyApp.app
    存放可执行文件和资源文件,包括:打包时的资源文件、本地文件、可执行文件、.plist文件。这个目录不会被iTunes同步。

  • iTunesArtWork

  • iTunesMetadata.plist

    Data Container

    Data Container位于/var/mobile/Containers/Data/Application/YYYYYYYY-YYYY-YYYY-YYYYYYYYYYYY/,主要用于存放App运行时产生的动态数据,其主要包含以下目录和文件:

  • Documents
    存放应用运行时生成的并且需要保存的不可再生数据。注:iTunes或iCloud同步设备时会备份该目录
  • Library
    • Library/Caches 存放应用运行时生成且需要保存的可再生数据,比如网络请求,用户需要负责删除对应文件。iTunes或iCloud不同步。
    • Library/Preferences 存放偏好设置。使用NSUserDefaults写的设置数据都会保存在该目录下的一个plist文件中。iTunes或iCloud同步设备时备份该目录。
  • tmp
    存放应用下次启动不再需要的临时文件。当应用不再需要这些文件的时候,需要主动将其删除。(当应用不再运行的时候,系统可能会将此目录清空。)这个目录不会被iTunes同步。

沙盒路径获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 沙盒目录
NSLog(@"%@",NSHomeDirectory());

// MyApp.app
NSLog(@"%@",[[NSBundle mainBundle] bundlePath]);

// Documents
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [paths objectAtIndex:0];
NSLog(@"%@",docPath);

// Library
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libPath = [paths objectAtIndex:0];
NSLog(@"%@",libPath);

// tmp
NSLog(@"%@",NSTemporaryDirectory());

iOS二进制文件

iOS逆向的目标主要包含三类二进制文件:ApplicationDynamic LibraryDaemon

Application

Application,即我们最熟悉的App。App的Bundle目录有以下三个部分比较重要:

  • Info.plist
    Info.plist记录了App的基本信息,如:bundle identifier、可执行文件名、图标文件名等。

  • 可执行文件
    查看Info.plist,即可定位可执行文件

  • lproj目录
    lproj目录下存放的是各种本地化的字符串

系统App VS. StoreApp
/Applications/目录下存放系统App(包括CydiaApp);/var/mobile/Containers/目录下存放StoreApp。其区别在于:

  • 目录结构
    两种App的Bundle目录区别不大,都含有Info.plist、可执行文件、lproj目录等。只是Data目录的位置不同:StoreApp的数据目录在/var/mobile/Containers/Data/下,以mobile权限运行的系统App的数据目录在/var/mobile/下,以root权限运行的系统App的数据目录在/var/root/下。

  • 安装格式和权限
    Cydia App的安装格式一般是deb,StoreApp的安装格式一般是ipa。前者的属主用户和属主组一般是root和admin,能够以root权限运行;后者的属主用户和属主组都是mobile,只能以mobile权限运行。

Dynamic Library

Dynamic Library简称dylib,即动态链接库。在正向开发中,在Xcode工程中导入的各种framework,链接的各种lib,其本质都是dylib。

在iOS中,lib分为static和dynamic两种,其中static lib在编译阶段成为App可执行文件的一部分,会增加可执行文件的大小。dylib则不会改变可执行文件的大小,只有当App运行时调用到dylib时,iOS才会把它加载进内存,成为App进程的一部分。

dylib是逆向工程的重要目标类型,但其本身并不是可执行文件,不能独立运行,只能为别的进程服务,而且它们寄生在别的进程里,成为这个进程的一部分。因此,dylib的权限是由它寄生的那个App决定的,同一个dylib寄生在系统App和StoreApp里时的权限是不同的。

越狱iOS中,Cydia里的各种tweak无一不是以dylib的形式工作的。

Daemon

iOS的daemon主要由一个可执行文件和一个plist文件构成。iOS的根进程是launchd,其会在开机时检查/System/Library/LaunchDaemons和/Library/LaunchDaemons下所有格式符合规定的plist文件,然后启动对应的daemon。这里的plist文件与App中的Info.plist文件作用类似,即记录Daemon的基本信息。

配置文件(provisioning profile)和开发者证书

iOS有严格的代码签名检测,只用通过签名检测的代码才可以运行,而代码签名需要provisioning profile。

provisioning profile(供应配合文件)是由苹果签名的一个plist文件,Provisioning Profile文件包含了:证书,App ID,设备,后缀名为.mobileprovision。
upload successful
Provisioning Profile决定Xcode用哪个证书(公钥)/私钥组合(Key Pair/Signing Identity)来签署应用程序(Signing Product),将在应用程序打包时嵌入到.ipa包里。安装应用程序时,Provisioning Profile文件被拷贝到iOS设备中,运行该iOS App的设备也通过它来认证安装的程序。

如果要打包或者在真机上运行一个APP,一般要经历以下三步:

  • 首先,需要证书对应的私钥来进行签名,用于标识这个APP是合法、安全、完整的;
  • 其次,需要指明它的App ID,并且验证Bundle ID是否与其一致;
  • 最后,如果是真机调试,需要确认这台设备是否授权运行该APP。

获得Provisioning Profile和证书有两个途径:

  • 1. 注册iOS开发者账号
    https://developer.apple.com/programs/enroll/ 上注册开发者账号,个人开发者需要缴纳99$费用,这种途径开发的应用可以在apple store上发行。
    使用如下命令可以列出所有的账号:

    1
    2
    3
    $ security find-identity -p codesigning -v
    1) 61FA3547E0AF42A11E233F6A2B255E6B6AF262CE "iPhone Distribution: Vantage Point Security Pte. Ltd."
    2) 8004380F331DCA22CC1B47FB1A805890AE41C938 "iPhone Developer: Bernhard Müller (RV852WND79)"
  • 2. 使用iTunes账号
    apple允许配置一个免费的provisioning profile,允许在设备上对自己开发的应用进行调试,但不能上传到apple store上。

参考:

  1. https://www.jianshu.com/p/351be39f959e
  2. https://www.nccgroup.trust/au/about-us/newsroom-and-events/blogs/2016/october/ios-instrumentation-without-jailbreak/

参考资料:

  1. iOS逆向工程基础篇 http://chuquan.me/2018/02/06/ios-reverse-engineering-basis/
  2. owasp - Setting up a Testing Environment for iOS Apps https://github.com/OWASP/owasp-mstg/blob/master/Document/0x06b-Basic-Security-Testing.md
  3. iOS底层基础知识-文件目录结构 http://www.cnblogs.com/wujy/archive/2016/02/13/5188302.html
  4. mac os术语表 https://bbs.feng.com/read-htm-tid-249.html