├── .gitattributes ├── LICENSE ├── README.md ├── binaries └── SQLite3UniversalBinaries-1.5.zip ├── img ├── exporting_burp_suite_proxy_certificate.png ├── exporting_zap_certificate.png ├── magisk_install_from_storage.jpg ├── spotbugs.jpg ├── sqlite.png └── wifi_adb.jpg └── scripts ├── android-intent-monitor.js ├── android-ssl-pinning-bypass-2.js ├── android-ssl-pinning-bypass.js └── gcp_firebase.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ivan Šincek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Penetration Testing Cheat Sheet 2 | 3 | This is more of a checklist for myself. May contain useful tips and tricks. **Still need to add a lot of things.** 4 | 5 | Everything was tested on Kali Linux v2023.1 (64-bit) and Samsung A5 (2017) with Android OS v8.0 (Oreo) and Magisk root v25.2. 6 | 7 | Check [Magisk](https://topjohnwu.github.io/Magisk) if you wish to root your Android device. I have no [liability](https://github.com/ivan-sincek/android-penetration-testing-cheat-sheet/blob/main/LICENSE) over your actions. 8 | 9 | For help with any of the tools type ` [-h | -hh | --help]` or `man `. 10 | 11 | If you didn't already, read [OWAS MASTG](https://mas.owasp.org/MASTG/) \([GitHub](https://github.com/OWASP/owasp-mastg)\) and [OWASP MASVS](https://mas.owasp.org/MASVS/) \([GitHub](https://github.com/OWASP/owasp-masvs)\). You can download OWASP MASTG checklist from [here](https://github.com/OWASP/owasp-mastg/releases). 12 | 13 | I also recommend reading [HackTricks - Android Applications Pentesting](https://book.hacktricks.xyz/mobile-pentesting/android-app-pentesting). 14 | 15 | __In most cases, to be eligible for a bug bounty reward, you need to exploit a vulnerability with non-root privileges, possibly building your own "malicious" PoC app.__ 16 | 17 | Find out more about my "malicious" PoC app from my other [project](https://github.com/ivan-sincek/malware-apk). 18 | 19 | Websites that you should use while writing the report: 20 | 21 | * [cwe.mitre.org/data](https://cwe.mitre.org/data) 22 | * [owasp.org/projects](https://owasp.org/projects) 23 | * [owasp.org/www-project-mobile-top-10](https://owasp.org/www-project-mobile-top-10) 24 | * [cheatsheetseries.owasp.org](https://cheatsheetseries.owasp.org/Glossary.html) 25 | * [first.org/cvss/calculator/4.0](https://www.first.org/cvss/calculator/4.0) 26 | * [bugcrowd.com/vulnerability-rating-taxonomy](https://bugcrowd.com/vulnerability-rating-taxonomy) 27 | * [nvd.nist.gov/ncp/repository](https://nvd.nist.gov/ncp/repository) 28 | * [attack.mitre.org](https://attack.mitre.org) 29 | 30 | My other cheat sheets: 31 | 32 | * [iOS Testing Cheat Sheet](https://github.com/ivan-sincek/ios-penetration-testing-cheat-sheet) 33 | * [Penetration Testing Cheat Sheet](https://github.com/ivan-sincek/penetration-testing-cheat-sheet) 34 | * [WiFi Penetration Testing Cheat Sheet](https://github.com/ivan-sincek/wifi-penetration-testing-cheat-sheet) 35 | 36 | Future plans: 37 | 38 | * modify `networkSecurityConfig` to add custom root CA certificates, 39 | * test widgets, push notifications, and Firebase, 40 | * SMALI code injection, 41 | * Flutter attacks, 42 | * create more Frida scripts. 43 | 44 | ## Table of Contents 45 | 46 | **0. [Install Tools](#0-install-tools)** 47 | 48 | * [WiFi ADB - Debug Over Air](#wifi-adb---debug-over-air) 49 | * [Magisk Frida](#magisk-frida) 50 | * [Magisk SQLite 3](#magisk-sqlite-3) 51 | * [BusyBox](#busybox) 52 | * [Kali Linux Tools](#kali-linux-tools) 53 | * [Java](#java) 54 | * [Apktool](#apktool) 55 | * [Mobile Security Framework (MobSF)](#mobile-security-framework-mobsf) 56 | * [Drozer](#drozer) 57 | * [Install Web Proxy Certificates](#install-web-proxy-certificates) 58 | 59 | **1. [Basics](#1-basics)** 60 | 61 | * [Android Debug Bridge (ADB)](#android-debug-bridge-adb) 62 | * [Install/Uninstall an APK](#installuninstall-an-apk) 63 | * [Download/Upload Files and Directories](#downloadupload-files-and-directories) 64 | * [Bypassing Permission Denied](#bypassing-permission-denied) 65 | 66 | **2. [Inspect an APK](#2-inspect-an-apk)** 67 | 68 | * [Pull an APK (base.apk)](#pull-an-apk-baseapk) 69 | * [AndroidManifest.xml](#androidmanifestxml) 70 | * [strings.xml](#stringsxml) 71 | 72 | **3. [Search for Files and Directories](#3-search-for-files-and-directories)** 73 | 74 | * [SharedPreferences](#sharedpreferences) 75 | 76 | **4. [Inspect Files](#4-inspect-files)** 77 | 78 | * [Single File](#single-file) 79 | * [Multiple Files](#multiple-files) 80 | * [File Scraper](#file-scraper) 81 | * [SQLite 3](#sqlite-3) 82 | * [Nuclei](#nuclei) 83 | * [Backups](#backups) 84 | 85 | **5. [SpotBugs](#5-SpotBugs)** 86 | 87 | **6. [Deep Links](#6-deep-links)** 88 | 89 | * [Android App Link Verification Tester](#android-app-link-verification-tester) 90 | 91 | * [Deep Link Hijacking](#deep-link-hijacking) 92 | 93 | **7. [WebViews](#7-webviews)** 94 | 95 | **8. [Frida](#8-frida)** 96 | 97 | * [Frida Scripts](#frida-scripts) 98 | 99 | **9. [Objection](#9-objection)** 100 | 101 | * [Bypasses](#bypasses) 102 | 103 | **10. [Drozer](#10-drozer)** 104 | 105 | * [Intents](#intents) 106 | * [Content Providers](#content-providers) 107 | * [Broadcast Receivers](#broadcast-receivers) 108 | 109 | **11. [Intent Injections](#11-intent-injections)** 110 | 111 | **12. [Taskjacking](#12-taskjacking)** 112 | 113 | **13. [Tapjacking](#13-tapjacking)** 114 | 115 | **14. [Decompile an APK](#14-decompile-an-apk)** 116 | 117 | **15. [Repackage an APK](#15-repackage-an-apk)** 118 | 119 | * [Decode](#decode) 120 | * [Repackage](#repackage) 121 | * [Code Sign](#code-sign) 122 | 123 | **16. [Miscellaneous](#16-miscellaneous)** 124 | 125 | * [Monitor the System Log](#monitor-the-system-log) 126 | * [Monitor File Changes](#monitor-file-changes) 127 | 128 | **17. [Tips and Security Best Practices](#17-tips-and-security-best-practices)** 129 | 130 | **18. [Useful Websites and Tools](#18-useful-websites-and-tools)** 131 | 132 | **19. [Vulnerable Apps](#19-vulnerable-apps)** 133 | 134 | ## 0. Install Tools 135 | 136 | ### WiFi ADB - Debug Over Air 137 | 138 | Install [WiFi ADB - Debug Over Air](https://play.google.com/store/apps/details?id=com.ttxapps.wifiadb). To be used with [ADB](#android-debug-bridge-adb). 139 | 140 |

WiFi ADB - Debug Over Air

141 | 142 |

Figure 1 - WiFi ADB - Debug Over Air

143 | 144 | ### Magisk Frida 145 | 146 | Download [Magisk Frida](https://github.com/ViRb3/magisk-frida/releases), then, open your [Magisk](https://topjohnwu.github.io/Magisk) app and install Frida by importing the downloaded archive. 147 | 148 |

Magisk Frida

149 | 150 |

Figure 2 - Magisk Frida

151 | 152 | ### Magisk SQLite 3 153 | 154 | Download [Magisk SQLite 3](https://github.com/ivan-sincek/android-penetration-testing-cheat-sheet/tree/main/binaries), then, open your [Magisk](https://topjohnwu.github.io/Magisk) app and install SQLite 3 by importing the downloaded archive. 155 | 156 | ### BusyBox 157 | 158 | Additional set of tools for advanced users. Read more at [busybox.net](https://busybox.net/about.html) \([Google Play](https://play.google.com/store/apps/details?id=stericson.busybox)\). 159 | 160 | ### Kali Linux Tools 161 | 162 | Install required tools on your Kali Linux: 163 | 164 | ```fundamental 165 | apt-get -y install docker.io 166 | 167 | systemctl start docker 168 | 169 | apt-get -y install adb dex2jar jadx nuclei radare2 sqlite3 sqlitebrowser xmlstarlet apksigner zipalign 170 | 171 | pip3 install frida-tools objection file-scraper 172 | ``` 173 | 174 | More information about my tool can be found at [ivan-sincek/file-scraper](https://github.com/ivan-sincek/file-scraper). 175 | 176 | Make sure that Frida and Objection are always up to date: 177 | 178 | ```fundamental 179 | pip3 install --upgrade frida-tools objection 180 | ``` 181 | 182 | ### Java 183 | 184 | Install: 185 | 186 | ```fundamental 187 | apt-get -y install default-jdk 188 | ``` 189 | 190 | More Java/JDK versions can be found at [oracle.com/java/technologies/downloads/archive](https://www.oracle.com/java/technologies/downloads/archive). 191 | 192 | To switch between multiple Java/JDK versions, run: 193 | 194 | ```fundamental 195 | update-alternatives --config java 196 | 197 | update-alternatives --config javac 198 | ``` 199 | 200 | ### Apktool 201 | 202 | Download and install: 203 | 204 | ```bash 205 | apt-get -y install aapt 206 | 207 | wget https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool -O apktool 208 | 209 | chmod +x apktool && cp apktool /usr/local/bin/apktool 210 | 211 | wget https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.9.3.jar -O apktool.jar 212 | 213 | chmod +x apktool.jar && cp apktool.jar /usr/local/bin/apktool.jar 214 | ``` 215 | 216 | ### Mobile Security Framework (MobSF) 217 | 218 | Install: 219 | 220 | ```fundamental 221 | docker pull opensecurity/mobile-security-framework-mobsf 222 | ``` 223 | 224 | Run: 225 | 226 | ```fundamental 227 | docker run -it --rm --name mobsf -p 8000:8000 opensecurity/mobile-security-framework-mobsf 228 | ``` 229 | 230 | Navigate to `http://localhost:8000` using your preferred web browser. Username and password are `mobsf:mobsf`. 231 | 232 | Sometimes, for some reason, [MobSF](#mobile-security-framework-mobsf) might not want to parse your APK; in that case, try to [decode](#decode) and [repackage](#repackage) your APK, then, upload it again. 233 | 234 | Uninstall: 235 | 236 | ```fundamental 237 | docker image rm opensecurity/mobile-security-framework-mobsf 238 | ``` 239 | 240 | ### Drozer 241 | 242 | Install: 243 | 244 | ```fundamental 245 | docker pull fsecurelabs/drozer 246 | ``` 247 | 248 | Run: 249 | 250 | ```fundamental 251 | docker run -it --rm --name drozer fsecurelabs/drozer 252 | ``` 253 | 254 | Download [Drozer Agent](https://github.com/WithSecureLabs/drozer-agent/releases) and install it either manually or by using [ADB](#android-debug-bridge-adb). 255 | 256 | Uninstall: 257 | 258 | ```fundamental 259 | docker image rm fsecurelabs/drozer 260 | ``` 261 | 262 | ## Install Web Proxy Certificates 263 | 264 | Open [Burp Suite](https://portswigger.net/burp/communitydownload), navigate to `Proxy --> Proxy Settings` and save the certificate, e.g., as `burp_suite_root_ca.der`. 265 | 266 |

Exporting Burp Suite Proxy Certificate

267 | 268 |

Figure 3 - Exporting Burp Suite Proxy Certificate

269 | 270 | Open [ZAP](https://www.zaproxy.org), navigate to `Tools --> Options --> Network --> Server Certificates`, and save the certificate, e.g., as `zap_root_ca.cer`. 271 | 272 |

Exporting ZAP Certificate

273 | 274 |

Figure 4 - Exporting ZAP Certificate

275 | 276 | Now, you can either transfer the files to your Android device manually or run: 277 | 278 | ```fundamental 279 | adb push burp_suite_root_ca.der /storage/emulated/0/ 280 | adb push zap_root_ca.cer /storage/emulated/0/ 281 | ``` 282 | 283 | `/storage/emulated/0/` is the internal storage path that can be accessed through the UI, e.g., on your Android device, navigate to `My Files --> Internal Storage`. 284 | 285 | To install, simply tap on the certificates and follow the on-screen instructions. 286 | 287 | ## 1. Basics 288 | 289 | ### Android Debug Bridge (ADB) 290 | 291 | Start the server: 292 | 293 | ```fundamental 294 | adb start-server 295 | ``` 296 | 297 | Stop the server: 298 | 299 | ```fundamental 300 | adb kill-server 301 | ``` 302 | 303 | List attached devices: 304 | 305 | ```fundamental 306 | adb devices 307 | ``` 308 | 309 | Connect to a remote device using [WiFi ADB](#wifi-adb---debug-over-air): 310 | 311 | ```fundamental 312 | adb connect 192.168.1.10:5555 313 | ``` 314 | 315 | Open a system shell as non-root: 316 | 317 | ```fundamental 318 | adb shell 319 | ``` 320 | 321 | Open a system shell as root: 322 | 323 | ```fundamental 324 | adb shell su 325 | ``` 326 | 327 | Show activity manager's full usage: 328 | 329 | ```fundamental 330 | adb shell am -h 331 | ``` 332 | 333 | ### Install/Uninstall an APK 334 | 335 | Install an APK (specify `-s` to install the APK to a removable storage): 336 | 337 | ```fundamental 338 | adb install someapp.apk 339 | 340 | adb install -s someapp.apk 341 | ``` 342 | 343 | Uninstall an APK (specify `-k` to keep the data and cache directories): 344 | 345 | ```fundamental 346 | adb uninstall com.someapp.dev 347 | 348 | adb uninstall -k com.someapp.dev 349 | ``` 350 | 351 | ### Download/Upload Files and Directories 352 | 353 | Some of the internal storage paths: 354 | 355 | ```fundamental 356 | cd /data/local/tmp/ 357 | 358 | cd /data/data/com.someapp.dev/cache/ 359 | cd /data/user/0/com.someapp.dev/cache/ 360 | 361 | cd /mnt/sdcard/Android/data/com.someapp.dev/cache/ 362 | cd /storage/emulated/0/Android/data/com.someapp.dev/cache/ 363 | 364 | cd /mnt/sdcard/Android/obb/com.someapp.dev/cache/ 365 | cd /storage/emulated/0/Android/obb/com.someapp.dev/cache/ 366 | 367 | cd /mnt/media_rw/3664-6132/Android/data/com.someapp.dev/files/ 368 | cd /storage/3664-6132/Android/data/com.someapp.dev/files/ 369 | ``` 370 | 371 | Number `0` in both, `/data/user/0/` and `/storage/emulated/0/` paths, represents the first user in a multi-user device. 372 | 373 | `/storage/emulated/0/` is the internal storage path that can be accessed through the UI, e.g., on your Android device, navigate to `My Files --> Internal Storage`. 374 | 375 | Don't confuse `/mnt/sdcard/` path with a real removable storage path because sometimes such path is device specific, so you will need to search it on the internet or extract it using some Java code. In my case it is `/mnt/media_rw/3664-6132/` path. 376 | 377 | ```fundamental 378 | XML --> Java Method --> Path 379 | 380 | --> getContext().getFilesDir() --> /data/user/0/com.someapp.dev/files 381 | 382 | --> getContext().getCacheDir() --> /data/user/0/com.someapp.dev/cache 383 | 384 | --> Environment.getExternalStorageDirectory() --> /storage/emulated/0 385 | 386 | --> getContext().getExternalFilesDir("") --> /storage/emulated/0/Android/data/com.someapp.dev/files 387 | 388 | --> getContext().getExternalCacheDir() --> /storage/emulated/0/Android/data/com.someapp.dev/cache 389 | 390 | --> getContext().getExternalMediaDirs() --> /storage/emulated/0/Android/media/com.someapp.dev 391 | /storage/3664-6132/Android/media/com.someapp.dev 392 | 393 | - --> getContext().getExternalFilesDirs("") --> /storage/emulated/0/Android/data/com.someapp.dev/files 394 | /storage/3664-6132/Android/data/com.someapp.dev/files 395 | ``` 396 | 397 | --- 398 | 399 | Tilde `~` is short for the root directory. 400 | 401 | Download a file or directory from your Android device: 402 | 403 | ```fundamental 404 | adb pull ~/somefile.txt ./ 405 | 406 | adb pull ~/somedir ./ 407 | ``` 408 | 409 | Keep in mind that not all directories have the write and/or execute permission; regardless, you can always upload files to and execute from `/data/local/tmp/` directory. 410 | 411 | Upload a file or directory to your Android device: 412 | 413 | ```fundamental 414 | adb push somefile.txt /data/local/tmp/ 415 | 416 | adb push somedir /data/local/tmp/ 417 | ``` 418 | 419 | Empty directories will not be uploaded. 420 | 421 | ### Bypassing Permission Denied 422 | 423 | Download a file from your Android device: 424 | 425 | ```bash 426 | adb shell su -c 'cat ~/somefile.txt' > somefile.txt 427 | 428 | adb shell su -c 'run-as com.someapp.dev cat ~/somefile.txt' > somefile.txt 429 | ``` 430 | 431 | Download a directory from your Android device: 432 | 433 | ```bash 434 | dir="somedir"; IFS=$'\n'; for subdir in $(adb shell su -c "find \"${dir}\" -type d"); do mkdir -p ".${subdir}"; done; for file in $(adb shell su -c "find \"${dir}\" -type f"); do adb shell su -c "cat \"${file// /\\\ }\"" > ".${file}"; done; 435 | ``` 436 | 437 | Upload a file or directory to your Android device: 438 | 439 | ```bash 440 | src="somefile.txt"; dst="/data/data/com.someapp.dev/"; tmp="/data/local/tmp/"; base=$(basename "${src}"); adb push "${src}" "${tmp}"; adb shell su -c "cp -r \"${tmp}${base}\" \"${dst}\" && rm -rf \"${tmp}${base}\"" 441 | ``` 442 | 443 | ## 2. Inspect an APK 444 | 445 | ### Pull an APK (base.apk) 446 | 447 | ```bash 448 | adb shell pm list packages 'keyword' | cut -d ':' -f2 449 | 450 | adb pull $(adb shell pm path com.someapp.dev | cut -d ':' -f2 | grep 'base.apk') ./ 451 | ``` 452 | 453 | Pull an APK by specific keyword (one-liner): 454 | 455 | ```bash 456 | keyword="keyword"; pkg=$(adb shell pm list packages "${keyword}" | head -n 1 | cut -d ':' -f2); adb pull $(adb shell pm path "${pkg}" | cut -d ':' -f2 | grep 'base.apk') ./ 457 | ``` 458 | 459 | Decode an APK using [Apktool](#decode). You should now see the `decoded` directory. 460 | 461 | ## AndroidManifest.xml 462 | 463 | Always inspect `decoded/AndroidManifest.xml` content for possible misconfigurations. 464 | 465 | Things to look for in AndroidManifest.xml: 466 | 467 | * `minSdkVersion`, `targetSDKVersion`, and `maxSdkVersion` - app should not support outdated and vulnerable Android releases, 468 | * `debuggable="true"` - production app (i.e., build) should not be debuggable, 469 | * `android:allowBackup="true"` - app should not [backup](#backups) any sensitive data, 470 | * `usesCleartextTraffic="true"` - app should not use a cleartext HTTP communication, 471 | * `networkSecurityConfig` - inspect network security configurations for SSL/TLS pinnings, whitelisted domains, and `cleartextTrafficPermitted="true"` inside `decoded/res/xml/` directory, 472 | * `permission` - look for unused \[custom\] permissions, and permissions with weak [protection](https://developer.android.com/guide/topics/manifest/permission-element) (`protectionLevel`), 473 | * `exported="true"` - [enumerate](#10-drozer) exported activities, content providers, broadcast receivers, and services, 474 | * `taskAffinity` - activities missing this attribute might be vulnerable to [taskjacking](#taskjacking), 475 | * `android:autoVerify="true"` - deep links missing this attribute might be vulnerable to [deep link hijacking](#deep-link-hijacking), 476 | * etc. 477 | 478 | --- 479 | 480 | Extract URL schemes from AndroidManifest.xml: 481 | 482 | ```bash 483 | xmlstarlet sel -t -m '//activity/intent-filter/data[@android:scheme]' -v '@android:scheme' -n AndroidManifest.xml | sort -uf | tee url_schemes.txt 484 | ``` 485 | 486 | Extract URL schemes and corresponding hosts from AndroidManifest.xml: 487 | 488 | ```bash 489 | xmlstarlet sel -t -m '//activity/intent-filter/data[@android:scheme and @android:host]' -v 'concat(@android:scheme, "://", @android:host, @android:pathPrefix, @android:path, @android:pathSufix)' -n AndroidManifest.xml | sort -uf | tee url_schemes_hosts.txt 490 | ``` 491 | 492 | Resolve all `@string` keys from AndroidManifest.xml as `key: value` pairs: 493 | 494 | ```bash 495 | dir="./"; for key in $(grep -Poi '(?<="\@string\/).+?(?=\")' "${dir}/AndroidManifest.xml" | sort -u); do val=$(xmlstarlet sel -t -v "/resources/string[@name='${key}']" "${dir}/res/values/strings.xml"); echo "${key}: ${val}"; done 496 | ``` 497 | 498 | ## strings.xml 499 | 500 | Always inspect `decoded/res/values/strings.xml` for endpoints, sensitive data \[in Base64 encoding\], etc. For more examples, see section [4. Inspect Files](#4-inspect-files). 501 | 502 | ## 3. Search for Files and Directories 503 | 504 | Search for files and directories from the root directory: 505 | 506 | ```bash 507 | find / -iname '*keyword*' 508 | ``` 509 | 510 | Search for files and directories in the app specific directories (run `env` in [Objection](#9-objection)): 511 | 512 | ```bash 513 | cd /data/user/0/com.someapp.dev/ 514 | 515 | cd /storage/emulated/0/Android/data/com.someapp.dev/ 516 | 517 | cd /storage/emulated/0/Android/obb/com.someapp.dev/ 518 | ``` 519 | 520 | If you want to download a whole directory from your Android device, see section [Download/Upload Files and Directories](#downloadupload-files-and-directories). 521 | 522 | I preffer downloading the app specific directories, and then doing the [file inspection](#4-inspect-files) on my Kali Linux. 523 | 524 | Search for files and directories from the current directory: 525 | 526 | ```bash 527 | find . -iname '*keyword*' 528 | 529 | for keyword in 'access' 'account' 'admin' 'card' 'cer' 'conf' 'cred' 'customer' 'email' 'history' 'info' 'json' 'jwt' 'key' 'kyc' 'log' 'otp' 'pass' 'pem' 'pin' 'plist' 'priv' 'refresh' 'salt' 'secret' 'seed' 'setting' 'sign' 'sql' 'token' 'transaction' 'transfer' 'tar' 'txt' 'user' 'zip' 'xml'; do find . -iname "*${keyword}*"; done 530 | ``` 531 | 532 | ### SharedPreferences 533 | 534 | Search for files and directories in [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences) insecure storage directory: 535 | 536 | ```bash 537 | cd /data/user/0/com.someapp.dev/shared_prefs/ 538 | ``` 539 | 540 | The files should not be world-readable (e.g., `-rw-rw-r--` is not good, and `-rw-rw----` is good): 541 | 542 | ```bash 543 | ls /data/user/0/com.someapp.dev/shared_prefs/ -al 544 | ``` 545 | 546 | If the production build is [debuggable](https://developer.android.com/topic/security/risks/android-debuggable), it is possible to get the read access rights to the app specific directories as a low-privileged user by leveraging `run-as` command. 547 | 548 | Download a file from SharedPreferences as non-root: 549 | 550 | ```bash 551 | adb exec-out run-as com.someapp.dev cat /data/user/0/com.someapp.dev/shared_prefs/somefile.xml > somefile.xml 552 | ``` 553 | 554 | SharedPreferences is unencrypted and backed up by default, and as such, should not contain any sensitive data after user logs out - it should be cleared by calling [SharedPreferences.Editor.clear\(\)](https://developer.android.com/reference/android/content/SharedPreferences.Editor#clear()). It should also be excluded from backups by specifying [dataExtractionRules](https://developer.android.com/guide/topics/data/autobackup#include-exclude-android-12) inside app's AndroidManifest.xml. 555 | 556 | ## 4. Inspect Files 557 | 558 | Inspect memory dumps, binaries, files inside [a decompiled APK](#14-decompile-an-apk), files inside the app specific directories, or any other files. 559 | 560 | After you finish testing \[and logout\], don't forget to [download](#downloadupload-files-and-directories) the app specific directories and inspect all the files inside. Inspect what is new and what still persists after the logout. 561 | 562 | There will be some false positive results since the regular expressions are not perfect. I prefer to use `rabin2` over `strings` because it can read Unicode characters. 563 | 564 | On your Android device, try to modify app's files to test the filesystem checksum validation, i.e., to test the file integrity validation. 565 | 566 | ### Single File 567 | 568 | Search for hardcoded sensitive data: 569 | 570 | ```bash 571 | rabin2 -zzzqq somefile | grep -Pi '[^\w\d\n]+(?:basic|bearer)\ .+' 572 | 573 | rabin2 -zzzqq somefile | grep -Pi '(?:access|account|admin|basic|bearer|card|conf|cred|customer|email|history|id|info|jwt|key|kyc|log|otp|pass|pin|priv|refresh|salt|secret|seed|setting|sign|token|transaction|transfer|user)[\w\d]*(?:\"\ *\:|\ *\=).+' 574 | 575 | rabin2 -zzzqq somefile | grep -Pi '[^\w\d\n]+(?:bug|comment|fix|issue|note|problem|to(?:\_|\ |)do|work)[^\w\d\n]+.+' 576 | ``` 577 | 578 | Extract URLs, deep links, IPs, etc.: 579 | 580 | ```bash 581 | rabin2 -zzzqq somefile | grep -Po '\w+\:\/\/[\w\-\.\@\:\/\?\=\%\&\#]+' | sort -uf | tee urls.txt 582 | 583 | rabin2 -zzzqq somefile | grep -Po '(?:\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}' | sort -uf | tee ips.txt 584 | ``` 585 | 586 | Extract all strings and decode Base64 strings: 587 | 588 | ```bash 589 | rabin2 -zzzqq somefile | sort -uf > strings.txt 590 | 591 | grep -Po '(?:[a-zA-Z0-9\+\/]{4})*(?:[a-zA-Z0-9\+\/]{4}|[a-zA-Z0-9\+\/]{3}\=|[a-zA-Z0-9\+\/]{2}\=\=)' strings.txt | sort -uf > base64.txt 592 | 593 | for string in $(cat base64.txt); do res=$(echo "${string}" | base64 -d 2>/dev/null | grep -PI '[\s\S]+'); if [[ ! -z $res ]]; then echo -n "${string}\n${res}\n\n"; fi; done | tee base64_decoded.txt 594 | ``` 595 | 596 | ### Multiple Files 597 | 598 | Search for hardcoded sensitive data: 599 | 600 | ```bash 601 | IFS=$'\n'; for file in $(find . -type f); do echo -n "\nFILE: \"${file}\"\n"; rabin2 -zzzqq "${file}" 2>/dev/null | grep -Pi '[^\w\d\n]+(?:basic|bearer)\ .+'; done 602 | 603 | IFS=$'\n'; for file in $(find . -type f); do echo -n "\nFILE: \"${file}\"\n"; rabin2 -zzzqq "${file}" 2>/dev/null | grep -Pi '(?:access|account|admin|basic|bearer|card|conf|cred|customer|email|history|id|info|jwt|key|kyc|log|otp|pass|pin|priv|refresh|salt|secret|seed|setting|sign|token|transaction|transfer|user)[\w\d]*(?:\"\ *\:|\ *\=).+'; done 604 | 605 | IFS=$'\n'; for file in $(find . -type f); do echo -n "\nFILE: \"${file}\"\n"; rabin2 -zzzqq "${file}" 2>/dev/null | grep -Pi '[^\w\d\n]+(?:bug|comment|fix|issue|note|problem|to(?:\_|\ |)do|work)[^\w\d\n]+.+'; done 606 | ``` 607 | 608 | Extract URLs, deep links, IPs, etc.: 609 | 610 | ```bash 611 | IFS=$'\n'; for file in $(find . -type f); do rabin2 -zzzqq "${file}" 2>/dev/null; done | grep -Po '\w+\:\/\/[\w\-\.\@\:\/\?\=\%\&\#]+' | grep -Piv '\.(css|gif|jpeg|jpg|ogg|otf|png|svg|ttf|woff|woff2)' | sort -uf | tee urls.txt 612 | 613 | IFS=$'\n'; for file in $(find . -type f); do rabin2 -zzzqq "${file}" 2>/dev/null; done | grep -Po '(?:\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}' | sort -uf | tee ips.txt 614 | ``` 615 | 616 | Extract all strings and decode Base64 strings: 617 | 618 | ```bash 619 | IFS=$'\n'; for file in $(find . -type f); do rabin2 -zzzqq "${file}" 2>/dev/null; done | sort -uf > strings.txt 620 | 621 | grep -Po '(?:[a-zA-Z0-9\+\/]{4})*(?:[a-zA-Z0-9\+\/]{4}|[a-zA-Z0-9\+\/]{3}\=|[a-zA-Z0-9\+\/]{2}\=\=)' strings.txt | sort -uf > base64.txt 622 | 623 | for string in $(cat base64.txt); do res=$(echo "${string}" | base64 -d 2>/dev/null | grep -PI '[\s\S]+'); if [[ ! -z $res ]]; then echo -n "${string}\n${res}\n\n"; fi; done | tee base64_decoded.txt 624 | ``` 625 | 626 | ### File Scraper 627 | 628 | Automate all of the above file inspection (and more) with a single tool, also using multithreading. 629 | 630 | ```bash 631 | apt-get -y install radare2 632 | 633 | pip3 install file-scraper 634 | ``` 635 | 636 | ```fundamental 637 | file-scraper -dir source -o file_scraper_results.html -e default 638 | ``` 639 | 640 | More about my other project at [ivan-sincek/file-scraper](https://github.com/ivan-sincek/file-scraper). 641 | 642 | ### SQLite 3 643 | 644 | Use [ADB](#downloadupload-files-and-directories) to download database files, and then open them using [DB Browser for SQLite](https://sqlitebrowser.org). 645 | 646 | To inspect the content, navigate to `Browse Data` tab, expand `Table` dropdown menu, and select the desired table. 647 | 648 |

SQLite

649 | 650 |

Figure 5 - DB Browser for SQLite

651 | 652 | To inspect and/or edit database files on your Android device directly, use [SQLite 3](#magisk-sqlite-3); [ADB](#android-debug-bridge-adb) to your Android device and run the following commands: 653 | 654 | ```sql 655 | sqlite3 somefile 656 | 657 | .dump 658 | 659 | .tables 660 | 661 | SELECT * FROM sometable; 662 | 663 | .quit 664 | ``` 665 | 666 | ### Nuclei 667 | 668 | Download mobile Nuclei templates: 669 | 670 | ```fundamental 671 | git clone https://github.com/optiv/mobile-nuclei-templates ~/mobile-nuclei-templates 672 | ``` 673 | 674 | Decode an APK using [Apktool](#decode). 675 | 676 | Search for hardcoded sensitive data: 677 | 678 | ```bash 679 | echo decoded | nuclei -t ~/mobile-nuclei-templates/Keys/ -o nuclei_keys_results.txt 680 | 681 | cat nuclei_keys_results.txt | grep -Po '(?<=\]\ ).+' | sort -uf > nuclei_keys_results_sorted.txt 682 | 683 | echo decoded | nuclei -t ~/mobile-nuclei-templates/Android/ -o nuclei_android_results.txt 684 | 685 | cat nuclei_android_results.txt | grep -Po '(?<=\]\ ).+' | sort -uf > nuclei_android_results_sorted.txt 686 | ``` 687 | 688 | ### Backups 689 | 690 | Create a backup of the whole Android device: 691 | 692 | ```fundamental 693 | adb backup -system -apk -shared -all -f backup.ab 694 | ``` 695 | 696 | Create a backup of a specific app: 697 | 698 | ``` 699 | adb backup -nosystem -noapk -noshared -f backup.ab com.someapp.dev 700 | ``` 701 | 702 | App should not backup any sensitive data. 703 | 704 | Restore from a backup: 705 | 706 | ```fundamental 707 | adb restore backup.ab 708 | ``` 709 | 710 | -- 711 | 712 | Download the latest [Android Backup Extrator](https://github.com/nelenkov/android-backup-extractor/releases), and repackage a backup to a browsable archive (TAR): 713 | 714 | ```fundamental 715 | java -jar abe.jar unpack backup.ab backup.tar 716 | ``` 717 | 718 | You can try to tamper with a browsable archive (TAR) and repackage it back to a restorable format: 719 | 720 | ```fundamental 721 | java -jar abe.jar pack backup.tar backup.ab 722 | ``` 723 | 724 | ## 5. SpotBugs 725 | 726 | SAST tool for identifying security vulnerabilities inside an APK, technically, inside a JAR. 727 | 728 | \[1\] Convert an APK to a JAR: 729 | 730 | ``` 731 | d2j-dex2jar base.apk -o base.jar 732 | ``` 733 | 734 | \[2\] Decompile the JAR using [jadx](#14-decompile-an-apk). You should now see the `source_jar` directory. 735 | 736 | \[3\] Download the latest version of the tool from [GitHub](https://github.com/spotbugs/spotbugs/releases), unpack the archive, and open your preferred console from the `/lib/` directory. 737 | 738 | Run with GUI: 739 | 740 | ```fundamental 741 | java -jar spotbugs.jar -gui 742 | ``` 743 | 744 |

SpotBugs

745 | 746 |

Figure 6 - SpotBugs

747 | 748 | Run without the GUI: 749 | 750 | ```fundamental 751 | java -jar spotbugs.jar -textui -progress -sourcepath /root/Desktop/source_jar/sources -html=/root/Desktop/spotbugs_results.html /root/Desktop/base.jar 752 | ``` 753 | 754 | More about the tool at [spotbugs/spotbugs](https://github.com/spotbugs/spotbugs). 755 | 756 | ## 6. Deep Links 757 | 758 | Test [/.well-known/assetlinks.json](https://developer.android.com/training/app-links/verify-android-applinks) using [developers.google.com/digital-asset-links/tools/generator](https://developers.google.com/digital-asset-links/tools/generator). 759 | 760 | Deep links can somtimes bypass authentication, including biometrics. 761 | 762 | Don't forget to test a deep link for a cross-site scripting (XSS), open redirect, etc., in case it is opening a WebView. 763 | 764 | --- 765 | 766 | Create an HTML template to manually test deep links (see also ##): 767 | 768 | ```bash 769 | mkdir android_deep_links 770 | 771 | # multiple URL schemes 772 | 773 | for scheme in $(cat url_schemes.txt); do for url in $(cat urls.txt | grep -Poi "${scheme}\:\/\/.+"); do if [[ ! -z $url ]]; then echo -n "${url}\n

\n" | tee -a "android_deep_links/${scheme}_deep_links.html"; fi; done; done 774 | 775 | # single URL scheme 776 | 777 | scheme="somescheme"; for string in $(cat urls.txt | grep -Poi "${scheme}\:\/\/.+"); do echo -n "${string}\n

\n"; done | tee -a "android_deep_links/${scheme}_deep_links.html" 778 | 779 | python3 -m http.server 9000 --directory android_deep_links 780 | ``` 781 | 782 | For `url_schemes.txt` see section [AndroidManifest.xml](#androidmanifestxml), and for `urls.txt` see section [4. Inspect Files](#4-inspect-files). 783 | 784 | --- 785 | 786 | Open a deep link using ADB: 787 | 788 | ``` 789 | adb shell am start -W -a android.intent.action.VIEW -d 'somescheme://com.someapp.dev/somepath?somekey=somevalue' 790 | ``` 791 | 792 | If you see a pop-up showing multiple apps to open the same deep link, it is very likely that this deep link could be hijacked. 793 | 794 | ### Android App Link Verification Tester 795 | 796 | Install: 797 | 798 | ```bash 799 | git clone https://github.com/inesmartins/Android-App-Link-Verification-Tester && cd Android-App-Link-Verification-Tester 800 | 801 | pip3 install -r requirements.txt 802 | ``` 803 | 804 | Decode an APK using [Apktool](#decode). You should now see the `decoded` directory. 805 | 806 | Get deep links: 807 | 808 | ```fundamental 809 | python3 deeplink_analyser.py -op list-applinks -m decoded/AndroidManifest.xml -s decoded/res/values/strings.xml 810 | ``` 811 | 812 | Build PoC: 813 | 814 | ```fundamental 815 | python3 deeplink_analyser.py -op build-poc -m decoded/AndroidManifest.xml -s decoded/res/values/strings.xml 816 | ``` 817 | 818 | Verify app links (valid app links have `http[s]` scheme): 819 | 820 | ```fundamental 821 | python3 deeplink_analyser.py -op verify-applinks -apk base.apk -p com.someapp.dev 822 | ``` 823 | 824 | ### Deep Link Hijacking 825 | 826 | Hijacking a deep link after a successful login on a website can easly lead to session hijacking. 827 | 828 | **Properly implemented app links cannot be hijacked.** 829 | 830 | To hijack a deep link, specify it in [AndroidManifest.xml](https://github.com/ivan-sincek/malware-apk/blob/main/src/Malware/app/src/main/AndroidManifest.xml#L48) inside a "malicious" PoC app: 831 | 832 | ```xml 833 | 837 | ``` 838 | 839 | Increasing the [priority](https://github.com/ivan-sincek/malware-apk/blob/main/src/Malware/app/src/main/AndroidManifest.xml#L44) might also increase your chances of hijacking a deep link: 840 | 841 | ```xml 842 | 843 | ``` 844 | 845 | After that, you will need to find a way to trigger your target deep link. 846 | 847 | Find out how to perform deep link hijacking using a "malicious" PoC app from my other [project](https://github.com/ivan-sincek/malware-apk#implicit-intent-testing). 848 | 849 | ## 7. WebViews 850 | 851 | Unless there is an explicit need, WebView URLs should not be user-controlled, e.g., through intents. 852 | 853 | WebViews can easily lead to cross-site scripting (XSS), arbitrary file read/write, data leakage and exfiltration, remote code execute (RCE), etc. 854 | 855 | Things to look for in the source code: 856 | * [WebView](https://developer.android.com/reference/android/webkit/WebView) 857 | * [setJavaScriptEnabled](https://developer.android.com/reference/android/webkit/WebSettings#setJavaScriptEnabled\(boolean\)) 858 | * default: `false` 859 | * [setAllowFileAccess](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess\(boolean\)) 860 | * default: `false` on Android OS v11.0+ and API v30+ 861 | * [setAllowUniversalAccessFromFileURLs](https://developer.android.com/reference/android/webkit/WebSettings#setAllowUniversalAccessFromFileURLs\(boolean\)) 862 | * default: `false` on Android OS v4.1+ and API v16+ 863 | * [setAllowFileAccessFromFileURLs](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccessFromFileURLs\(boolean\)) 864 | * default: `false` on Android OS v4.1+ and API v16+ 865 | * value is ignored if `getAllowUniversalAccessFromFileURLs` is `true` 866 | * [addJavascriptInterface](https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface\(java.lang.Object,%20java.lang.String\)) 867 | * default: only public methods annotated with `@JavascriptInterface` on Android OS v4.2+ and API v17+ can be added; otherwise, all public methods (including inherited ones) can be added 868 | * [loadUrl](https://developer.android.com/reference/android/webkit/WebView#loadUrl\(java.lang.String\)) 869 | 870 | Simple cross-site scripting (XSS) payloads: 871 | 872 | ```html 873 | javascript:alert(1) 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | ``` 883 | 884 | Arbitrary file read using the `file://` URL scheme: 885 | 886 | ```fundamental 887 | file:///data/data/com.someapp.dev/shared_prefs/somefile.xml 888 | ``` 889 | 890 | Arbitrary file read using a cross-site scripting (XSS): 891 | 892 | ```html 893 | 903 | ``` 904 | 905 | After you finish testing \[and logout\], don't forget to [download](#downloadupload-files-and-directories) the app specific directories and inspect all the files inside. Inspect what is new and what still persists after the logout. 906 | 907 | WebView specific directories to look for: 908 | 909 | * `app_webview` 910 | * `blob_storage` 911 | * `Cookies` 912 | * `pref_store` 913 | * `Service Worker` 914 | * `Session Storage` 915 | * `Web Data` 916 | 917 | ## 8. Frida 918 | 919 | Useful resources: 920 | 921 | * [frida.re](https://frida.re/docs/home) 922 | * [learnfrida.info](https://learnfrida.info) 923 | * [codeshare.frida.re](https://codeshare.frida.re) 924 | * [dweinstein/awesome-frida](https://github.com/dweinstein/awesome-frida) 925 | * [interference-security/frida-scripts](https://github.com/interference-security/frida-scripts) 926 | * [m0bilesecurity/Frida-Mobile-Scripts](https://github.com/m0bilesecurity/Frida-Mobile-Scripts) 927 | * [WithSecureLabs/android-keystore-audit](https://github.com/WithSecureLabs/android-keystore-audit) 928 | 929 | List processes: 930 | 931 | ```bash 932 | frida-ps -Uai 933 | 934 | frida-ps -Uai | grep -i 'keyword' 935 | ``` 936 | 937 | Get PID for a specified keyword: 938 | 939 | ```bash 940 | frida-ps -Uai | grep -i 'keyword' | cut -d ' ' -f 1 941 | ``` 942 | 943 | Discover internal methods/calls: 944 | 945 | ```bash 946 | frida-discover -U -f com.someapp.dev | tee frida_discover.txt 947 | ``` 948 | 949 | Trace internal methods/calls: 950 | 951 | ```bash 952 | frida-trace -U -p 1337 953 | 954 | frida-trace -U -p 1337 -i 'recv*' -i 'send*' 955 | ``` 956 | 957 | ### Frida Scripts 958 | 959 | Bypass SSL Pinning using [android-ssl-pinning-bypass-2](https://codeshare.frida.re/@ivan-sincek/android-ssl-pinning-bypass-2) script: 960 | 961 | ```fundamental 962 | frida -U -no-pause -l android-ssl-pinning-bypass-2.js -f com.someapp.dev 963 | 964 | frida -U -no-pause --codeshare ivan-sincek/android-ssl-pinning-bypass-2 -f com.someapp.dev 965 | ``` 966 | 967 | I prefer to use the built-in method in [Objection](#bypasses). 968 | 969 | --- 970 | 971 | For this Frida script to work, you need to push your Burp Proxy or ZAP certificate to a specific location with the specific name `cacert.der`: 972 | 973 | ```fundamental 974 | adb push cacert.der /data/local/tmp/cacert.der 975 | ``` 976 | 977 | Bypass SSL Pinning using [android-ssl-pinning-bypass](https://codeshare.frida.re/@ivan-sincek/android-ssl-pinning-bypass) script: 978 | 979 | ```fundamental 980 | frida -U -no-pause -l android-ssl-pinning-bypass.js -f com.someapp.dev 981 | 982 | frida -U -no-pause --codeshare ivan-sincek/android-ssl-pinning-bypass -f com.someapp.dev 983 | ``` 984 | 985 | I prefer to use the built-in method in [Objection](#bypasses). 986 | 987 | --- 988 | 989 | Monitor all intent calls, including deep links, using [android-intent-monitor](https://codeshare.frida.re/@ivan-sincek/android-intent-monitor) script: 990 | 991 | ```fundamental 992 | frida -U -no-pause -l android-intent-monitor.js -f com.someapp.dev 993 | 994 | frida -U -no-pause --codeshare ivan-sincek/android-intent-monitor -f com.someapp.dev 995 | ``` 996 | 997 | ## 9. Objection 998 | 999 | Useful resources: 1000 | 1001 | * [sensepost/objection](https://github.com/sensepost/objection) 1002 | 1003 | Run: 1004 | 1005 | ```fundamental 1006 | objection -g com.someapp.dev explore 1007 | ``` 1008 | 1009 | Run a [Frida](#8-frida) script in Objection: 1010 | 1011 | ```fundamental 1012 | import somescript.js 1013 | 1014 | objection -g com.someapp.dev explore --startup-script somescript.js 1015 | ``` 1016 | 1017 | Get environment variables: 1018 | 1019 | ```fundamental 1020 | env 1021 | ``` 1022 | 1023 | List KeyStore: 1024 | 1025 | ```fundamental 1026 | android keystore list 1027 | ``` 1028 | 1029 | Dump app's memory to a file: 1030 | 1031 | ```fundamental 1032 | memory dump all mem.dmp 1033 | ``` 1034 | 1035 | Dump app's memory after, e.g., 10 minutes of inactivity, then, check if sensitive data is still in the memory. See section [4. Inspect Files](#4-inspect-files). 1036 | 1037 | **In case Objection detaches from the app, use the process ID to attach it back without restarting the app.** 1038 | 1039 | Search app's memory directly: 1040 | 1041 | ```bash 1042 | memory search 'somestring' --string 1043 | ``` 1044 | 1045 | List classes and methods: 1046 | 1047 | ```bash 1048 | android hooking list classes 1049 | 1050 | android hooking search classes com.someapp.dev 1051 | android hooking search classes 'keyword' 1052 | 1053 | android hooking list class_methods 'someclass' 1054 | android hooking search methods com.someapp.dev 'someclass' 1055 | ``` 1056 | 1057 | Hook on a class or method: 1058 | 1059 | ```bash 1060 | android hooking watch class 'someclass' 1061 | 1062 | android hooking watch class_method 'somemethod' --dump-args --dump-backtrace --dump-return 1063 | ``` 1064 | 1065 | Change the method's return value: 1066 | 1067 | ```bash 1068 | android hooking set return_value 'somemethod' 'somevalue' 1069 | ``` 1070 | 1071 | Monitor the clipboard: 1072 | 1073 | ```fundamental 1074 | android clipboard monitor 1075 | ``` 1076 | 1077 | ### Bypasses 1078 | 1079 | Bypass a root detection: 1080 | 1081 | ```bash 1082 | android root disable --quiet 1083 | 1084 | objection -g com.someapp.dev explore --startup-command 'android root disable --quiet' 1085 | ``` 1086 | 1087 | --- 1088 | 1089 | Bypass SSL pinning: 1090 | 1091 | ```bash 1092 | android sslpinning disable --quiet 1093 | 1094 | objection -g com.someapp.dev explore --startup-command 'android sslpinning disable --quiet' 1095 | ``` 1096 | 1097 | Also, you can import [Frida](#frida-scripts) script. 1098 | 1099 | ## 10. Drozer 1100 | 1101 | Connect to a remote agent: 1102 | 1103 | ```fundamental 1104 | drozer console connect --server 192.168.1.10 1105 | ``` 1106 | 1107 | List modules and show module details: 1108 | 1109 | ```fundamental 1110 | list 1111 | 1112 | run somemodule --help 1113 | ``` 1114 | 1115 | List / search packages: 1116 | 1117 | ```bash 1118 | run app.package.list 1119 | 1120 | run app.package.list -f 'keyword' 1121 | 1122 | run app.package.list -p android.permission.SOME_PERMISSION 1123 | 1124 | run app.package.backup 1125 | 1126 | run app.package.debuggable 1127 | ``` 1128 | 1129 | Show a package information: 1130 | 1131 | ```fundamental 1132 | run app.package.info -a com.someapp.dev 1133 | ``` 1134 | 1135 | Show app's AndroidManifest.xml: 1136 | 1137 | ```fundamental 1138 | run app.package.manifest com.someapp.dev 1139 | ``` 1140 | 1141 | In case Drozer did not fetch the whole manifest file, decode an APK using [Apktool](#decode) and inspect the file manually. 1142 | 1143 | Show app's attack surface: 1144 | 1145 | ```fundamental 1146 | run app.package.attacksurface com.someapp.dev 1147 | ``` 1148 | 1149 | ### Intents 1150 | 1151 | Intents, together with other Android components, can easily lead to cross-site scripting (XSS), arbitrary file read/write, data leakage and exfiltration, remote code execute (RCE), etc. 1152 | 1153 | Read more about intents and intent filters [here](developer.android.com/guide/components/intents-filters). 1154 | 1155 | List exported and protected (unexported) activities and their intents: 1156 | 1157 | ```fundamental 1158 | run app.activity.info -i -a com.someapp.dev 1159 | 1160 | run app.activity.info -u -i -a com.someapp.dev 1161 | ``` 1162 | 1163 | Examine the launch intent (main activity): 1164 | 1165 | ```fundamental 1166 | run app.package.launchintent com.someapp.dev 1167 | ``` 1168 | 1169 | List browsable URIs (deep links): 1170 | 1171 | ``` 1172 | run scanner.activity.browsable -a com.someapp.dev 1173 | ``` 1174 | 1175 | You will need to [reverse engineer](#14-decompile-an-apk) the APK and look into the source code to find out what parameters need to be sent to the intent to exploit it. 1176 | 1177 | Start an activity: 1178 | 1179 | ```fundamental 1180 | run app.activity.start --component com.someapp.dev com.someapp.dev.SomeActivity 1181 | 1182 | run app.activity.start --component com.someapp.dev com.someapp.dev.SomeActivity --action android.intent.action.SOME_ACTION --data-uri somescheme://somehost --extra integer somekey somevalue --extra string somekey somevalue 1183 | ``` 1184 | 1185 | Use `--help` to see more options. 1186 | 1187 | __In Drozer, you cannot pass arrays, lists, objects, etc., to an intent due to the console line interface (CLI) limitations, but the same can be done if you build your own "malicious" app.__ 1188 | 1189 | ### Content Providers 1190 | 1191 | Read more about content providers [here](https://developer.android.com/guide/topics/providers/content-providers). 1192 | 1193 | List exported and protected (unexported) content providers: 1194 | 1195 | ```fundamental 1196 | run app.provider.info -a com.someapp.dev 1197 | 1198 | run app.provider.info -u -a com.someapp.dev 1199 | ``` 1200 | 1201 | List, query, and scan for vulnerabilities all content providers' URIs: 1202 | 1203 | ```fundamental 1204 | run app.provider.finduri com.someapp.dev 1205 | 1206 | run scanner.provider.finduris -a com.someapp.dev 1207 | 1208 | run scanner.provider.injection -a com.someapp.dev 1209 | 1210 | run scanner.provider.sqltables -a com.someapp.dev 1211 | 1212 | run scanner.provider.traversal -a com.someapp.dev 1213 | ``` 1214 | 1215 | You will need to [reverse engineer](#14-decompile-an-apk) the APK and look into the source code to find out what parameters need to be sent to the content provider to exploit it. 1216 | 1217 | Content provider CRUD controls and more: 1218 | 1219 | ```fundamental 1220 | run app.provider.insert content://com.someapp.dev.ContentProvider --integer somekey somevalue --string somekey somevalue 1221 | 1222 | run app.provider.query content://com.someapp.dev.ContentProvider --projection '*' 1223 | 1224 | run app.provider.query content://com.someapp.dev.ContentProvider --projection '* FROM anothertable;--' 1225 | 1226 | run app.provider.update content://com.someapp.dev.ContentProvider --selection 'somekey=?' --selection-args somevalue --integer somekey somevalue --string somekey somevalue 1227 | 1228 | run app.provider.delete content://com.someapp.dev.ContentProvider --selection 'somekey=?' --selection-args somevalue 1229 | 1230 | run app.provider.read content://com.someapp.dev.FileProvider/etc/hosts 1231 | ``` 1232 | 1233 | Use `--help` to see more options. 1234 | 1235 | ### Broadcast Receivers 1236 | 1237 | Read more about broadcasts [here](https://developer.android.com/develop/background-work/background-tasks/broadcasts). 1238 | 1239 | List exported and protected (unexported) broadcast receivers: 1240 | 1241 | ```fundamental 1242 | run app.broadcast.info -i -a com.someapp.dev 1243 | 1244 | run app.broadcast.info -i -u -a com.someapp.dev 1245 | ``` 1246 | 1247 | Monitor broadcast receivers: 1248 | 1249 | ```fundamental 1250 | run app.broadcast.sniff --action com.someapp.dev.SOME_ACTION 1251 | ``` 1252 | 1253 | You will need to [reverse engineer](#14-decompile-an-apk) the APK and look into the source code to find out what parameters need to be sent to the broadcast receiver to exploit it. 1254 | 1255 | Send data to a broadcast receiver: 1256 | 1257 | ```fundamental 1258 | run app.broadcast.send --action com.someapp.dev.SOME_ACTION --extra integer somekey somevalue --extra string somekey somevalue 1259 | ``` 1260 | 1261 | __In Drozer, you cannot specify a broadcast receiver, but in [ADB](#android-debug-bridge-adb), you can.__ 1262 | 1263 | If a broadcast receiver does not have an intent filter, you can try triggering it with a non-existent action: 1264 | 1265 | ```fundamental 1266 | adb shell am broadcast -a android.intent.action.NON_EXISTING_ACTION -n come.someapp.dev/.SomeReceiver 1267 | ``` 1268 | 1269 | Use `--help` to see more options. 1270 | 1271 | ### Services 1272 | 1273 | Read more about services [here](https://developer.android.com/develop/background-work/services). 1274 | 1275 | List exported and protected (unexported) services: 1276 | 1277 | ```fundamental 1278 | run app.service.info -i -a com.someapp.dev 1279 | 1280 | run app.service.info -i -u -a com.someapp.dev 1281 | ``` 1282 | 1283 | You will nedd to [reverse engineer](#14-decompile-an-apk) the APK and look into the source code to find out what parameters need to be sent to the service to exploit it. 1284 | 1285 | Send data to a service: 1286 | 1287 | ```fundamental 1288 | run app.service.send com.someapp.dev com.someapp.dev.SomeService --msg what arg1 arg2 --extra string somevalue --extra integer somevalue --bundle-as-obj 1289 | ``` 1290 | 1291 | `--msg` is a special type of input. Read more about the Message class [here](https://developer.android.com/reference/android/os/Message). 1292 | 1293 | `--bundle-as-obj` helps you to parse a special type of return data. Read more about the Bundle class [here](https://developer.android.com/reference/android/os/Bundle). 1294 | 1295 | Use `--help` to see more options. 1296 | 1297 | ## 11. Intent Injections 1298 | 1299 | Access a protected (unexported) component, such as a private file or an SQLite content provider, using an exported (proxy) intent. 1300 | 1301 | This can easily lead to arbitrary file read/write, data leakage and exfiltration, remote code execute (RCE), etc. 1302 | 1303 | **This can only be done using a "malicious" PoC app, as it is too complex for tools such as Drozer.** 1304 | 1305 | Find out how to perform intent injections using a "malicious" PoC app from my other [project](https://github.com/ivan-sincek/malware-apk#implicit-intent-injection-testing). 1306 | 1307 | ## 12. Taskjacking 1308 | 1309 | Find out how to perform [taskjacking](https://developer.android.com/privacy-and-security/risks/strandhogg) using a "malicious" PoC app from my other [project](https://github.com/ivan-sincek/malware-apk#task-hijacking-testing). 1310 | 1311 | Sometimes, this is by design, to improve the user experience (UX) when "switching" between two apps. 1312 | 1313 | ## 13. Tapjacking 1314 | 1315 | Find out how to perform [tapjacking](https://developer.android.com/privacy-and-security/risks/tapjacking) using a "malicious" PoC app from my other [project](https://github.com/ivan-sincek/malware-apk#tapjacking-testing). 1316 | 1317 | App should prevent overlays on sensitive data inputs by specifying `android:filterTouchesWhenObscured="true"` in its layout files. 1318 | 1319 | ## 14. Decompile an APK 1320 | 1321 | Decompile an APK: 1322 | 1323 | ```bash 1324 | jadx --threads-count $(grep -c 'processor' /proc/cpuinfo) -d /root/Desktop/source/ /root/Desktop/base.apk 1325 | ``` 1326 | 1327 | **`d2j-dex2jar` \+ `jadx` actually gives the best results.** 1328 | 1329 | Convert an APK to a JAR: 1330 | 1331 | ```fundamental 1332 | d2j-dex2jar base.apk -o base.jar 1333 | ``` 1334 | 1335 | Decompile a JAR: 1336 | 1337 | ```bash 1338 | jadx --threads-count $(grep -c 'processor' /proc/cpuinfo) -d /root/Desktop/source_jar/ /root/Desktop/base.jar 1339 | ``` 1340 | 1341 | Decompiling a JAR will give you a different directory structure, so you might want to decompile both, base.jar and base.apk. 1342 | 1343 | Make sure to specify a full path to the output directory; otherwise, it will default to `/usr/share/jadx/bin/` directory (i.e., to the root directory). 1344 | 1345 | Make sure to specify a full path to the base.jar or [base.apk](#pull-an-apk-baseapk); otherwise, JADX might not recognize it. 1346 | 1347 | To inspect the source code using GUI, run the following command and open either base.jar or base.apk: 1348 | 1349 | ```fundamental 1350 | jadx-gui 1351 | ``` 1352 | 1353 | --- 1354 | 1355 | Resolve `java.lang.OutOfMemoryError` issue by modifying `/usr/bin/d2j-dex2jar` and increasing the heap size specified in `-Xms` and `-Xmx` parameters, for example: 1356 | 1357 | ```fundamental 1358 | java -Xms1024m -Xmx4096m -classpath "${_classpath}" "com.googlecode.dex2jar.tools.Dex2jarCmd" "$@" 1359 | ``` 1360 | 1361 | ## 15. Repackage an APK 1362 | 1363 | ### Decode 1364 | 1365 | Get the SMALI source code from an APK. Convenient for quickly fetching and inspecting app's AndroidManifest.xml. 1366 | 1367 | ```fundamental 1368 | apktool decode base.apk -o decoded 1369 | ``` 1370 | 1371 | Decode an APK without decoding the sources and resources: 1372 | 1373 | ```fundamental 1374 | apktool decode -r -s base.apk -o decoded 1375 | ``` 1376 | 1377 | ### Repackage 1378 | 1379 | Create a repackaged APK from the decoded directory: 1380 | 1381 | ```fundamental 1382 | apktool build -f decoded -o repackaged.apk 1383 | ``` 1384 | 1385 | ZIP align all the files inside the repackaged APK and check the alignments: 1386 | 1387 | ```fundamental 1388 | zipalign -v 4 repackaged.apk 1389 | 1390 | zipalign -c -v 4 repackaged.apk 1391 | ``` 1392 | 1393 | ### Code Sign 1394 | 1395 | [keytool](https://docs.oracle.com/javase/10/tools/keytool.htm) and [jarsigner](https://docs.oracle.com/javase/10/tools/jarsigner.htm) come pre-installed with [Java](#java). However, use [apksigner](https://developer.android.com/tools/apksigner) for the best results because it can use `v1-4` signature schemes; while `jarsigner` can only use `v1` signature scheme. 1396 | 1397 | Generate a code signing certificate: 1398 | 1399 | ```fundamental 1400 | keytool -genkey -keyalg RSA -validity 365 -keysize 2048 -storetype PKCS12 -alias apk_rsa_priv -keystore apk_rsa_priv.key -storepass 12345678 1401 | ``` 1402 | 1403 | Code sign the repackaged APK: 1404 | 1405 | ```fundamental 1406 | apksigner sign --ks apk_rsa_priv.key --ks-pass "pass:12345678" repackaged.apk 1407 | 1408 | jarsigner -sigalg SHA256withRSA -digestalg SHA-256 -tsa http://timestamp.digicert.com -keystore apk_rsa_priv.key -storepass 12345678 repackaged.apk apk_rsa_priv 1409 | ``` 1410 | 1411 | Verify the repackaged APK's code signature: 1412 | 1413 | ```fundamental 1414 | apksigner verify repackaged.apk 1415 | 1416 | jarsigner -verify -verbose -certs repackaged.apk 1417 | ``` 1418 | 1419 | ## 16. Miscellaneous 1420 | 1421 | ### Monitor the System Log 1422 | 1423 | On your Kali Linux, run the following command: 1424 | 1425 | ```fundamental 1426 | adb logcat | grep 1337 1427 | ``` 1428 | 1429 | Or, get the PID from a keyword: 1430 | 1431 | ```fundamental 1432 | keyword="keyword"; adb logcat | grep $(frida-ps -Uai | grep -i "${keyword}" | tr -s '[:blank:]' ' ' | cut -d ' ' -f 1) 1433 | ``` 1434 | 1435 | ### Monitor File Changes 1436 | 1437 | On your Kali Linux, download the latest `fsmon` version from [GitHub](https://github.com/nowsecure/fsmon/releases), upload it to your Android device, give it necessary permissions, and run it: 1438 | 1439 | ```bash 1440 | adb push fsmon-and-arm /data/local/tmp/ 1441 | 1442 | adb shell su 1443 | 1444 | chmod +x /data/local/tmp/fsmon-and-arm 1445 | 1446 | /data/local/tmp/fsmon-and-arm /data/data/com.someapp.dev/ 1447 | ``` 1448 | 1449 | Always look for created or cached files, images/screenshots, etc. 1450 | 1451 | Sensitive files such as know your customer (KYC) and similar, should not persists in the app specific directories on the user device after the file upload. Sensitive files should not be stored in `/tmp/` directory nor similar system-wide directories. 1452 | 1453 | Images and screenshots path: 1454 | 1455 | ```fundamental 1456 | cd /mnt/sdcard/DCIM/ 1457 | cd /storage/emulated/0/DCIM/ 1458 | 1459 | cd /mnt/media_rw/3664-6132/DCIM/ 1460 | cd /storage/3664-6132/DCIM/ 1461 | 1462 | cd /data/system_ce/0/snapshots/ 1463 | ``` 1464 | 1465 | Don't confuse `/mnt/sdcard/` path with a real removable storage path because sometimes such path is device specific, so you will need to search it on the internet or extract it using some Java code. In my case it is `/mnt/media_rw/3664-6132/` path. 1466 | 1467 | ## 17. Tips and Security Best Practices 1468 | 1469 | Bypass any keyboard restriction by copying and pasting data into an input field. 1470 | 1471 | Access tokens should be short lived, and if possible, invalidated on logout. 1472 | 1473 | Don't forget to test widgets, push notifications, and Firebase. 1474 | 1475 | Sometimes, deep links and widgets can bypass authentication, including biometrics. 1476 | 1477 | Only if explicitly allowed, try flooding 3rd party APIs to cause possible monetary damage to the company, or denial-of-service (DoS) by exhausting the allowed quotas/limits. 1478 | 1479 | --- 1480 | 1481 | App should not disclose sensitive data in the predictive text (due to incorrectly defined input field type), app switcher, and push notifications. 1482 | 1483 | App should warn a user when taking a screenshot of sensitive data. 1484 | 1485 | App should warn a user that it is trivial to bypass biometrics authentication if Android device is jailbroken. 1486 | 1487 | Production app (i.e., build) should not be debuggable. 1488 | 1489 | ## 18. Useful Websites and Tools 1490 | 1491 | | URL | Description | 1492 | | --- | --- | 1493 | | [developer.android.com](https://developer.android.com) | Official Android documentation. | 1494 | | [streaak/keyhacks](https://github.com/streaak/keyhacks) | Validate various API keys. | 1495 | | [zxing.org/w/decode.jspx](https://zxing.org/w/decode.jspx) | Decode QR codes. | 1496 | | [odinforum.com](https://odinforum.com/discussion/11/latest-versions-of-odin-flashing-tool) | Firmware flashing tool for Samsung devices. | 1497 | | [developer.samsung.com/android-usb-driver](https://developer.samsung.com/android-usb-driver) | USB driver for Samsung devices. | 1498 | | [samfrew.com](https://samfrew.com) | Firmwares for Samsung devices. | 1499 | | [xdaforums.com](https://xdaforums.com/t/magisk-the-magic-mask-for-android.3473445) | Mobile software development forum. | 1500 | 1501 | ## 19. Vulnerable Apps 1502 | 1503 | Vulnerable apps for learning purposes: 1504 | 1505 | * [payatu/diva-android](https://github.com/payatu/diva-android) 1506 | * [WithSecureLabs/sieve](https://github.com/WithSecureLabs/sieve) 1507 | * [satishpatnayak/AndroGoat](https://github.com/satishpatnayak/AndroGoat) 1508 | * [dineshshetty/Android-InsecureBankv2](https://github.com/dineshshetty/Android-InsecureBankv2) 1509 | * [ctf.hpandro.raviramesh.info](https://ctf.hpandro.raviramesh.info) 1510 | -------------------------------------------------------------------------------- /binaries/SQLite3UniversalBinaries-1.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-sincek/android-penetration-testing-cheat-sheet/a843dce3d7cd8892306b7c4948c77be6e713e78c/binaries/SQLite3UniversalBinaries-1.5.zip -------------------------------------------------------------------------------- /img/exporting_burp_suite_proxy_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-sincek/android-penetration-testing-cheat-sheet/a843dce3d7cd8892306b7c4948c77be6e713e78c/img/exporting_burp_suite_proxy_certificate.png -------------------------------------------------------------------------------- /img/exporting_zap_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-sincek/android-penetration-testing-cheat-sheet/a843dce3d7cd8892306b7c4948c77be6e713e78c/img/exporting_zap_certificate.png -------------------------------------------------------------------------------- /img/magisk_install_from_storage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-sincek/android-penetration-testing-cheat-sheet/a843dce3d7cd8892306b7c4948c77be6e713e78c/img/magisk_install_from_storage.jpg -------------------------------------------------------------------------------- /img/spotbugs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-sincek/android-penetration-testing-cheat-sheet/a843dce3d7cd8892306b7c4948c77be6e713e78c/img/spotbugs.jpg -------------------------------------------------------------------------------- /img/sqlite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-sincek/android-penetration-testing-cheat-sheet/a843dce3d7cd8892306b7c4948c77be6e713e78c/img/sqlite.png -------------------------------------------------------------------------------- /img/wifi_adb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivan-sincek/android-penetration-testing-cheat-sheet/a843dce3d7cd8892306b7c4948c77be6e713e78c/img/wifi_adb.jpg -------------------------------------------------------------------------------- /scripts/android-intent-monitor.js: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * Name: Android Intent Monitor 3 | * OS: Android 4 | * Author: ivan-sincek 5 | * Source: https://github.com/ivan-sincek/android-penetration-testing-cheat-sheet/blob/main/scripts/android-intent-monitor.js 6 | ************************************************************************/ 7 | function hook(intent) { 8 | var text = []; 9 | var tmp = null; 10 | tmp = intent.getComponent(); 11 | if (tmp) { 12 | text.push("Activity: " + tmp.getClassName()); 13 | } 14 | tmp = intent.getAction(); 15 | if (tmp) { 16 | text.push("Action: " + tmp); 17 | } 18 | tmp = intent.getData(); 19 | if (tmp) { 20 | text.push("URI: " + tmp); 21 | } 22 | tmp = intent.getFlags(); 23 | if (tmp) { 24 | text.push("Flags: " + tmp); 25 | } 26 | tmp = intent.getType(); 27 | if (tmp) { 28 | text.push("Type: " + tmp); 29 | } 30 | tmp = intent.getExtras(); 31 | if (tmp) { 32 | var keys = tmp.keySet().iterator(); 33 | while (keys.hasNext()) { 34 | var key = keys.next(); 35 | var obj = tmp.get(key); 36 | var value = "null"; 37 | var type = ""; 38 | if (obj) { 39 | try { 40 | type = obj.getClass().getSimpleName(); 41 | value = (obj.getClass().isArray() ? Java.use("org.json.JSONArray").$new(obj) : obj).toString(); 42 | } catch (error) { 43 | value = error.toString(); 44 | } 45 | } 46 | text.push("Extra \"" + key + "\" (" + type + "): " + value); 47 | } 48 | } 49 | text.push("--------------------"); 50 | console.log(text.join("\n")); 51 | } 52 | function hookGetData() { 53 | hook(this); 54 | return this.getData(); 55 | } 56 | function hookGetIntent() { 57 | var intent = this.getIntent(); 58 | hook(intent); 59 | return intent; 60 | } 61 | setTimeout(function() { 62 | Java.perform(function() { 63 | console.log(""); 64 | var Intent = Java.use("android.content.Intent"); 65 | Intent.getData.implementation = hookGetData; 66 | // var Activity = Java.use("android.app.Activity"); 67 | // Activity.getIntent.implementation = hookGetIntent; 68 | }); 69 | }, 0); 70 | -------------------------------------------------------------------------------- /scripts/android-ssl-pinning-bypass-2.js: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * Name: Android SSL Pinning Bypass 2 3 | * OS: Android 4 | * Author: sowdust (Credits to the author!) 5 | * Source: https://codeshare.frida.re/@sowdust/universal-android-ssl-pinning-bypass-2 6 | * Edited: https://github.com/ivan-sincek/android-penetration-testing-cheat-sheet/blob/main/scripts/android-ssl-pinning-bypass-2.js 7 | ************************************************************************/ 8 | setTimeout(function() { 9 | Java.perform(function() { 10 | var ArrayList = Java.use("java.util.ArrayList"); 11 | var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl"); 12 | console.log("Running Android SSL Pinning Bypass..."); 13 | TrustManagerImpl.checkTrustedRecursive.implementation = function(a, b, c, d, e, f) { 14 | return ArrayList.$new(); 15 | } 16 | }); 17 | }, 0); 18 | -------------------------------------------------------------------------------- /scripts/android-ssl-pinning-bypass.js: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * Name: Android SSL Pinning Bypass 3 | * OS: Android 4 | * Author: pcipolloni (Credits to the author!) 5 | * Source: https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida 6 | * Edited: https://github.com/ivan-sincek/android-penetration-testing-cheat-sheet/blob/main/scripts/android-ssl-pinning-bypass.js 7 | * Extras: adb push cacert.der /data/local/tmp/cacert.der 8 | ************************************************************************/ 9 | setTimeout(function() { 10 | Java.perform(function() { 11 | var FileInputStream = Java.use("java.io.FileInputStream"); 12 | var BufferedInputStream = Java.use("java.io.BufferedInputStream"); 13 | var CertificateFactory = Java.use("java.security.cert.CertificateFactory"); 14 | var X509Certificate = Java.use("java.security.cert.X509Certificate"); 15 | var KeyStore = Java.use("java.security.KeyStore"); 16 | var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory"); 17 | var SSLContext = Java.use("javax.net.ssl.SSLContext"); 18 | 19 | var certificate = "/data/local/tmp/cacert.der"; 20 | 21 | console.log("[>] Android SSL Pinning Bypass"); 22 | console.log("[+] Loading CA..."); 23 | var ca = null; 24 | var fileInputStream = null; 25 | var bufferedInputStream = null; 26 | try { 27 | fileInputStream = FileInputStream.$new(certificate); 28 | bufferedInputStream = BufferedInputStream.$new(fileInputStream); 29 | ca = CertificateFactory.getInstance("X.509").generateCertificate(bufferedInputStream); 30 | } catch (error) { 31 | console.error("[X] " + error); 32 | } finally { 33 | if (fileInputStream !== null) { 34 | fileInputStream.close(); 35 | } 36 | if (bufferedInputStream !== null) { 37 | bufferedInputStream.close(); 38 | } 39 | } 40 | if (ca !== null) { 41 | console.log("[>] CA Info: " + Java.cast(ca, X509Certificate).getSubjectDN()); 42 | 43 | console.log("[+] Creating KeyStore..."); 44 | var keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 45 | keyStore.load(null, null); 46 | keyStore.setCertificateEntry("ca", ca); 47 | 48 | console.log("[+] Creating TrustManager..."); 49 | var trustManager = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 50 | trustManager.init(keyStore); 51 | 52 | console.log("[>] Hijacking SSLContext methods..."); 53 | console.log("[>] Waiting for the application to invoke SSLContext.init()..."); 54 | 55 | SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a, b, c) { 56 | console.log("[>] Application invoked SSLContext.init()!"); 57 | SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, trustManager.getTrustManagers(), c); 58 | console.log("[+] SSLContext.init() has been initialized with a custom TrustManager!"); 59 | }; 60 | } 61 | }); 62 | }, 0); 63 | -------------------------------------------------------------------------------- /scripts/gcp_firebase.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # pip3 install pyrebase4 4 | 5 | import pyrebase 6 | 7 | config = { 8 | "apiKey": "apiKey", 9 | "authDomain": "authDomain.firebaseapp.com", 10 | "databaseURL": "https://databaseURL.firebaseio.com", 11 | "storageBucket": "storageBucket.appspot.com" 12 | } 13 | 14 | firebase = pyrebase.initialize_app(config) 15 | 16 | db = firebase.database() 17 | 18 | print(db.get()) 19 | --------------------------------------------------------------------------------