我自己写了一个简单的apk,有一个按钮,按下时会发送请求,这个apk使用证书验证,我尝试用hook绕过它,但没有成功。
以下是apk证书验证的部分代码。
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) {
}
当我按下按钮时,我输出下面的调用堆栈。
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)
我想挂钩这个功能
com.android.org.conscrypt.Platform.checkServerTrusted
,这是
挂钩代码
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);
};
});
我用frida来hook,当我hook时,当我按下发送请求的按钮时,没有
console.log
。
frida的版本是16.0.1,我的android版本是11,python版本是3.7.9。
我想知道为什么我无法挂接这个名为
com.android.org.conscrypt.Platform.checkServerTrusted
的函数
您的挂钩代码是正确的,但它只是挂钩了错误的重载版本
checkServerTrusted
,因此您不会收到错误,但挂钩内的代码永远不会执行:
类
com.android.org.conscrypt.Platform
包含 checkServerTrusted
的两个公共实现:
checkServerTrusted(X509TrustManager, X509Certificate[], String, AbstractConscryptSocket)
checkServerTrusted(X509TrustManager, X509Certificate[], String, ConscryptEngine)
您已经挂钩了第一个版本,但是查看 com.android.org.conscrypt.ConscryptEngine 中调用 checkServerTrusted 的代码(请参阅堆栈跟踪),您将看到最后一个参数是
this
,因此第二个参数是调用 version 时最后一个参数类型为 com.android.org.conscrypt.ConscryptEngine
。
因此,如果您将代码挂钩到以下脚本,它应该可以工作。
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.ConscryptEngine').implementation = function (x509tm, chain, authType, socket) {
console.log('\n[+] checkServer ', x509tm, JSON.stringify(x509tm));
//return this.checkServerTrusted(x509tm, chain, authType, socket);
};
});
请注意,链接的源代码引用不属于您设备的 Android 版本,因此行号不匹配,并且您的旧版本中的代码可能不同。
如果你想获得在你的设备上执行的确切代码,你必须从你的设备中提取 Android 框架库并反编译它们(不确定你需要从
/system/framework
中提取哪些文件才能获得 conscrypt 字节代码) ).