未越狱iPhone中使用Frida

现时越狱越来越难了, iOS 10.2.1 - 11都没有有效的越狱. 没有有效的越狱, 我们就无法安装 frida-server, 也无法访问 localstorage, keychain 等.

本文为此阐述了如何在未越狱 iPhone 中运行 Frida.

项目地址: Github

1. Prerequisite

  • python3.4+
  • pip3
  • virtualev (optional, but highly recommended)
  • XCode
  • nvm (optional, but highly recommended)
  • applesign
  • insert_dylib
  • ios-deploy

1.1 Installing python3 & pip3

Since Mac has python2 preinstalled, we need to install python3 & pip3 separately.

$ brew install python3

After installation, you would have python3 and pip3. However, as python2 and python3 co-exist, you need to run python, pip for python2, python3, pip3 for python3.

NIN: If homebrew is yet to be installed, visit Homebrew — The missing package manager for macOS for details on installation.

1.2 Installing virtualenv

$ pip3 install --user virtualenv

1.3 Installing objection

$ mkdir objection
$ cd objection
$ virtualenv -p python3 venv  
$ source venv/bin/activate  
$ pip3 install -U objection

1.4 NVM

NIN: It is recommended using nvm to manage node & npm. Visit Github for more details.

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash

After running above command, it would clone the nvm repository to ~/.nvm. If after installation, it still complains nvm not found, add below lines to your profile (~/.bash_profile, ~/.zshrc, ~/.profile, or ~/.bashrc), depending on what shell are you using.

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm

NIN: 6.10.3 is used for this tutorial.

$ nvm install 6.10.3
$ node -v
v6.10.3

1.5 Installing applesign

$ npm install -g applesign

$ which applesign
/Users/its/.nvm/versions/node/v6.10.3/bin/applesign

1.6 Installing insert_dylib

$ git clone https://github.com/Tyilo/insert_dylib
$ cd insert_dylib
$ xcodebuild
$ cp build/Release/insert_dylib /usr/local/bin/insert_dylib

$ which insert_dylib
/usr/local/bin/insert_dylib

NIN: If xcodebuild is not found, make sure you have installed command line tools with xcode-select --install.

1.7 Installing ios-deploy

$ npm install -g ios-deploy

$ which ios-deploy
/usr/local/bin/ios-deploy

2. Patching iOS Applications

2.1 XCode Developer Certificate

First and foremost, you need to register for an Apple Developer account. A free one works fine, but you need to keep in mind that you will only be allowed to run patched applications for 7 days, before repeating the patching/signing/installation process again

To register:

  1. Visit https://developer.apple.com/register/ and agree to the license agreement.
  2. Sign in with your AppleID in XCode by browsing to "XCode" -> "Preferences" -> "Accounts" and clicking on the "+" at the bottom left.
  3. Click on "Manage Certificates" and click on the "+" drop down, selecting "iOS Development". XCode will generate a new code signing certificate for you to use.
  4. Click "Done".

Once you have a developer account signed in to in XCode, you will now be able to sideload applications and run them on iOS devices. You can also check for code signing certificates that are now available in a terminal:

$ security find-identity -p codesigning -v
  1) CC295C1137E6F2A08B26Axxxxxx "iPhone Developer: xxxxx@gmail.com (RF6X7S2JSJ)"
  2) 00DB9FD78FA8E21CE3793xxxxxx "iPhone Developer: xxxxx@sina.com (4X74WJ9LKM)" (CSSMERR_TP_CERT_REVOKED)
  3) DA44B44E56769CF64B1D2xxxxxx "iPhone Developer: xxxxx@sina.com (4X74WJ9LKM)"
     3 valid identities found

2.2 mobileprovision

With XCode ready we can now generate the .mobileprovison file we need. This file contains some certificate information as well as the entitlements groups for the application. To generate the .mobileprovision file, all we need to do is build and deploy a blank iOS application to an iOS device. The build process will leave an embedded.mobileprovision file in ~/Library/Developer/Xcode/DerivedData/ for us to pick up and re-use. When you run the objection patchipa command, it will automatically search for a valid embedded.mobileprovision file in ~/Library/Developer/Xcode/DerivedData/ to use.

