httptoolkit / frida-interception-and-unpinning

Frida scripts to directly MitM all HTTPS traffic from a target mobile application
https://httptoolkit.com/android/
GNU Affero General Public License v3.0
871 stars 176 forks source link

Error: Address(): argument types do not match #52

Closed 3052 closed 6 months ago

3052 commented 7 months ago

using this command:

> frida -U `
-f com.nbcuni.nbc `
-l android/android-certificate-unpinning.js `
-l config.js

I get this:

     ____
    / _  |   Frida 16.1.4 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Android Emulator 5554 (id=emulator-5554)
Spawning `com.nbcuni.nbc`...

Spawned `com.nbcuni.nbc`. Resuming main thread!
[Android Emulator 5554::com.nbcuni.nbc ]-> == Certificate unpinning completed ==
Error: Address(): argument types do not match any of:
        .overload('java.lang.String', 'int', 'javax.net.SocketFactory', 'javax.net.ssl.SSLSocketFactory', 'javax.net.ssl.HostnameVerifier', 'com.android.okhttp.CertificatePinner', 'com.android.okhttp.Authenticator', 'java.net.Proxy', 'java.util.List', 'java.util.List', 'java.net.ProxySelector')
    at X (frida/node_modules/frida-java-bridge/lib/class-factory.js:569)
    at value (frida/node_modules/frida-java-bridge/lib/class-factory.js:973)
    at e (frida/node_modules/frida-java-bridge/lib/class-factory.js:553)
    at <anonymous> (D:\Desktop\frida-interception-and-unpinning-main\android\android-certificate-unpinning.js:170)
    at apply (native)
    at ne (frida/node_modules/frida-java-bridge/lib/class-factory.js:620)
    at <anonymous> (frida/node_modules/frida-java-bridge/lib/class-factory.js:598)
pimterry commented 7 months ago

config.js needs to come first on the command line, although I don't think that would cause this. It defines various variables that are used in the other scripts.

Can you try setting DEBUG_MODE in config.js to true, and share the output afterwards? That should tell us exactly which hook is failing.

3052 commented 7 months ago

OK this command:

> frida -U `
-f com.nbcuni.nbc `
-l config.js `
-l android/android-certificate-unpinning.js

result:

     ____
    / _  |   Frida 16.1.4 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Android Emulator 5554 (id=emulator-5554)
Spawning `com.nbcuni.nbc`...

*** Starting scripts ***
Spawned `com.nbcuni.nbc`. Resuming main thread!
[Android Emulator 5554::com.nbcuni.nbc ]->
    === Disabling all recognized unpinning libraries ===
[+] javax.net.ssl.HttpsURLConnection setDefaultHostnameVerifier
[+] javax.net.ssl.HttpsURLConnection setSSLSocketFactory
[+] javax.net.ssl.HttpsURLConnection setHostnameVerifier
[+] javax.net.ssl.SSLContext init(KeyManager;[], TrustManager;[], SecureRandom)
[+] com.android.org.conscrypt.CertPinManager isChainValid
[ ] com.android.org.conscrypt.CertPinManager checkChainPinning
[ ] android.security.net.config.NetworkSecurityConfig *
[+] com.android.okhttp.Address $init
[ ] okhttp3.CertificatePinner *
[ ] com.squareup.okhttp.CertificatePinner *
[ ] com.datatheorem.android.trustkit.pinning.PinningTrustManager *
[ ] appcelerator.https.PinningTrustManager *
[ ] nl.xservices.plugins.sslCertificateChecker *
[ ] com.worklight.wlclient.api.WLClient *
[ ] com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning *
[ ] com.worklight.androidgap.plugin.WLCertificatePinningPlugin *
[ ] com.commonsware.cwac.netsecurity.conscrypt.CertPinManager *
[ ] io.netty.handler.ssl.util.FingerprintTrustManagerFactory *
[ ] com.silkimen.cordovahttp.CordovaServerTrust *
[ ] com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyHostnameVerifier *
[ ] com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyInterceptor *
[ ] com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyTrustManager *
== Certificate unpinning completed ==
*** Scripts completed ***

 => com.android.okhttp.Address $init
