Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Pwning mobile apps without root or jailbreak

3,975 views

Published on

With the big delays in the time it takes until an iOS jailbreak is public and stable, it is often not possible to test mobile apps in the latest iOS version. Occasionally customers might also provide builds that only work in iOS versions for which no jailbreak is available. On Android the situation is better, but there can also be problems to root certain phone models. These trends make security testing of mobile apps difficult. This talk will cover approaches to defeat common security mechanisms that must be bypassed in the absence of root/jailbreak.

Published in: Technology

Pwning mobile apps without root or jailbreak

  1. 1. Pwning Mobile Apps Without Root or Jailbreak > Abraham Aranguren > abraham@7asecurity.com > @7asecurity > @7a_ + 7asecurity.com CureCon 2018, Berlin
  2. 2. Agenda • Motivation • Repackaging & Instrumentation examples • Android • iOS • Q&A
  3. 3. • Director at 7ASecurity, check out our public reports, presentations, etc: 7asecurity.com/#publications • Author of Practical Web Defense, a hands-on attack & defense course: www.elearnsecurity.com/PWD • Founder and leader of OWASP OWTF, an OWASP flagship project: owtf.org • Some presentations: www.slideshare.net/abrahamaranguren/presentations • Some sec certs: CISSP, OSCP, GWEB, OSWP, CPTS, CEH, MCSE: Security, MCSA: Security, Security+ • Some dev certs: ZCE PHP 5, ZCE PHP 4, Oracle PL/SQL Developer Certified Associate, MySQL 5 CMDev, MCTS SQL Server 2005 Who am I
  4. 4. Motivation ● iOS jailbreaks are not always available: ○ The app requires iOS version X, without a public jailbreak available ● iOS/Android jailbreak/root detection might take too long to bypass ○ Example: root/jailbreak detection via obfuscated binary ● Test an app on a device you don’t want to root/jailbreak ● Avoid ptrace/debugging app checks due to tampered environment
  5. 5. Repackaging: Android - Problem: App filesystem access Problem: ● When using the Android emulator/Genymotion you have a root shell ● BUT sometimes the app will only work on a real phone ● A non-rooted phone won’t give you a root shell ● A non-rooted phone won’t give you access to application files in /data/data/… ● The app often has backups disabled too Repackaging Solution: ● Modify the APK, enable backups
  6. 6. Repackaging: Android - Problem: Debugging Problem: ● Some apps enable debugging features, such as Webview debugging or other useful information in logcat, etc., when the app has debugging enabled Repackaging Solution: ● Modify the APK, enable debugging
  7. 7. Step 1: Disassemble APK - apktool d some_app.apk -o some_app_disassembled Step 2: Edit AndroidManifest.xml Change: <application android:allowBackup="false" To: <application android:allowBackup="true" android:debuggable="true" Step 3: Repackage APK - apktool b some_app_disassembled -o some_app_debug.apk Step 4: Sign - jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore some_app_debug.apk alias_name Step 5: Install - adb install some_app_debug.apk Example: Backups + Debugging
  8. 8. Example: Backups + Debugging Now we have access to app files via adb backup: Step 1: Backup app files adb backup some.app.com Step 2: Make the backup useful ( printf "x1fx8bx08x00x00x00x00x00" ; tail -c +25 backup.ab ) | tar xfvz - Step 3: Review files :)
  9. 9. Yay file access!
  10. 10. Repackaging: Android - Problem: Pinning ● Often a problem at the start of the test as you try to MitM :) ● We can modify the APK to skip certificate pinning checks
  11. 11. Repackaging: Android - Problem: Pinning Examp Step 1: Disassemble - apktool d some_app.apk -o some_app_disassembled Step 2: Find file to modify - grep -Ir checkServerTrusted * Step 3: Modify the file .method public final checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;) V [...] return-void # Pinning bypass Steps 4-6: Repackage, Sign & Install :)
  12. 12. Wait, is it that easy?
  13. 13. Repackaging: Android - Problem: Root detection ● Sometimes apps refuse to run when your phone is rooted ● Repackaging often allows us to bypass these checks and enjoy root powers :D
  14. 14. Android repackaging - Root detection bypass example 1 Step 1: Disassemble - apktool d some.apk -o some_disassembled Step 2: Remove check from app Java Code: if (isRooted()) [...] Related Smali Code: if-eqz v0, :cond_0 Change Smali Code to: if-nez v0, :cond_0 NOTE: The if-nez opcode inverts the condition, hence bypassing the check Steps 3-5: Repackage, Sign & Install :)
  15. 15. Android repackaging - Root detection bypass example 2 Step 1: Disassemble - apktool d some.apk -o some_disassembled Step 2: Remove check from app, return “False” from isRooted .method public isRooted()Z const/4 v0, 0x0 # False return v0 # Return false [...] Steps 3-5: Repackage, Sign & Install :)
  16. 16. So this is awesome, right?
  17. 17. Limitations of apktool-style Android repackaging ● Limited to changes in smali code: ○ We can only modify Java code disassembled as smali ○ If the app loads and runs code from a binary we cannot modify that (at least not as easily :D) ● Changes are static ○ If you notice later that you need further changes you need to: ■ Disassemble ■ Modify ■ Repackage, Sign and Install ■ … For each modification! :P
  18. 18. Further reading Must-use tool for Android repackaging: https://ibotpeaches.github.io/Apktool/ Cool smali opcode references: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html https://source.android.com/devices/tech/dalvik/dalvik-bytecode
  19. 19. What is Frida? - https://www.frida.re/ ● Dynamic Instrumentation Toolkit ● Allows hooking and observing/modifying any app function: ○ Crypto APIs ○ Proprietary functions ○ Even functionality in binaries ● Lets you inject snippets of JavaScript into native apps that run on Windows, Mac, Linux, iOS and Android In short: Frida Gadgets allow root-like access on apps from not-rooted/jailbroken devices
  20. 20. How to add Frida to an APK so we can run it without root? Step 1: Disassemble - apktool d some_app.apk -o some_app_disassembled Step 2: Add the frida-gadget binaries to the APK - For the correct architecture! :) https://github.com/frida/frida/releases/download/12.0.8/frida-gadget-12.0.8-androi d-x86.so.xz https://github.com/frida/frida/releases/download/12.0.8/frida-gadget-12.0.8-androi d-x86_64.so.xz https://github.com/frida/frida/releases/download/12.0.8/frida-gadget-12.0.8-androi d-arm.so.xz https://github.com/frida/frida/releases/download/12.0.8/frida-gadget-12.0.8-androi d-arm64.so.xz
  21. 21. How do I know the architecture? ADB Command: adb shell getprop ro.product.cpu.abi Example Output (Genymotion): x86
  22. 22. Step 2: Adding the Frida-Gadget to the APK - (ARM 32bits) Download: wget https://github.com/frida/frida/releases/download/12.0.8/frida-gadget-12.0.8-a ndroid-arm.so.xz Uncompress: unxz frida-gadget-12.0.8-android-arm.so.xz Copy: cp frida-gadget-12.0.8-android-arm.so some_disassembled/lib/armeabi/libfrida-gadget.so
  23. 23. Step 3: Make the APK load the Gadget Find main activity: find . | grep -i main | grep smali$ Add the following smali code to the constructor: const-string v0, "frida-gadget" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V Corresponding Java Code: System.loadLibrary("frida-gadget")
  24. 24. Step 4: Ensure network permissions in AndroidManifest.xml We will talk to Frida over the network so the app needs to use the internet, most apps do but worth double checking: File: AndroidManifest.xml Make sure it has: <uses-permission android:name="android.permission.INTERNET" />
  25. 25. Repackage, Sign & Install Step 5: Repackage APK - apktool b some_app_disassembled -o some_app_debug.apk Step 6: Sign - jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore some_app_debug.apk alias_name Step 7: Install - adb install some_app_debug.apk
  26. 26. Basic Frida usage Logcat - Frida: Listening on TCP port 27042 The PID will show Gadget instead of the original package name: Command: $ frida-ps –U Output: PID Name ----- ------ 16071 Gadget
  27. 27. Basic Frida usage – Interactive Instrumentation Shell Command: frida -U Gadget --no-pause Output: Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit [USB::Android Emulator 5556::['com.android.chrome']]-> Java.androidVersion "7.1.1"
  28. 28. Basic Frida usage – Public script example: Root Bypass https://github.com/0xdea/frida-scripts/blob/master/android-snippets/raptor_frida _android_bypass.js Usage (Frida Server): frida -U -f com.xxx.yyy -l raptor_frida_android.js --no-pause Usage (Frida Gadget): frida -U Gadget -l raptor_frida_android.js --no-pause
  29. 29. Basic Frida usage – Public script example: Root Bypass setTimeout(function() { // avoid java.lang.ClassNotFoundException Java.perform(function() {// Root detection bypass example var hook = Java.use("com.target.utils.RootCheck"); hook.isRooted.overload().implementation = function() { console.log("info: entered target method"); var retval = this.isRooted.overload().call(this); //old retval console.log("old ret value: " + retval); var retnew = false; // set new retval console.log("new ret value: " + retnew); return retnew; } }); }, 0);
  30. 30. Basic Frida usage – Crypto Hooks https://gitlab.com/roxanagogonea/frida-scripts/blob/master/cryptography/crypt ography.js setImmediate(function() { Java.perform(function() { var keyGenerator = Java.use("javax.crypto.KeyGenerator"); keyGenerator.generateKey.implementation = function () { console.log("[*] Generate symmetric key called. "); return this.generateKey(); }; }); });
  31. 31. Basic Frida usage – Crypto Hooks setImmediate(function() { Java.perform(function() { var keyGenerator = Java.use("javax.crypto.KeyGenerator"); keyGenerator.getInstance.overload('java.lang.String').implementation = function (var0) { console.log("[*] KeyGenerator.getInstance called with algorithm: " + var0 + "n"); return this.getInstance(var0); }; }); });
  32. 32. Basic Frida usage – Crypto Hooks setImmediate(function() { Java.perform(function() { var keyGenerator = Java.use("javax.crypto.KeyGenerator"); keyGenerator.getInstance.overload('java.lang.String', 'java.lang.String').implementation = function (var0, var1) { console.log("[*] KeyGenerator.getInstance called with algorithm: " + var0 + " and provider: " + var1 + "n"); return this.getInstance(var0, var1); }; }); });
  33. 33. Basic Frida usage – Shared Preferences setImmediate(function() { Java.perform(function() { var contextWrapper = Java.use("android.content.ContextWrapper"); var sharedPreferencesEditor = Java.use("android.app.SharedPreferencesImpl$EditorImpl"); sharedPreferencesEditor.putString.overload('java.lang.String', 'java.lang.String').implementation = function(var0, var1) { console.log("[*] Added a new String value to SharedPreferences with key: " + var0 + " and value " + var1 + "n"); var editor = this.putString(var0, var1); return editor; }});});
  34. 34. Basic Frida usage – SQLite query hooks setImmediate(function() { Java.perform(function() { var sqliteDatabase = Java.use("android.database.sqlite.SQLiteDatabase"); sqliteDatabase.execSQL.overload('java.lang.String').implementation = function(var0) { console.log("[*] SQLiteDatabase.exeqSQL called with query: " + var0 + "n"); var execSQLRes = this.execSQL(var0); return execSQLRes; };});}); https://gitlab.com/roxanagogonea/frida-scripts/blob/master/data-storage/sqlite-d atabase.js
  35. 35. Further reading & Frida script examples https://www.frida.re/docs/gadget/ https://koz.io/using-frida-on-android-without-root/ https://www.codemetrix.net/hacking-android-apps-with-frida-1/ https://github.com/iddoeldor/frida-snippets https://github.com/poxyran/misc https://gitlab.com/roxanagogonea/frida-scripts/blob/master/
  36. 36. Can this be automated? Here are some attempts: https://github.com/dpnishant/appmon/tree/master/apk_builder
  37. 37. BUT BUT BUT … What about iOS????
  38. 38. iOS Reversing 101 Usual approach overview: ● Decrypt IPA with Clutch - https://github.com/KJCracks/Clutch ● Generate Objective-C headers with class-dump - https://github.com/nygard/class-dump ● Disassemble with Hopper - https://www.hopperapp.com/index.html Explained by filedescriptor ☺ https://blog.innerht.ml/page/2/
  39. 39. iOS Repackaging Guides https://labs.mwrinfosecurity.com/blog/repacking-and-resigning-ios-applications/ https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2016/octo ber/ios-instrumentation-without-jailbreak/ https://github.com/sensepost/objection/wiki/Patching-iOS-Applications
  40. 40. iOS Repackaging - Step 1: Add Apple ID to XCode Add an Apple ID to Xcode: Xcode / Preferences / Accounts / Add Apple ID
  41. 41. iOS Repackaging - Step 2: Manage Certificates
  42. 42. iOS Repackaging - Step 2: Manage Certificates – iOS Dev
  43. 43. iOS Repackaging - Step 2: Manage Certificates – Done
  44. 44. iOS Repackaging - Step 2: Verify Code Signing Certificate Command: security find-identity -p codesigning -v Output: 1) xxx[…] "iPhone Developer: abraham+1@cure53.de ([…]XX)" 1 valid identities found
  45. 45. iOS Repackaging - Step 3: Create mobileprovision file
  46. 46. iOS Repackaging - Step 3: Create mobileprovision file
  47. 47. iOS Repackaging - Step 3: Create mobileprovision file
  48. 48. iOS Repackaging - Step 3: Create mobileprovision file
  49. 49. iOS Repackaging - Step 3: Create mobileprovision file
  50. 50. iOS Repackaging - Step 3: Create mobileprovision file Just login :D
  51. 51. iOS Repackaging - Step 3: Create mobileprovision file ● Plug your iPhone ● Select the iPhone as the target device on Xcode ● Hit the “Play” button ● Verify the mobileprovision file has been created: find ~/Library/Developer/Xcode/DerivedData/ -name embedded.mobileprovision
  52. 52. iOS Repackaging - Step 3: Create mobileprovision file Do we have to do all this nonsense every time?
  53. 53. iOS Repackaging - Step 3: Create mobileprovision file From here, each time we will “only” need to: ● Create a blank app ● Deploy it to an iDevice This will create a new, valid provisioning file
  54. 54. iOS Repackaging - Step 4: IPA Patching Dependencies ● objection – from: https://github.com/sensepost/objection/wiki/Installation ● applesign - from: https://github.com/nowsecure/node-applesign ● insert_dylib - from: https://github.com/Tyilo/insert_dylib ● security, codesign, xcodebuild` - macOS/XCode commands ● zip & unzip - builtin, or just installed using homebrew ● 7z - installed using homebrew with brew install p7zip
  55. 55. iOS Repackaging - Step 4: IPA Patching Dependencies Objection Installation: pip3 install -U objection More details and options: https://github.com/sensepost/objection/wiki/Installation
  56. 56. iOS Repackaging - Step 4: IPA Patching Dependencies applesign Installation: npm install -g applesign. If npm is missing: brew install npm
  57. 57. iOS Repackaging - Step 4: IPA Patching Dependencies insert_dylib installation: Compile from source like so: git clone https://github.com/Tyilo/insert_dylib cd insert_dylib xcodebuild cp build/Release/insert_dylib /usr/local/bin/insert_dylib
  58. 58. iOS Repackaging - Step 4: IPA Patching Command: objection patchipa --source my-app.ipa --codesign-signature xxxx
  59. 59. iOS Repackaging - Step 5: Running the patched IPA More dependencies :D Install ios-deploy: npm install -g ios-deploy
  60. 60. iOS Repackaging - Step 5: Running the patched IPA Installing and running the app: unzip my-app.ipa # Creates a Payload/ directory. Unlock iDevice and plug via USB to your Mac Run ios-deploy: ios-deploy --bundle Payload/my-app.app -W -d More intel and Linux instructions: https://github.com/sensepost/objection/wiki/Running-Patched-iOS-Applications
  61. 61. iOS Repackaging - Step 6: Using Frida ☺ So now we can run Frida scripts: frida -U Gadget -l <frida_script> --no-pause Some nice examples for iOS inspiration: https://github.com/iddoeldor/frida-snippets https://github.com/0xdea/frida-scripts/tree/master/ios-snippets
  62. 62. Frida Examples – Filesystem access https://github.com/nowsecure/frida-fs const fs = require('frida-fs'); fs.createReadStream('/etc/hosts').pipe(networkStream);
  63. 63. Frida Examples – Grab iOS Screenshots https://github.com/nowsecure/frida-screenshot const screenshot = require('frida-screenshot'); const png = yield screenshot(); send({ name: '+screenshot', payload: { timestamp: Date.now() }}, png);
  64. 64. Frida Examples – iOS instance member values ObjC.choose(ObjC.classes[clazz], { onMatch: function (obj) { console.log('onMatch: ', obj); Object.keys(obj.$ivars).forEach(function(v) { console.log('t', v, '=', obj.$ivars[v]); }); }, onComplete: function () { console.log('onComplete', arguments.length); }}); https://github.com/iddoeldor/frida-snippets
  65. 65. Frida Examples – iOS extract cookies var cookieJar = []; var cookies = ObjC.classes.NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies(); for (var i = 0, l = cookies.count(); i < l; i++) { var cookie = cookies['- objectAtIndex:'](i); cookieJar.push(cookie.Name() + '=' + cookie.Value()); } console.log(cookieJar.join("; ")); https://github.com/iddoeldor/frida-snippets
  66. 66. Frida Examples – iOS monitor file access Interceptor.attach(ObjC.classes.NSFileManager['- fileExistsAtPath:'].implementation, { onEnter: function (args) { console.log('open' , ObjC.Object(args[2]).toString()); } }); https://github.com/iddoeldor/frida-snippets
  67. 67. What is Objection? ● Wrapper around Frida ● Automates a lot of stuff via Frida hooks ● Works for iOS and Android https://github.com/sensepost/objection/wiki
  68. 68. Demos from the author of objection https://www.youtube.com/watch?v=zkxSFERFuBw https://www.youtube.com/watch?v=AqqPGXa4nO8 https://www.youtube.com/watch?v=t3nRDELo_fY https://www.youtube.com/watch?v=aL8Z2PctBFE https://www.youtube.com/watch?v=Mhf92DeRk8c
  69. 69. > abraham@7asecurity.com @7asecurity | + 7asecurity.com @7a_ OWASP OWTF: @owtfp | + owtf.org Q & A Thank you for your time

×