Expand and polish up the per-script documentation

This commit is contained in:
Tim Perry
2023-10-23 17:43:40 +02:00
parent fa12f2010d
commit e126af2902
6 changed files with 56 additions and 21 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ To get started:
-l ./android/android-proxy-override.js \
-l ./android/android-system-certificate-injection.js \
-l ./android/android-certificate-unpinning.js \
-l ./android/android-fallback-script.js \
-l ./android/android-certificate-unpinning-fallback.js \
-f $PACKAGE_ID
```
7. Explore, examine & modify all the traffic you're interested in! If you have any problems, please [open an issue](https://github.com/httptoolkit/frida-android-unpinning/issues/new) and help make these scripts even better.
@@ -1,22 +1,24 @@
/**
* Once we've set up the configuration and certificate, and then disabled all the
* pinning techniques we're aware of, we add one last touch: a fallback hook,
* designed to spot and handle unknown unknowns.
/**************************************************************************************************
*
* This can also be useful for heavily obfuscated apps, where 3rd party libraries
* are obfuscated sufficiently that our hooks no longer recognize the methods we
* care about.
* Once we've set up the configuration and certificate, and then disabled all the pinning
* techniques we're aware of, we add one last touch: a fallback hook, designed to spot and handle
* unknown unknowns.
*
* To handle this, we watch for methods that throw known built-in TLS errors
* (these are _very_ widely used, and always recognizable as they're defined natively),
* and then subsequently patch them for all future calls. Whenever a method throws
* this, we attempt to recognize it from signatures alone, and automatically hook it.
* This can also be useful for heavily obfuscated apps, where 3rd party libraries are obfuscated
* sufficiently that our hooks no longer recognize the methods we care about.
*
* These are very much a fallback! They might not work! They almost certainly won't
* work on the first request, so applications will see at least one failure.
* Even when they fail though, they will at least log the method that's failing, so
* this works well as a starting point for manual reverse engineering.
*/
* To handle this, we watch for methods that throw known built-in TLS errors (these are *very*
* widely used, and always recognizable as they're defined natively), and then subsequently patch
* them for all future calls. Whenever a method throws this, we attempt to recognize it from
* signatures alone, and automatically hook it.
*
* These are very much a fallback! They might not work! They almost certainly won't work on the
* first request, so applications will see at least one failure. Even when they fail though, they
* will at least log the method that's failing, so this works well as a starting point for manual
* reverse engineering. If this does fail and cause problems, you may want to skip this script
* and use only the known-good patches provided elsewhere.
*
*************************************************************************************************/
// Capture the full fields or methods from a Frida class reference via JVM reflection:
const getFields = (cls) => getFridaValues(cls, cls.class.getDeclaredFields());
+21
View File
@@ -1,3 +1,24 @@
/**************************************************************************************************
*
* This script defines a large set of targeted certificate unpinning hooks: matching specific
* methods in certain classes, and transforming their behaviour to ensure that restrictions to
* TLS trust are disabled.
*
* This does not disable TLS protections completely - each hook is designed to disable only
* *additional* restrictions, and to explicitly trust the certificate provided as CERT_PEM in the
* config.js configuration file, preserving normal TLS protections wherever possible, even while
* allowing for controlled MitM of local traffic.
*
* The file consists of a few general-purpose methods, then a data structure declaratively
* defining the classes & methods to match, and how to transform them, and then logic at the end
* which uses this data structure, applying the transformation for each found match to the
* target process.
*
* For more details on what was matched, and log output when each hooked method is actually used,
* enable DEBUG_MODE in config.js, and watch the Frida output after running this script.
*
*************************************************************************************************/
function buildX509CertificateFromBytes(certBytes) {
const ByteArrayInputStream = Java.use('java.io.ByteArrayInputStream');
const CertFactory = Java.use('java.security.cert.CertificateFactory');
+4 -2
View File
@@ -1,4 +1,5 @@
/**
/**************************************************************************************************
*
* The first step in intercepting HTTP & HTTPS traffic is to set the default proxy settings,
* telling the app that all requests should be sent via our HTTP proxy.
*
@@ -11,7 +12,8 @@
* with a framework that does not do this by default (Flutter is notably in this category).
* To handle those less tidy cases, we manually capture traffic to recognized target ports
* in the native connect() hook script.
*/
*
*************************************************************************************************/
Java.perform(() => {
// Set default JVM system properties for the proxy address. Notably these are used
@@ -1,4 +1,5 @@
/**
/**************************************************************************************************
*
* Once we have captured traffic (once it's being sent to our proxy port) the next step is
* to ensure any clients using TLS (HTTPS) trust our CA certificate, to allow us to intercept
* encrypted connections successfully.
@@ -11,7 +12,8 @@
* This does not handle all standalone certificate pinning techniques - where the application
* actively rejects certificates that are trusted by default on the system. That's dealt with
* in the separate certificate unpinning script.
*/
*
*************************************************************************************************/
Java.perform(() => {
// First, we build a JVM representation of our certificate:
+8
View File
@@ -1,3 +1,11 @@
/******************************************************************************
*
* This file defines various config parameters, used later within the other
* scripts. In all cases, you'll want to set CERT_PEM and likely
* PROXY_HOST and PROXY_PORT.
*
*****************************************************************************/
// Local testing certificate for now
const CERT_PEM = `-----BEGIN CERTIFICATE-----
MIIDTzCCAjegAwIBAgIRClDpdJeylUmDvNyq5qq+plcwDQYJKoZIhvcNAQELBQAw