Error: Address(): argument types do not match any of:
        .overload('java.lang.String', 'int', 'javax.net.SocketFactory', 'javax.net.ssl.SSLSocketFactory', 'javax.net.ssl.HostnameVerifier', 'com.android.okhttp.CertificatePinner', 'com.android.okhttp.Authenticator', 'java.net.Proxy', 'java.util.List', 'java.util.List', 'java.net.ProxySelector')
    at X (frida/node_modules/frida-java-bridge/lib/class-factory.js:622)
    at value (frida/node_modules/frida-java-bridge/lib/class-factory.js:1141)
    at e (frida/node_modules/frida-java-bridge/lib/class-factory.js:606)
    at <anonymous> (D:\Desktop\frida-interception-and-unpinning-main\android\android-certificate-unpinning.js:170)
    at apply (native)
    at <anonymous> (D:\Desktop\frida-interception-and-unpinning-main\android\android-certificate-unpinning.js:435)
    at apply (native)
    at ne (frida/node_modules/frida-java-bridge/lib/class-factory.js:673)
    at <anonymous> (frida/node_modules/frida-java-bridge/lib/class-factory.js:651)
 => com.android.okhttp.Address $init
pimterry commented 6 months ago

Thanks! So that's definitely happening in this hook of the built-in Android Address constructor.

I think this must be within the call to the real $init with replaced arguments, here:

https://github.com/httptoolkit/frida-interception-and-unpinning/blob/05d9b8ab444b81b8fc4fa3101f5ffcfff1c2d38a/android/android-certificate-unpinning.js#L163-L170

This assumes arguments 5 & 6 (zero-indexed) are the hostname verifier and cert pinner. If they're not, the call to $init at the end will fail, because the argument types will be wrong.

Confusingly though, that does seem to be true in the Android source, and there's only one constructor there: https://android.googlesource.com/platform/external/okhttp/+/refs/heads/main/okhttp/src/main/java/com/squareup/okhttp/Address.java#51

What Android version are you running here?

It's possible that in older OS versions, this was different. If so that's not a big problem, we'll just need to work out what differences need handling, and then update this hook to detect that.

3052 commented 6 months ago

This assumes arguments 5 & 6 (zero-indexed) are the hostname verifier and cert pinner. If they're not, the call to $init at the end will fail, because the argument types will be wrong.

OK yes, with Oreo and later, that is the case:

