I wrote a simple apk myself with a button that sends a request when pressed, this apk uses certificate verification, I tried to bypass it with hook, but it didn't work.
The following is part of the code for apk certificate verification.
X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// Certificate returned by the server
X509Certificate cf = chain[0];
RSAPublicKey pubkey = (RSAPublicKey) cf.getPublicKey();
String encoded = Base64.encodeToString(pubkey.getEncoded(), 0);
Log.e("Certificate returned by the server:", encoded);
// Reads the client's default certificate
InputStream client_input = getResources().openRawResource(R.raw.baidu);
CertificateFactory finalcf = CertificateFactory.getInstance("X.509");
X509Certificate realCertificate = (X509Certificate) finalcf.generateCertificate(client_input);
String realPubKey = Base64.encodeToString(realCertificate.getPublicKey().getEncoded(), 0);
Log.e("client's default certificate:", realPubKey);
cf.checkValidity();
final boolean expected = realPubKey.equalsIgnoreCase(encoded);
Log.e("Call stack", Log.getStackTraceString(new Throwable()));
if (!expected) {
throw new CertificateException("Certificate inconsistency");
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
SSLSocketFactory factory = null;
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
factory = sslContext.getSocketFactory();
} catch (Exception e) {
}
I output the call stack below when i press the button.
at com.nb.netdemo3.MainActivity$2.checkServerTrusted(MainActivity.java:77)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:254)
at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1644)
at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(Native Method)
at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:568)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:849)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access$100(ConscryptEngineSocket.java:722)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:238)
at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:217)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:336)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:300)
And i want to hook this function com.android.org.conscrypt.Platform.checkServerTrusted
,here is the
hook code
Java.perform(function () {
var Platform = Java.use('com.android.org.conscrypt.Platform');
Platform.checkServerTrusted.overload('javax.net.ssl.X509TrustManager', '[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'com.android.org.conscrypt.AbstractConscryptSocket').implementation = function (x509tm, chain, authType, socket) {
console.log('\n[+] checkServer ', x509tm, JSON.stringify(x509tm));
//return this.checkServerTrusted(x509tm, chain, authType, socket);
};
});
I used frida to hook, and when I hooked, when I pressed the button to send the request, there was no console.log
.
The version of frida is 16.0.1,my android version is 11,python version is 3.7.9.
I want to know why I can't hook this function called com.android.org.conscrypt.Platform.checkServerTrusted
Your hooking code is correct, but it just hooks the wrong overloaded version of
checkServerTrusted
, therefore you don't get an error but your code inside the hook is never executed:The class
com.android.org.conscrypt.Platform
contains two public implementations ofcheckServerTrusted
:checkServerTrusted(X509TrustManager, X509Certificate[], String, AbstractConscryptSocket)
checkServerTrusted(X509TrustManager, X509Certificate[], String, ConscryptEngine)
You have hooked the first version, but looking at the code in com.android.org.conscrypt.ConscryptEngine where checkServerTrusted is called (see your stack trace) you will see that the last argument is a
this
thus the second version is called where the last argument type iscom.android.org.conscrypt.ConscryptEngine
.So f you your hooking code to the following script it should work.
Note that the linked source code references do not belong to the Android version of your device, therefore the line numbers don't match and it would be possible that in your older version the code is different.
If you want to get the exact code that is executed on your device you would have to extract the Android Framework libraries from your device and decompile them (not sure which files you would have to extract from
/system/framework
to get the conscrypt byte code).