So, to build and deploy a blank iOS application using XCode to get the updated embedded.mobileprovision file you need:

  1. Start XCode and select "Create new XCode Project"
  2. Select "iOS" -> "Single View Application" and hit next.
  3. Fill in a Product name, choose a unique organization identifier and hit next.
  4. Choose where to save the project and finally click on "Create".
  5. In the projects root, under the "General" tab, ensure that there are no errors with the signing certificate. Most of the time, XCode is pretty verbose with what needs to be done to fix any errors you may encounter, so just take a moment to read.
  6. When done, ensure your iOS device is plugged in. Select it as the target device in the top left corner, and hit the big play button. This process will compile the blank app for the target device, and leave that embedded.mobileprovision file on disk for us to pick up later.
  7. You should now see the application has been installed on your iPhone. Then trust your iTunes account to run code on your iOS device.
    Settings App -> General -> Profiles & Device Management -> Select your iTunes account from the "Developer App" section -> Select "Trust".

2.3 Patching

$ objection patchipa --source my-app.ipa --codesign-signature CC295C1137E6F2A08B26Axxxxxx

It should work like a charm. A new IPA with Frida.dylib bundled will be created on the current path.

3. Running

3.1 Troubleshooting

NIN: Make sure you are using ios-deploy with version 1.9.2. Otherwise, you may find an error - [ !! ] Unable to mount developer disk image. (Ref: https://github.com/phonegap/ios-deploy/issues/221)

------ Debug phase ------
Starting debug of 63e8000a2b7f13b82caff22b8988c7b8424604e3 (N49AP, iPhone 5c (Global/CDMA), iphoneos, armv7s) a.k.a. 'Illnino的 iPhone' connected through USB...
[  0%] Looking up developer disk image
2017-10-30 23:13:05.504 ios-deploy[13314:7893719] [ !! ] Unable to mount developer disk image. (e8000033)

Run below command to install the latest version of ios-deploy.

npm install -g ios-deploy

3.2 Deploying the patched app

  1. Extract the IPA package with unzip my-app.ipa. This should leave you with a Payload/ directory.
  2. Attach your iOS device to your computer via USB and ensure that it is unlocked.
  3. Run ios-deploy with ios-deploy --bundle Payload/my-app.app -W -d where my-app.app is the folder where your application lives.
$ unzip my-app.ipa
$ objection ios-deploy --bundle Payload/MyApp.app -W -d
[....] Waiting for iOS device to be connected
[....] Using 63e8000a2b7f13b82caff22b8988c7b8424604e3 (N49AP, iPhone 5c (Global/CDMA), iphoneos, armv7s) a.k.a. 'Illnino的 iPhone'.
------ Install phase ------
[  0%] Found 63e8000a2b7f13b82caff22b8988c7b8424604e3 (N49AP, iPhone 5c (Global/CDMA), iphoneos, armv7s) a.k.a. 'Illnino的 iPhone' connected through USB, beginning install
[  5%] Copying /Users/its/Project/tools/iOS/objection/Payload/MyApp.app/META-INF/ to device
[REDACTED]
[ 52%] CreatingStagingDirectory
[ 57%] ExtractingPackage
[ 60%] InspectingPackage
[ 60%] TakingInstallLock
[ 65%] PreflightingApplication
[ 65%] InstallingEmbeddedProfile
[ 70%] VerifyingApplication
[ 75%] CreatingContainer
[ 80%] InstallingApplication
[ 85%] PostflightingApplication
[ 90%] SandboxingApplication
[ 95%] GeneratingApplicationMap
[100%] Installed package Payload/MyApp.app
------ Debug phase ------
Starting debug of 63e8000a2b7f13b82caff22b8988c7b8424604e3 (N49AP, iPhone 5c (Global/CDMA), iphoneos, armv7s) a.k.a. 'Illnino的 iPhone' connected through USB...
[  0%] Looking up developer disk image
[ 95%] Developer disk image mounted successfully
[100%] Connecting to remote debug server
-------------------------
(lldb) command source -s 0 '/tmp/869AF7F1-B18C-4049-8F0F-9A0973C76031/fruitstrap-lldb-prep-cmds-63e8000a2b7f13b82caff22b8988c7b8424604e3'
Executing commands in '/tmp/869AF7F1-B18C-4049-8F0F-9A0973C76031/fruitstrap-lldb-prep-cmds-63e8000a2b7f13b82caff22b8988c7b8424604e3'.
(lldb)     platform select remote-ios --sysroot '/Users/its/Library/Developer/Xcode/iOS DeviceSupport/9.3.1 (13E238)/Symbols'
  Platform: remote-ios
 Connected: no
  SDK Path: "/Users/its/Library/Developer/Xcode/iOS DeviceSupport/9.3.1 (13E238)/Symbols"
(lldb)     target create "/Users/its/Project/tools/iOS/objection/Payload/MyApp.app"
Current executable set to '/Users/its/Project/tools/iOS/objection/Payload/MyApp.app' (arm64).
(lldb)     script fruitstrap_device_app="/private/var/containers/Bundle/Application/CBC05B30-14E0-4542-969B-4B3505A7149A/MyApp.app"
(lldb)     script fruitstrap_connect_url="connect://127.0.0.1:64641"
(lldb)     target modules search-paths add /usr "/Users/its/Library/Developer/Xcode/iOS DeviceSupport/9.3.1 (13E238)/Symbols/usr" /System "/Users/its/Library/Developer/Xcode/iOS DeviceSupport/9.3.1 (13E238)/Symbols/System" "/private/var/containers/Bundle/Application/CBC05B30-14E0-4542-969B-4B3505A7149A" "/Users/its/Project/tools/iOS/objection/Payload" "/var/containers/Bundle/Application/CBC05B30-14E0-4542-969B-4B3505A7149A" "/Users/its/Project/tools/iOS/objection/Payload" /Developer "/Users/its/Library/Developer/Xcode/iOS DeviceSupport/9.3.1 (13E238)/Symbols/Developer"
(lldb)     command script import "/tmp/869AF7F1-B18C-4049-8F0F-9A0973C76031/fruitstrap_63e8000a2b7f13b82caff22b8988c7b8424604e3.py"
(lldb)     command script add -f fruitstrap_63e8000a2b7f13b82caff22b8988c7b8424604e3.connect_command connect
(lldb)     command script add -s asynchronous -f fruitstrap_63e8000a2b7f13b82caff22b8988c7b8424604e3.run_command run
(lldb)     command script add -s asynchronous -f fruitstrap_63e8000a2b7f13b82caff22b8988c7b8424604e3.autoexit_command autoexit
(lldb)     command script add -s asynchronous -f fruitstrap_63e8000a2b7f13b82caff22b8988c7b8424604e3.safequit_command safequit
(lldb)     connect
(lldb)     run
success
2017-10-30 23:20:02.119 MyApp[8159:1933074] Frida: Listening on 127.0.0.1 TCP port 27042

At the very last line, you should see Frida-server is running on the iPhone. Leave this tab open.

3.3 Using Frida

Open another tab.

➜  App frida-ps -Uai
 PID  Name    Identifier
----  ------  ---------------
8176  Gadget  re.frida.Gadget
➜  App frida -U 8176
     ____
    / _  |   Frida 10.6.10 - A world-class dynamic instrumentation framework
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at http://www.frida.re/docs/home/

[iPhone::PID::8176]->

3.4 Using objection

Alternatively, you could take full advantage of objection which has a list of pre-defined frida scripts.

com.myapp.mybank on (iPhone: 9.3.1) [usb] # ios keychain dump
Note: You may be asked to authenticate using the devices passcode or TouchID
Get all of the attributes by adding `--json keychain.json` to this command
Reading the iOS keychain...

Class                     Account        Service                     Generic    Data
------------------------  -------------  --------------------------  ---------  ----------------------------------
kSecClassGenericPassword  ATTRIBUTE_KEY  myapp-KEYCHAIN-SERVICE-NAME             UUID
kSecClassGenericPassword  myapp-APP-UUID  myapp-KEYCHAIN-SERVICE-NAME             017F435248791246F0B29F8A3A5C93917E

Bonus

embedded.mobileprovision

这是一个 provisioning profile 集成到 App 中的. 假如机器上没有这个 profile,iOS 会在安装 App 的时候把它也安装上去.

这个 Profile 其实就是一个 plist file, 记录了一系列的 permission. 假如无法安装, 可以查看UDID 是否绑定在该provisioning file 中.

以下 command 会显示 mobileprovision 绑定那个 UDID.

security cms -D -i /path/to/appName.mobileprovision

Ref

Show Comments