public Address(String uriHost, int uriPort, Dns dns, SocketFactory socketFactory,
SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier,
CertificatePinner certificatePinner, Authenticator authenticator, Proxy proxy,
List<Protocol> protocols, List<ConnectionSpec> connectionSpecs, ProxySelector proxySelector) {

https://android.googlesource.com/platform/external/okhttp/+/refs/heads/oreo-release/okhttp/src/main/java/com/squareup/okhttp/Address.java

but with Nougat and before, the signature is different:

public Address(String uriHost, int uriPort, SocketFactory socketFactory,
SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier,
CertificatePinner certificatePinner, Authenticator authenticator, Proxy proxy,
List<Protocol> protocols, List<ConnectionSpec> connectionSpecs, ProxySelector proxySelector) {

https://android.googlesource.com/platform/external/okhttp/+/refs/heads/nougat-release/okhttp/src/main/java/com/squareup/okhttp/Address.java

however, even if I use Oreo it still doesn't work. I no longer get the Error, but it seems some pinning is still happening, because the app gets stuck on the initial load screen, and works as expected if I disable the proxy.

pimterry commented 6 months ago

Thanks, that's useful confirmation.

I've just pushed a patch for unpinning for Nougat and older - can you check that the address patch now doesn't fail in that case for you? With debug mode enabled it should now show two lines about patching com.android.okhttp.Address, with slightly different signatures, and at least one should be applied (i.e. should show [+]) in all cases.

however, even if I use Oreo it still doesn't work. I no longer get the Error, but it seems some pinning is still happening, because the app gets stuck on the initial load screen, and works as expected if I disable the proxy.

This sounds like a separate problem, unrelated to this address issue. If you can share more info on that (any logs from that case, traces of any errors detected by the fallback script, any other clues as to what's failing) in a new issue that would be helpful.

3052 commented 6 months ago

I've just pushed a patch for unpinning for Nougat and older - can you check that the address patch now doesn't fail in that case for you? With debug mode enabled it should now show two lines about patching com.android.okhttp.Address, with slightly different signatures, and at least one should be applied (i.e. should show [+]) in all cases.

     ____
    / _  |   Frida 16.1.4 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Android Emulator 5554 (id=emulator-5554)
Spawning `com.nbcuni.nbc`...

*** Starting scripts ***
Spawned `com.nbcuni.nbc`. Resuming main thread!
[Android Emulator 5554::com.nbcuni.nbc ]->
    === Disabling all recognized unpinning libraries ===
[+] javax.net.ssl.HttpsURLConnection setDefaultHostnameVerifier
[+] javax.net.ssl.HttpsURLConnection setSSLSocketFactory
[+] javax.net.ssl.HttpsURLConnection setHostnameVerifier
[+] javax.net.ssl.SSLContext init(KeyManager;[], TrustManager;[], SecureRandom)
[+] com.android.org.conscrypt.CertPinManager isChainValid
[ ] com.android.org.conscrypt.CertPinManager checkChainPinning
[+] android.security.net.config.NetworkSecurityConfig $init(*) (0)
[+] android.security.net.config.NetworkSecurityConfig $init(*) (1)
[ ] com.android.okhttp.Address $init(String, int, Dns, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
[+] com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
[ ] okhttp3.CertificatePinner *
[ ] com.squareup.okhttp.CertificatePinner *
[ ] com.datatheorem.android.trustkit.pinning.PinningTrustManager *
[ ] appcelerator.https.PinningTrustManager *
[ ] nl.xservices.plugins.sslCertificateChecker *
[ ] com.worklight.wlclient.api.WLClient *
[ ] com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning *
[ ] com.worklight.androidgap.plugin.WLCertificatePinningPlugin *
[ ] com.commonsware.cwac.netsecurity.conscrypt.CertPinManager *
[ ] io.netty.handler.ssl.util.FingerprintTrustManagerFactory *
[ ] com.silkimen.cordovahttp.CordovaServerTrust *
[ ] com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyHostnameVerifier *
[ ] com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyInterceptor *
[ ] com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyTrustManager *
== Certificate unpinning completed ==
*** Scripts completed ***

 => android.security.net.config.NetworkSecurityConfig $init(*) (1)
 => android.security.net.config.NetworkSecurityConfig $init(*) (0)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => javax.net.ssl.SSLContext init(KeyManager;[], TrustManager;[], SecureRandom)
 => javax.net.ssl.SSLContext init(KeyManager;[], TrustManager;[], SecureRandom)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => javax.net.ssl.HttpsURLConnection setDefaultHostnameVerifier
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => javax.net.ssl.SSLContext init(KeyManager;[], TrustManager;[], SecureRandom)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => javax.net.ssl.SSLContext init(KeyManager;[], TrustManager;[], SecureRandom)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.okhttp.Address $init(String, int, SocketFactory, SSLSocketFactory, HostnameVerifier, CertificatePinner, Authenticator, Proxy, List, List, ProxySelector)
 => com.android.org.conscrypt.CertPinManager isChainValid

This sounds like a separate problem, unrelated to this address issue. If you can share more info on that (any logs from that case, traces of any errors detected by the fallback script, any other clues as to what's failing) in a new issue that would be helpful.

will do

pimterry commented 6 months ago

This address issue is now resolved, so I'll close this, we can handle the rest in the other issues.