User Tools

Site Tools


howto:iosfrida

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
howto:iosfrida [2017/10/22 00:39]
czokie [4. Application Modification & Signing]
howto:iosfrida [2019/01/16 02:37] (current)
czokie
Line 102: Line 102:
 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" 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 [[howto:iosmod|IOSMOD]]+NB: This MUST be a decrypted Go4 app. these are available to [[howto:firmware#dji_go_4|download here]]
  
 ===== 4. Application Modification & Signing ===== ===== 4. Application Modification & Signing =====
Line 134: Line 134:
 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. 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.
 ==== 6.3 Launch in Springboard ==== ==== 6.3 Launch in Springboard ====
-Ideally, we want to be able to launch the app from the phone with no connected USB cable. Howeverthis is still failing. More testing needed. Until resolvedwe can still launch via USB and then disconnect USB and start Frida.+We can now launch in Springboardif you correctly configured your Frida configuration file, and you are only using Swizzle hooks.
 ===== 7. Launch objection ===== ===== 7. Launch objection =====
  
Line 337: Line 337:
 This option will allow us to have a frida modified IPA that will run on our device, launched by springboard with no special debug startup sequences required. This option will allow us to have a frida modified IPA that will run on our device, launched by springboard with no special debug startup sequences required.
  
-===== 11. Credits =====+===== 11. Error Codes ===== 
 +If you get an error during install, [[http://docwiki.appmethod.com/appmethod/1.16/topics/en/RunIOSDeviceFailedHelpPage|this page is a good reference guide]] to help troubleshoot. 
 + 
 +===== 12. Credits =====
 oleavr from Frida has been awesome through this process. Some of our needs were not readily possible in the existing Frida code. He has made changes throughout the process to the Frida-gadget which have been enormously helpful. In addition, he has provided guidance and coaching as we came up to speed with using Frida... so thanks oleavr. oleavr from Frida has been awesome through this process. Some of our needs were not readily possible in the existing Frida code. He has made changes throughout the process to the Frida-gadget which have been enormously helpful. In addition, he has provided guidance and coaching as we came up to speed with using Frida... so thanks oleavr.
 +
 +===== 13. Footnote =====
 +In parallel to the Objection method of patching, work has been ongoing into an alternate method that can be scripted "in the cloud". This work is dependent on one component called [[https://github.com/saucelabs/isign|isign]]
 +
 +This work had stalled, but it was confirmed to be working. However, it was discovered recently that IPA files from 4.3.2 and later fail to be signed using this tool. Below is an analysis of the current state of problem solving.
 +
 +Firstly... a quick review of the components. isign is a python app. It uses a component called "[[https://pypi.org/project/construct/2.5.5/|construct]]". Note that iSign fails to operate with versions of Construct after 2.5.5. Also, pip fails to install 2.5.4 and 2.5.5 automatically. You will need to manually install if you want to experiment with these versions.
 +
 +Construct is "Construct is a powerful declarative parser (and builder) for binary data." In other words, you define a data structure and point the parser to a stream of data, and it builds python objects containing the data from the stream.
 +
 +When using isign with IPA 4.3.2 or later, it parses all of the framework binaries, and then moves to the main DJI GO 4 macho binary and we get a construct error. A copy of the error message is listed below:
 +
 +<file>
 +working on /tmp/isign-Kvt0Zy/Payload/DJI GO 4.app/DJI GO 4
 +removing ua: /tmp/isign-Kvt0Zy
 +Traceback (most recent call last):
 +  File "/usr/bin/isign", line 5, in <module>
 +    pkg_resources.run_script('isign==1.6.15.1547538117.dev26-root', 'isign')
 +  File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 540, in run_script
 +    self.require(requires)[0].run_script(script_name, ns)
 +  File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 1455, in run_script
 +    execfile(script_filename, namespace, namespace)
 +  File "/usr/lib/python2.7/site-packages/isign-1.6.15.1547538117.dev26_root-py2.7.egg/EGG-INFO/scripts/isign", line 252, in <module>
 +    isign.resign(app_path, **kwargs)
 +  File "/usr/lib/python2.7/site-packages/isign-1.6.15.1547538117.dev26_root-py2.7.egg/isign/isign.py", line 81, in resign
 +    alternate_entitlements_path)
 +  File "/usr/lib/python2.7/site-packages/isign-1.6.15.1547538117.dev26_root-py2.7.egg/isign/archive.py", line 400, in resign
 +    ua.bundle.resign(deep, signer, provisioning_profile, alternate_entitlements_path)
 +  File "/usr/lib/python2.7/site-packages/isign-1.6.15.1547538117.dev26_root-py2.7.egg/isign/bundle.py", line 262, in resign
 +    super(App, self).resign(deep, signer)
 +  File "/usr/lib/python2.7/site-packages/isign-1.6.15.1547538117.dev26_root-py2.7.egg/isign/bundle.py", line 177, in resign
 +    self.sign(deep, signer)
 +  File "/usr/lib/python2.7/site-packages/isign-1.6.15.1547538117.dev26_root-py2.7.egg/isign/bundle.py", line 172, in sign
 +    executable = self.signable_class(self, self.get_executable_path(), signer)
 +  File "/usr/lib/python2.7/site-packages/isign-1.6.15.1547538117.dev26_root-py2.7.egg/isign/signable.py", line 41, in __init__
 +    self.m = macho.MachoFile.parse_stream(self.f)
 +  File "/usr/lib/python2.7/site-packages/construct/core.py", line 193, in parse_stream
 +    return self._parse(stream, Container())
 +  File "/usr/lib/python2.7/site-packages/construct/core.py", line 665, in _parse
 +    subobj = sc._parse(stream, context)
 +  File "/usr/lib/python2.7/site-packages/construct/core.py", line 846, in _parse
 +    obj = self.cases.get(key, self.default)._parse(stream, context)
 +  File "/usr/lib/python2.7/site-packages/construct/core.py", line 665, in _parse
 +    subobj = sc._parse(stream, context)
 +  File "/usr/lib/python2.7/site-packages/construct/core.py", line 266, in _parse
 +    return self.subcon._parse(stream, context)
 +  File "/usr/lib/python2.7/site-packages/construct/core.py", line 440, in _parse
 +    raise ArrayError("expected %d, found %d" % (count, c), sys.exc_info()[1])
 +construct.core.ArrayError: ('expected 79, found 78', ArrayError('expected 6, found 3', SwitchError('no default case defined',)))
 +</file>
 +
 +So. Lets talk about program flow. The structure of the macho binary is defined in [[https://github.com/saucelabs/isign/blob/master/isign/macho.py|macho.py]]. This object is used in [[https://github.com/saucelabs/isign/blob/master/isign/signable.py|signable.py]] in line 41
 +
 +  self.m = macho.MachoFile.parse_stream(self.f)
 +
 +To help understand where the failure is happening, [[https://pypi.org/project/construct/2.5.5/|construct]] provides some [[https://construct.readthedocs.io/en/latest/debugging.html|debugging]] capabilities.
 +
 +If you look at line 169 of [[https://github.com/saucelabs/isign/blob/master/isign/macho.py|macho.py]], you will notice there is a probe command commented out.
 +
 +  #Probe(),
 +
 +To get some debugging data as the IPA is parsed, remove the comment character above in [[https://github.com/saucelabs/isign/blob/master/isign/macho.py|macho.py]]
 +
 +However, we get a new error when debugging is enabled. From what I can tell, the debugging stream is reset on changing input files. isign parses multiple files, and only fails on the last file. The debugger does not work well on opening the next file. To get debug data, I modified the test IPA file to remove all of the framework directories, Everything else was unchanged. I then get the following [[https://dji.retroroms.info/debug.txt|debug output]]
 +
 +So. Whats next? To fix this problem will require comparing by hand the parsing of the 4.3.10 macho binary (specifically the DJI GO 4 file inside the IPA) against this debug data... and finding out what changes are required to [[https://github.com/saucelabs/isign/blob/master/isign/macho.py|macho.py]] to parse this file.
 +
 +Below is a table of the modules found within DJI GO 4 version 4.3.10 - which was created by hand analysis of the actual IPA file. This shows 79 load commands, yet Construct finds only 78. Which one is missing? Time to compare the table below with the [[https://dji.retroroms.info/debug.txt|debug output]]
 +
 +==== Manual analysis of DJI GO 4 v4.3.10 ====
 +|Count|Hex|Command|Name|
 +|1|19|LC_SEGMENT_64|_PAGEZERO|
 +|2|19|LC_SEGMENT_64|_TEXT|
 +|3|19|LC_SEGMENT_64|_DATA|
 +|4|19|LC_SEGMENT_64|_LINKEDIT|
 +|5|80000022|LC_DYLD_INFO_ONLY| |
 +|6|02|LC_SYMTAB| |
 +|7|0B|LC_DYSYMTAB| |
 +|8|08|LC_LOAD_DYLINKER| |
 +|9|1B|LC_UUID| |
 +|10|25|LC_VERSION_MIN_IPHONEOS| |
 +|11|2A|LC_SOURCE_VERSION| |
 +|12|80000028|LC_MAIN| |
 +|13|2C|LC_ENCRYPYION_INFO_64| |
 +|14|0C|LC_LOAD_DYLIB|libc++.1.dylib|
 +|15|0C|LC_LOAD_DYLIB|libsqlite3.dylib|
 +|16|0C|LC_LOAD_DYLIB|libxml2.2.dylib|
 +|17|0C|LC_LOAD_DYLIB|libz.1.dylib|
 +|18|0C|LC_LOAD_DYLIB|AVFoundation|
 +|19|0C|LC_LOAD_DYLIB|Accelerate|
 +|20|0C|LC_LOAD_DYLIB|AddressBook|
 +|21|0C|LC_LOAD_DYLIB|AssetsLibrary|
 +|22|0C|LC_LOAD_DYLIB|CFNetwork|
 +|23|0C|LC_LOAD_DYLIB|CoreData|
 +|24|0C|LC_LOAD_DYLIB|CoreFoundation|
 +|25|80000018|LC_LOAD_WEAK_DYLIB|CoreGraphics|
 +|26|0C|LC_LOAD_DYLIB|CoreImage|
 +|27|80000018|LC_LOAD_WEAK_DYLIB|CoreLocation|
 +|28|0C|LC_LOAD_DYLIB|CoreMedia|
 +|29|0C|LC_LOAD_DYLIB|CoreMotion|
 +|30|0C|LC_LOAD_DYLIB|CoreTelephony|
 +|31|0C|LC_LOAD_DYLIB|CoreText|
 +|32|0C|LC_LOAD_DYLIB|CoreVideo|
 +|33|80000018|LC_LOAD_WEAK_DYLIB|Foundation|
 +|34|0C|LC_LOAD_DYLIB|ImageIO|
 +|35|0C|LC_LOAD_DYLIB|MessageUI|
 +|36|0C|LC_LOAD_DYLIB|MobileCoreServices|
 +|37|0C|LC_LOAD_DYLIB|OpenGLES|
 +|38|80000018|LC_LOAD_WEAK_DYLIB|QuartzCore|
 +|39|0C|LC_LOAD_DYLIB|SafariServices|
 +|40|80000018|LC_LOAD_WEAK_DYLIB|Security|
 +|41|0C|LC_LOAD_DYLIB|StoreKit|
 +|42|0C|LC_LOAD_DYLIB|SystemConfiguration|
 +|43|80000018|LC_LOAD_WEAK_DYLIB|UIKit|
 +|44|80000018|LC_LOAD_WEAK_DYLIB|Accounts|
 +|45|80000018|LC_LOAD_WEAK_DYLIB|AudioToolbox|
 +|46|80000018|LC_LOAD_WEAK_DYLIB|Social|
 +|47|80000018|LC_LOAD_WEAK_DYLIB|WatchConnect|
 +|48|0C|LC_LOAD_DYLIB|AWSS3|
 +|49|0C|LC_LOAD_DYLIB|AWSCore|
 +|50|0C|LC_LOAD_DYLIB|Masonry|
 +|51|0C|LC_LOAD_DYLIB|pop|
 +|52|0C|LC_LOAD_DYLIB|CoreBluetooth|
 +|53|0C|LC_LOAD_DYLIB|DJIFlySimulator|
 +|54|0C|LC_LOAD_DYLIB|libresolv.9.dylib|
 +|55|80000018|LC_LOAD_WEAK_DYLIB|NetworkExtension|
 +|56|0C|LC_LOAD_DYLIB|libicucore.A.dylib|
 +|57|0C|LC_LOAD_DYLIB|GLKit|
 +|58|0C|LC_LOAD_DYLIB|SceneKit|
 +|59|0C|LC_LOAD_DYLIB|VideoToolbox|
 +|60|0C|LC_LOAD_DYLIB|JavaScriptCore|
 +|61|80000018|LC_LOAD_WEAK_DYLIB|ReplayKit|
 +|62|0C|LC_LOAD_DYLIB|Photos|
 +|63|0C|LC_LOAD_DYLIB|DJPanoramaKit|
 +|64|0C|LC_LOAD_DYLIB|BokehFramework|
 +|65|0C|LC_LOAD_DYLIB|MediaPlayer|
 +|66|0C|LC_LOAD_DYLIB|DJHttpProtocol|
 +|67|0C|LC_LOAD_DYLIB|libiconv.2.dylib|
 +|68|0C|LC_LOAD_DYLIB|libbz2.1.0.dylib|
 +|69|0C|LC_LOAD_DYLIB|libobjc.A.dylib|
 +|70|0C|LC_LOAD_DYLIB|libSystem.B.dylib|
 +|71|0C|LC_LOAD_DYLIB|AVKit|
 +|72|0C|LC_LOAD_DYLIB|ExternalAccessory|
 +|73|0C|LC_LOAD_DYLIB|GameController|
 +|74|0C|LC_LOAD_DYLIB|MapKit|
 +|75|0C|LC_LOAD_DYLIB|WebKit|
 +|76|1C|LC_RPATH| |
 +|77|26|LC_FUNCTION_STARTS| |
 +|78|29|LC_DATA_IN_CODE| |
 +|79|1D|LC_CODE_SIGNATURE| |
howto/iosfrida.1508632797.txt.gz · Last modified: 2017/10/22 00:39 by czokie