This is an old revision of the document!
I had planned to look at the IOS app for some time. More recently, DJI decided to implement certificate pinning to try to stop us from seeing what data they are exchanging. My first thought “How rude!”.
To get under the hood, Hostile reminded me (again) that I should really look at Frida. Never done it before, but that is no excuse. I started looking, and I also found https://github.com/dpnishant/appmon and https://github.com/sensepost/objection
My first efforts were to get the basic frida functionality working since these apps depended on it. But this was a major fail. Frida on Python 2.x was not working for me all that well. And on 3.x, it failed to install due to some weird certificate errors that are OSX related.
After struggling, I downloaded the egg file and did the install manually. That worked. While researching, I concluded that Objection looked like a good fit for what I wanted, so I installed that also.
Below is the step by step of what I have done so far to get to this point.
We need several tools and dependencies in order to start. Many of these may be already installed on your mac if you've been involved in previous development work. However, its a good idea to check and install if necessary. Lets start with Xcode.
Go to App store, search and Install Xcode, this is a multi GB (around 5) install, so give it time.
Once complete, In terminal run the following commands
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install python3
brew install wget
brew install npm
Frida does not install cleanly on OSX using pip3. There is some weird ass certificate error. I've googled enough and decided to cheat. By putting the egg file in ~ it just works…
cd ~ wget `wget -q "https://pypi.python.org/pypi/frida" -O- | grep macosx | tail -1 | cut -d "\"" -f 2` pip3 install frida
pip3 install objection -U
npm install -g applesign
cd ~/Documents git clone https://github.com/Tyilo/insert_dylib cd insert_dylib xcodebuild cp build/Release/insert_dylib /usr/local/bin/insert_dylib
npm install -g ios-deploy
The Frida Gadget supports configuration parameters, that will allow the gadget to start in a variety of modes. We need to add this file to the IPA which will be read by the gadget during application load. This is particularly important, since we dont want to be dependent on the USB cable which is the default behaviour. At the moment, the behaviour here is to wait for frida to connect. Later, we can have our own gadget scripts that we will add into the IPA which will work standalone, without a need to have a network connection at all.
Download this file to ~/Documents
{ "interaction": { "type": "listen", "address": "0.0.0.0", "port": 27042, "on_load": "wait" } }
You will need a hex string to use below, which is your code-signing identity. Execute this command to get your value
security find-identity -p codesigning -v
It goes without saying you will need an IPA file to play with. Below, it is assumed you have downloaded your IPA file and saved it to “~/Documents/DJI GO 4.ipa”
NB: This MUST be a decrypted Go4 app. these are available to download here IOSMOD
cd ~/Documents rm -rf Payload mkdir -p "Payload/DJI GO 4.app/Frameworks" cp FridaGadget.config "Payload/DJI GO 4.app/Frameworks/" zip -r "DJI GO 4.ipa" Payload objection patchipa -s "DJI GO 4.ipa" --codesign-signature <your signature>
cd ~/Documents rm -rf Payload unzip *-frida-codesigned.ipa ios-deploy --bundle Payload/*.app -W
There are a few options for launching… Pick which is best for you
Device must be connected via USB and unlocked.
ios-deploy --bundle ~/Documents/Payload/*.app -W -d -m
this may also be of interest to trace some of the flow via lldb
ios-deploy --bundle ~/Documents/Payload/*.app -m -L
After launch is complete, you can disconnect the USB cable. Make sure you promptly launch Frida if you have it in “wait” mode, otherwise the app will fail to completely launch.
Ideally, we want to be able to launch the app from the phone with no connected USB cable. However, this is still failing. More testing needed. Until resolved, we can still launch via USB and then disconnect USB and start Frida.
Launch the objection user interface in a new terminal window. Objection is a front end with pre packaged Frida hooks.
objection explore
objection -N -h <mobile-device-ip> explore
Too many hooks to cover here… but the first one that was of interest to me is listed below.
ios sslpinning disable
Look at traffic that we can see, noting that most of it is now not SSL pinned. What is of interest?
Starting objection as described above is great - but there is one better option.
objection -N -h <mobile-device-ip> explore --startup-command "ios sslpinning disable"
This will automatically apply the SSL pinning bypass as soon as frida connects. By doing this, we appear to get access to all SSL comms without pinning, with the exception of traffic to https://statistical-report.djiservice.org … for reasons unknown at this time.
The default SSL pinning works out of the box with Frida/Objection - However, some DJI traffic is still not able to be read. Looking at lldb, we find:
DJI GO 4[5809:2007849] CFNetwork SSLHandshake failed (-9807)
This error message is defined here…
errSSLXCertChainInvalid = -9807, /* invalid certificate chain */
The default objection hook code is listed here for reference
We found that this was working for SOME requests, but not all. Particularly it appears on IOS10. Instead, you can replace the default hook with this and you should be good to go.
wget -q -O- https://raw.githubusercontent.com/vtky/Swizzler2/master/SSLKillSwitch.js > /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/objection/hooks/ios/pinning/disable.js
After making this change, DJI ssl pinning is your oyster. Crack it open!
Frida is new to me - I would like to build a hook that tricks the DJI go app into thinking the terms and conditions have already been accepted - even for a new install.
Install this first hook to bypass the terms and conditions screen and package it with the app.
Create more hooks and package with a frida tweak'd app to change the behaviour of the application. For example:
Interrupt process and halt
process interrupt
Set a breakpoint on SSLHandshake
b SSLHandshake
View registers
register read
If anything in the list looks like it has a CoreFoundation or Obj-C object, type the following:
po <register of object>
And finally, if you think there's a C string being pointed to by one of the variables, you can use this:
p (char*)<register of string>
ios cookies get ios nsuserdefaults get ios sslpinning disable
This GitHub project may be useful when combined with lldb to get some more information about execution flow - but have not fully got it working yet.