diff --git a/android-proxy-override.js b/android-proxy-override.js index 26af81c..ebba9eb 100644 --- a/android-proxy-override.js +++ b/android-proxy-override.js @@ -1,16 +1,28 @@ -// Default emulator address for now: -const PROXY_HOST = '192.168.104.248'; -const PROXY_PORT = 8000; +/** + * 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. + * + * In this script, we set that up via a few different mechanisms, which cumulatively should + * ensure that all connections are sent via the proxy, even if they attempt to use their + * own custom proxy configurations to avoid this. + * + * Despite that, this still only covers well behaved apps - it's still possible for apps + * to send network traffic directly if they're determined to do so, or if they're built + * 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. + */ setTimeout(() => { Java.perform(() => { + // Set default JVM system properties for the proxy address: Java.use('java.lang.System').setProperty('http.proxyHost', PROXY_HOST); Java.use('java.lang.System').setProperty('http.proxyPort', PROXY_PORT.toString()); Java.use('java.lang.System').setProperty('https.proxyHost', PROXY_HOST); Java.use('java.lang.System').setProperty('https.proxyPort', PROXY_PORT.toString()); + // Configure the proxy indirectly, by overriding the return value for all ProxySelectors everywhere: const Collections = Java.use('java.util.Collections'); - const ArrayList = Java.use('java.util.ArrayList'); const ProxyType = Java.use('java.net.Proxy$Type'); const InetSocketAddress = Java.use('java.net.InetSocketAddress'); const ProxyCls = Java.use('java.net.Proxy'); // 'Proxy' is reserved in JS diff --git a/android-system-certificate-injection.js b/android-system-certificate-injection.js index fa15d3e..4b5ed77 100644 --- a/android-system-certificate-injection.js +++ b/android-system-certificate-injection.js @@ -1,23 +1,17 @@ -const CERT_PEM = `-----BEGIN CERTIFICATE----- -MIIDTzCCAjegAwIBAgIRClDpdJeylUmDvNyq5qq+plcwDQYJKoZIhvcNAQELBQAw -QTEYMBYGA1UEAxMPSFRUUCBUb29sa2l0IENBMQswCQYDVQQGEwJYWDEYMBYGA1UE -ChMPSFRUUCBUb29sa2l0IENBMB4XDTIyMTIyNTE5MDQ1MFoXDTIzMTIyNjE5MDQ1 -MFowQTEYMBYGA1UEAxMPSFRUUCBUb29sa2l0IENBMQswCQYDVQQGEwJYWDEYMBYG -A1UEChMPSFRUUCBUb29sa2l0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAz4pwm0pLDvf8qVmAiOi2cvu8xDgboetoLWBoONOY2wvoEFRylLUGaieP -UG5Yuofcj798uYPEqPLoF2ugnw8J/lhYhkMqTEbuqoyZT7DooBiqtSbm4b++T/Zt -F6YnpkYeWIkv88UJaRvLG8OHytVbiC71JQ/DFCEjzNzATCKT7UFqyF4ZsT3cnGJe -3x1iiSzWxJsnDkNZmiQ+IDYSM/dx7RJYwrXO5oWbAHC7otdC66O9eB1uBYq9I8gU -4FcVKHbWAH1BYbsoF/pQJLz2mAXD7E92/Vvho7FgTKYOUq0b58LF9UHt+gDRUGUC -L4HtuMeb/Ckiwyoej50jqI//ER1XswIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBxjAdBgNVHQ4EFgQUfsk69D2mzcAFjDX0GV53o3gySMMw -DQYJKoZIhvcNAQELBQADggEBAH08sPexRXFxzuIVWD1aUoarYq8FwNBP+xusgZcg -DmRKr0FpEyUjBxgVIsmd44WSX/TWdXokdd7aLPVnjwQbq2mhYtXAn4aIRn3QBNaj -TvFQovVy+LCSRwZjvlpr/KJnXlVMrqLIxP++I6FqLO5G5zJ+qDF39C7RUkkMpvmU -tiS70/zpt2LSfLUNtnS287P9s4wXEwbrkOOY6oNgKDz7jtNua0ZiPq2uGdqrkyZ2 -VPgirbNnuoC1uZmuy0Mvih4+8xrvJWHb9QO7JOH3cXA+ZiZ945V+viMEnV0YkQB6 -FL11l3fE9xzkPv357Z3e7QULnC8vDRgFAossuh8WBhNjjmo= ------END CERTIFICATE-----`; +/** + * 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. + * + * This script does so by attaching to the internals of Conscrypt (the Android SDK's standard + * TLS implementation) and pre-adding our certificate to the 'already trusted' cache, so that + * future connections trust it implicitly. This ensures that all normal uses of Android APIs + * for HTTPS & TLS will allow interception. + * + * 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: @@ -55,5 +49,5 @@ Java.perform(() => { // pinning too! It auto-trusts us in any implementation that uses TrustManagerImpl (Conscrypt) as // the underlying cert checking component. - console.log('Inject system certificate trust'); + console.log('System certificate trust injected'); }); \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..a787638 --- /dev/null +++ b/config.js @@ -0,0 +1,25 @@ +// Local testing certificate for now +const CERT_PEM = `-----BEGIN CERTIFICATE----- +MIIDTzCCAjegAwIBAgIRClDpdJeylUmDvNyq5qq+plcwDQYJKoZIhvcNAQELBQAw +QTEYMBYGA1UEAxMPSFRUUCBUb29sa2l0IENBMQswCQYDVQQGEwJYWDEYMBYGA1UE +ChMPSFRUUCBUb29sa2l0IENBMB4XDTIyMTIyNTE5MDQ1MFoXDTIzMTIyNjE5MDQ1 +MFowQTEYMBYGA1UEAxMPSFRUUCBUb29sa2l0IENBMQswCQYDVQQGEwJYWDEYMBYG +A1UEChMPSFRUUCBUb29sa2l0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAz4pwm0pLDvf8qVmAiOi2cvu8xDgboetoLWBoONOY2wvoEFRylLUGaieP +UG5Yuofcj798uYPEqPLoF2ugnw8J/lhYhkMqTEbuqoyZT7DooBiqtSbm4b++T/Zt +F6YnpkYeWIkv88UJaRvLG8OHytVbiC71JQ/DFCEjzNzATCKT7UFqyF4ZsT3cnGJe +3x1iiSzWxJsnDkNZmiQ+IDYSM/dx7RJYwrXO5oWbAHC7otdC66O9eB1uBYq9I8gU +4FcVKHbWAH1BYbsoF/pQJLz2mAXD7E92/Vvho7FgTKYOUq0b58LF9UHt+gDRUGUC +L4HtuMeb/Ckiwyoej50jqI//ER1XswIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBxjAdBgNVHQ4EFgQUfsk69D2mzcAFjDX0GV53o3gySMMw +DQYJKoZIhvcNAQELBQADggEBAH08sPexRXFxzuIVWD1aUoarYq8FwNBP+xusgZcg +DmRKr0FpEyUjBxgVIsmd44WSX/TWdXokdd7aLPVnjwQbq2mhYtXAn4aIRn3QBNaj +TvFQovVy+LCSRwZjvlpr/KJnXlVMrqLIxP++I6FqLO5G5zJ+qDF39C7RUkkMpvmU +tiS70/zpt2LSfLUNtnS287P9s4wXEwbrkOOY6oNgKDz7jtNua0ZiPq2uGdqrkyZ2 +VPgirbNnuoC1uZmuy0Mvih4+8xrvJWHb9QO7JOH3cXA+ZiZ945V+viMEnV0YkQB6 +FL11l3fE9xzkPv357Z3e7QULnC8vDRgFAossuh8WBhNjjmo= +-----END CERTIFICATE-----`; + +// Default emulator address for now: +const PROXY_HOST = '127.0.0.1'; +const PROXY_PORT = 8000; \ No newline at end of file diff --git a/native-hook.js b/native-hook.js index 676e642..cfa482e 100644 --- a/native-hook.js +++ b/native-hook.js @@ -12,9 +12,6 @@ * to do proxy config alongside this, primarily to capture traffic that might be sent on any non-standard ports. */ -const PROXY_PORT = 8000; -const PROXY_HOST = '127.0.0.1'; - // Ports which we recognize, and forcibly redirect to capture, if not captured already. const RECOGNIZED_PORTS = [ 80,