有了上一篇JustTrustMe源码解读作铺垫,下面我讲解用frida实现JustTrustMe就很容易了。但是还是有些难点,比如JustTrustMe中有一些自定义的类和方法。那到底如何用frida的方式来实现自定义的类和方法?
自定义类虽然在frida语法中可以用registerClass的方式实现,但是由于类太复杂。我们可以把实现好的java代码打包成dex然后inject到目标进程中再跑hook脚本。
梳理JustTrustMe Main.java 中内部类有如下3个:
同学们要对技术要有自己的判断力,虽然frida有registerClass让你用js语法定义一个类这样的功能。但是,这只是frida的附属价值。你看到这样的技术,了解一下就得了。不用学它,浪费精力!frida的openClassFile摆在那里让你可以注入dex,你居然还用registerClass。那你跟放弃用计算器,手动算数有什么区别?有什么本质的提高吗?并没有,还JB浪费时间。别人在进步,你在原地踏步! IDA和GDB都说自己反汇编,哪个更好你没点B数吗? Java和C++都说自己是面向对象,面向对象封装性哪个更好你没点B数吗?
除了以上3个类,JustTrustMe还有几个静态方法需要我们实现。可以说上面几个类,最终都是通过这几个方法使用的。比如getSCCM()、getEmptySSLFactory()、getCCM()等 我们还是用Java直接实现,那么这些方法。
关于怎么打包涉及到一些技术细节,暂时不便透露。感兴趣的朋友可以去https://github.com/CreditTone/hooker看我的radar.dex 里面有所有打包好的代码。
现在JustTrustMe除hook逻辑之外的所有自定义类和方法我们现在全部搞定了。我们可以正式开始用frida来实现JustTrustMe所有hook点了。
我们还是按上一篇《实现frida版的JustTrustMe(一)JustTrustMe官方源码学习》的源码解读顺序来逐一实现。为了让大家更容易理解,我不贴JustTrustMe的代码了。我贴每个hook点的伪代码,然后跟上frida的实现。这样大家会理解的清晰一点。
上节分析:三个构造方法的目的都是在new DefaultHttpClient之后替换connManager参数。而getSCCM()方法就是返回一个不安全的ClientConnectionManager。
上节分析:X509TrustManagerExtensions原方法会进行一系列的效应证书和服务器是否可信。这里xposed用了XC_MethodReplacement直接替换方法的执行体。
上节分析:原NetworkSecurityTrustManager类的checkPins方法List参数原型是List<X509Certificate>。校验X509Certificate集合是否合法,如果不合法就会抛CertificateException。这里xposed用了XC_MethodReplacement直接替换方法的执行体,并且什么都没做。
上节分析:这个稍微有点复杂,但目的很简单。就是为了替换TrustManager,而TrustManager不可以直接传进来,是内部创建一个sslcontext来包装一个TrustManager[]。所以要new一个自定义的sslcontext然后把ImSureItsLegitTrustManager传进去。sslcontext对象要进行init()所以整个代码看起来比较多。
分析:逻辑过于简单,不解释了
上节分析:强制让isSecure返回true
上节分析: 如果存在com.android.org.conscrypt.TrustManagerImpl这个类的,并且返回的TrustManager[]的长度大于0,并且TrustManager[]第0个是com.android.org.conscrypt.TrustManagerImpl实例,则什么都不操作。否则直接把返回值改成TrustManager[]{new ImSureItsLegitTrustManager()}
上节分析:让setDefaultHostnameVerifier方法失效,让setSSLSocketFactory失效,让setHostnameVerifier失效
上节分析:不用第0和低2个参数,而第1个参数使用TrustManager[]{new ImSureItsLegitTrustManager()}
上节分析:由于xposed基于zygote进程孵化app进程,hook非常早。所以如果它想对应用层的类进行hook的话,必须等Application的attach调用之后才能拿到应用级的ClassLoader。那么在attach之后他又进行了processOkHttp、processHttpClientAndroidLib、processXutils方法的调用,分别对应okhttp库的hook、httpclientandroidlib库的hook、org.xutils.http的hook。这三个是应用喜欢用的三方http库。
上节分析okhttp包名不统一问题:由于okhttp 2.x和3.x包名相差比较大。所以这里第一个hook你可以看到justTrustMe试图去找com.squareup.okhttp.CertificatePinner类,这是为了尽量兼容老安卓项目。
上节分析CertificatePinner.check:无论是okhttp2.x还是3.x、4.x都是有CertificatePinner.check(String str, List<Certificate> list)这个方法的。可以上面第一二个hook做的是XC_MethodReplacement,并且什么都不操作。对比原check方法,我们知道这个目的是为了阻止check抛SSLPeerUnverifiedException异常。
上节分析:第三四个hook OkHostnameVerifier.verify(),校验hostname是否合法最终会调用verify(str, (X509Certificate) sSLSession.getPeerCertificates()[0]);说明还是对远程服务证书进行了校验,这里直接用return true替代了原来的逻辑。
上节分析:一个冷门http库的hook
上节分析:一个冷门http库的hook
到此为止,JustTrustMe所有的hook点除了webviewclient之外全部用frida实现了。我们merge一下。
JustTrustMe的官方源码hook点虽然全部实现,但是由于Android一直在更新和app的混淆不断变强使得我们hook点经常hook不到。那么下一篇我们就来看看如何添加这些新的hook点和对抗混淆frida版本的JustTrustMe
public DefaultHttpClient(final ClientConnectionManager conman, final HttpParams params) {
super
(getCCM(conman, params), params);
}
public DefaultHttpClient(final HttpParams params) {
super
(getSCCM(), params);
}
public DefaultHttpClient() {
super
(getSCCM(), null);
}
public DefaultHttpClient(final ClientConnectionManager conman, final HttpParams params) {
super
(getCCM(conman, params), params);
}
public DefaultHttpClient(final HttpParams params) {
super
(getSCCM(), params);
}
public DefaultHttpClient() {
super
(getSCCM(), null);
}
Java.perform(function() {
var Helper
=
Java.use(
"gz.justtrustme.Helper"
);
var DefaultHttpClientClass
=
Java.use(
"org.apache.http.impl.client.DefaultHttpClient"
);
/
/
被强奸的构造方法
var DefaultHttpClientClassRapeConstructor
=
DefaultHttpClientClass.$init.overload(
'org.apache.http.conn.ClientConnectionManager'
,
'org.apache.http.params.HttpParams'
);
DefaultHttpClientClassRapeConstructor.implementation
=
function(v0, v1) {
/
/
被强奸的构造方法被调用的话,我们替换调ClientConnectionManager参数为我们的
var returnObj
=
DefaultHttpClientClassRapeConstructor.call(this, Helper.getCCM(v0, v1), v1);
console.log(
"org.apache.http.impl.client.DefaultHttpClient.$init('org.apache.http.conn.ClientConnectionManager', 'org.apache.http.params.HttpParams') was hooked!"
);
return
returnObj;
};
var DefaultHttpClientClassInit_1602
=
DefaultHttpClientClass.$init.overload();
DefaultHttpClientClassInit_1602.implementation
=
function() {
/
/
使用DefaultHttpClientClassRapeConstructor强奸它
var returnObj
=
DefaultHttpClientClassRapeConstructor.call(this, Helper.getSCCM(), null);
console.log(
"org.apache.http.impl.client.DefaultHttpClient.$init() was hooked!"
);
return
returnObj;
};
var DefaultHttpClientClassInit_1603
=
DefaultHttpClientClass.$init.overload(
'org.apache.http.params.HttpParams'
);
DefaultHttpClientClassInit_1603.implementation
=
function(v0) {
/
/
使用DefaultHttpClientClassRapeConstructor强奸它
var returnObj
=
DefaultHttpClientClassRapeConstructor.call(this, Helper.getSCCM(), v0);
console.log(
"org.apache.http.impl.client.DefaultHttpClient.$init('org.apache.http.params.HttpParams') was hooked!"
);
return
returnObj;
};
/
/
以上DefaultHttpClient的三个构造方法逻辑全部被我们用frida的方式替换了
}
Java.perform(function() {
var Helper
=
Java.use(
"gz.justtrustme.Helper"
);
var DefaultHttpClientClass
=
Java.use(
"org.apache.http.impl.client.DefaultHttpClient"
);
/
/
被强奸的构造方法
var DefaultHttpClientClassRapeConstructor
=
DefaultHttpClientClass.$init.overload(
'org.apache.http.conn.ClientConnectionManager'
,
'org.apache.http.params.HttpParams'
);
DefaultHttpClientClassRapeConstructor.implementation
=
function(v0, v1) {
/
/
被强奸的构造方法被调用的话,我们替换调ClientConnectionManager参数为我们的
var returnObj
=
DefaultHttpClientClassRapeConstructor.call(this, Helper.getCCM(v0, v1), v1);
console.log(
"org.apache.http.impl.client.DefaultHttpClient.$init('org.apache.http.conn.ClientConnectionManager', 'org.apache.http.params.HttpParams') was hooked!"
);
return
returnObj;
};
var DefaultHttpClientClassInit_1602
=
DefaultHttpClientClass.$init.overload();
DefaultHttpClientClassInit_1602.implementation
=
function() {
/
/
使用DefaultHttpClientClassRapeConstructor强奸它
var returnObj
=
DefaultHttpClientClassRapeConstructor.call(this, Helper.getSCCM(), null);
console.log(
"org.apache.http.impl.client.DefaultHttpClient.$init() was hooked!"
);
return
returnObj;
};
var DefaultHttpClientClassInit_1603
=
DefaultHttpClientClass.$init.overload(
'org.apache.http.params.HttpParams'
);
DefaultHttpClientClassInit_1603.implementation
=
function(v0) {
/
/
使用DefaultHttpClientClassRapeConstructor强奸它
var returnObj
=
DefaultHttpClientClassRapeConstructor.call(this, Helper.getSCCM(), v0);
console.log(
"org.apache.http.impl.client.DefaultHttpClient.$init('org.apache.http.params.HttpParams') was hooked!"
);
return
returnObj;
};
/
/
以上DefaultHttpClient的三个构造方法逻辑全部被我们用frida的方式替换了
}
public
List
<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType, String host) throws CertificateException {
return
chain;
}
public
List
<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType, String host) throws CertificateException {
return
chain;
}
Java.perform(function() {
var X509TrustManagerExtensionsClass
=
Java.use(
'android.net.http.X509TrustManagerExtensions'
);
var X509TrustManagerExtensionsClassCheckServerTrusted
=
X509TrustManagerExtensionsClass.checkServerTrusted.overload(
'[Ljava.security.cert.X509Certificate;'
,
'java.lang.String'
,
'java.lang.String'
);
X509TrustManagerExtensionsClassCheckServerTrusted.implementation
=
function(certsArr, v1, v2) {
console.log(
"android.net.http.X509TrustManagerExtensions.checkServerTrusted('[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'java.lang.String') was hooked!"
);
return
certsArr;
};
}
Java.perform(function() {
var X509TrustManagerExtensionsClass
=
Java.use(
'android.net.http.X509TrustManagerExtensions'
);
var X509TrustManagerExtensionsClassCheckServerTrusted
=
X509TrustManagerExtensionsClass.checkServerTrusted.overload(
'[Ljava.security.cert.X509Certificate;'
,
'java.lang.String'
,
'java.lang.String'
);
X509TrustManagerExtensionsClassCheckServerTrusted.implementation
=
function(certsArr, v1, v2) {
console.log(
"android.net.http.X509TrustManagerExtensions.checkServerTrusted('[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'java.lang.String') was hooked!"
);
return
certsArr;
};
}
private void checkPins(
List
<X509Certificate> chain) throws CertificateException {
/
/
什么都不做
}
private void checkPins(
List
<X509Certificate> chain) throws CertificateException {
/
/
什么都不做
}
Java.perform(function() {
var NetworkSecurityTrustManagerClass
=
Java.use(
'android.security.net.config.NetworkSecurityTrustManager'
);
var NetworkSecurityTrustManagerClassCheckPins
=
NetworkSecurityTrustManagerClass.checkPins.overload(
'java.util.List'
);
NetworkSecurityTrustManagerClassCheckPins.implementation
=
function(v0) {
/
/
什么都不做
console.log(
"android.security.net.config.NetworkSecurityTrustManager.checkPins('java.util.List') was hooked!"
);
};
}
Java.perform(function() {
var NetworkSecurityTrustManagerClass
=
Java.use(
'android.security.net.config.NetworkSecurityTrustManager'
);
var NetworkSecurityTrustManagerClassCheckPins
=
NetworkSecurityTrustManagerClass.checkPins.overload(
'java.util.List'
);
NetworkSecurityTrustManagerClassCheckPins.implementation
=
function(v0) {
/
/
什么都不做
console.log(
"android.security.net.config.NetworkSecurityTrustManager.checkPins('java.util.List') was hooked!"
);
};
}
public SSLSocketFactory(
String algorithm,
final KeyStore keystore,
final String keystorePassword,
final KeyStore truststore,
final SecureRandom random,
final HostNameResolver nameResolver)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
{
super
();
if
(algorithm
=
=
null) {
algorithm
=
TLS;
}
KeyManager[] keymanagers
=
null;
if
(keystore !
=
null) {
keymanagers
=
createKeyManagers(keystore, keystorePassword);
}
TrustManager[] trustmanagers
=
new TrustManager[]{new ImSureItsLegitTrustManager()};;
/
/
这里被替换了,就这么简单
this.sslcontext
=
SSLContext.getInstance(algorithm);
this.sslcontext.init(keymanagers, trustmanagers, random);
this.socketfactory
=
this.sslcontext.getSocketFactory();
this.nameResolver
=
nameResolver;
}
public SSLSocketFactory(
String algorithm,
final KeyStore keystore,
final String keystorePassword,
final KeyStore truststore,
final SecureRandom random,
final HostNameResolver nameResolver)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
{
super
();
if
(algorithm
=
=
null) {
algorithm
=
TLS;
}
KeyManager[] keymanagers
=
null;
if
(keystore !
=
null) {
keymanagers
=
createKeyManagers(keystore, keystorePassword);
}
TrustManager[] trustmanagers
=
new TrustManager[]{new ImSureItsLegitTrustManager()};;
/
/
这里被替换了,就这么简单
this.sslcontext
=
SSLContext.getInstance(algorithm);
this.sslcontext.init(keymanagers, trustmanagers, random);
this.socketfactory
=
this.sslcontext.getSocketFactory();
this.nameResolver
=
nameResolver;
}
Java.perform(function() {
var Helper
=
Java.use(
"gz.justtrustme.Helper"
);
/
/
替换trustmanagers参数
var SSLSocketFactory
=
Java.use(
'org.apache.http.conn.ssl.SSLSocketFactory'
);
var SSLSocketFactoryRapeConstructor
=
SSLSocketFactory.$init.overload(
'java.lang.String'
,
'java.security.KeyStore'
,
'java.lang.String'
,
'java.security.KeyStore'
,
'java.security.SecureRandom'
,
'org.apache.http.conn.scheme.HostNameResolver'
);
SSLSocketFactoryRapeConstructor.implementation
=
function(v0, v1, v2, v3, v4, v5) {
var returnObj
=
SSLSocketFactoryRapeConstructor.call(this, v0, v1, v2, v3, v4, v5);
console.log(
"org.apache.http.conn.ssl.SSLSocketFactory.$init('java.lang.String', 'java.security.KeyStore', 'java.lang.String', 'java.security.KeyStore', 'java.security.SecureRandom', 'org.apache.http.conn.scheme.HostNameResolver') was hooked!"
);
if
(Helper.reInitSSLSocketFactory(returnObj, v0, v1, v2, v3, v4, v5)) {
console.log(
"替换trustmanagers参数成功!"
);
}
else
{
console.log(
"替换trustmanagers参数失败!"
);
}
return
returnObj;
};
}
Java.perform(function() {
var Helper
=
Java.use(
"gz.justtrustme.Helper"
);
/
/
替换trustmanagers参数
var SSLSocketFactory
=
Java.use(
'org.apache.http.conn.ssl.SSLSocketFactory'
);
var SSLSocketFactoryRapeConstructor
=
SSLSocketFactory.$init.overload(
'java.lang.String'
,
'java.security.KeyStore'
,
'java.lang.String'
,
'java.security.KeyStore'
,
'java.security.SecureRandom'
,
'org.apache.http.conn.scheme.HostNameResolver'
);
SSLSocketFactoryRapeConstructor.implementation
=
function(v0, v1, v2, v3, v4, v5) {
var returnObj
=
SSLSocketFactoryRapeConstructor.call(this, v0, v1, v2, v3, v4, v5);
console.log(
"org.apache.http.conn.ssl.SSLSocketFactory.$init('java.lang.String', 'java.security.KeyStore', 'java.lang.String', 'java.security.KeyStore', 'java.security.SecureRandom', 'org.apache.http.conn.scheme.HostNameResolver') was hooked!"
);
if
(Helper.reInitSSLSocketFactory(returnObj, v0, v1, v2, v3, v4, v5)) {
console.log(
"替换trustmanagers参数成功!"
);
}
else
{
console.log(
"替换trustmanagers参数失败!"
);
}
return
returnObj;
};
}
public static SSLSocketFactory getSocketFactory() {
/
/
return
NoPreloadHolder.DEFAULT_FACTORY;
return
new SSLSocketFactory();
}
public static SSLSocketFactory getSocketFactory() {
/
/
return
NoPreloadHolder.DEFAULT_FACTORY;
return
new SSLSocketFactory();
}
Java.perform(function() {
var SSLSocketFactory
=
Java.use(
'org.apache.http.conn.ssl.SSLSocketFactory'
);
var SSLSocketFactoryGetSocketFactoryMethod
=
SSLSocketFactory.getSocketFactory.overload();
var SSLSocketFactoryEmptyConstructor
=
SSLSocketFactory.$init.overload();
SSLSocketFactoryGetSocketFactoryMethod.implementation
=
function() {
/
/
强制用空的构造方法
console.log(
"org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory() was hooked!"
);
return
SSLSocketFactoryEmptyConstructor.call(this);
};
}
Java.perform(function() {
var SSLSocketFactory
=
Java.use(
'org.apache.http.conn.ssl.SSLSocketFactory'
);
var SSLSocketFactoryGetSocketFactoryMethod
=
SSLSocketFactory.getSocketFactory.overload();
var SSLSocketFactoryEmptyConstructor
=
SSLSocketFactory.$init.overload();
SSLSocketFactoryGetSocketFactoryMethod.implementation
=
function() {
/
/
强制用空的构造方法
console.log(
"org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory() was hooked!"
);
return
SSLSocketFactoryEmptyConstructor.call(this);
};
}
public boolean isSecure(Socket sock)
throws IllegalArgumentException {
return
true;
}
public boolean isSecure(Socket sock)
throws IllegalArgumentException {
return
true;
}
Java.perform(function() {
var SSLSocketFactory
=
Java.use(
'org.apache.http.conn.ssl.SSLSocketFactory'
);
var SSLSocketFactoryIsSecure
=
SSLSocketFactory.isSecure.overload(
'java.net.Socket'
);
SSLSocketFactoryIsSecure.implementation
=
function(v0) {
/
/
强制返回true
console.log(
"org.apache.http.conn.ssl.SSLSocketFactory.isSecure('java.net.Socket') was hooked!"
);
return
true;
};
}
Java.perform(function() {
var SSLSocketFactory
=
Java.use(
'org.apache.http.conn.ssl.SSLSocketFactory'
);
var SSLSocketFactoryIsSecure
=
SSLSocketFactory.isSecure.overload(
'java.net.Socket'
);
SSLSocketFactoryIsSecure.implementation
=
function(v0) {
/
/
强制返回true
console.log(
"org.apache.http.conn.ssl.SSLSocketFactory.isSecure('java.net.Socket') was hooked!"
);
return
true;
};
}
public final TrustManager[] getTrustManagers() {
TrustManager[] originResult
=
factorySpi.engineGetTrustManagers();
/
/
原代码是直接
return
factorySpi.engineGetTrustManagers()
if
(hasTrustManagerImpl()) {
Class<?>
cls
=
Class.
from
(
"com.android.org.conscrypt.TrustManagerImpl"
);
if
(originResult.length >
0
&&
cls
.
isInstance
(originResult[
0
])) {
return
originResult;
}
}
return
new TrustManager[]{new ImSureItsLegitTrustManager()};
}
public final TrustManager[] getTrustManagers() {
TrustManager[] originResult
=
factorySpi.engineGetTrustManagers();
/
/
原代码是直接
return
factorySpi.engineGetTrustManagers()
if
(hasTrustManagerImpl()) {
Class<?>
cls
=
Class.
from
(
"com.android.org.conscrypt.TrustManagerImpl"
);
if
(originResult.length >
0
&&
cls
.
isInstance
(originResult[
0
])) {
return
originResult;
}
}
return
new TrustManager[]{new ImSureItsLegitTrustManager()};
}
Java.perform(function() {
var Helper
=
Java.use(
"gz.justtrustme.Helper"
);
var TrustManagerFactory
=
Java.use(
'javax.net.ssl.TrustManagerFactory'
);
var TrustManagerFactoryGetTrustManagers
=
TrustManagerFactory.getTrustManagers.overload();
TrustManagerFactoryGetTrustManagers.implementation
=
function() {
var ret
=
TrustManagerFactoryGetTrustManagers.call(this);
/
/
替换getTrustManagers方法逻辑
console.log(
"javax.net.ssl.TrustManagerFactory.getTrustManagers() was hooked!"
);
return
Helper.replaceGetTrustManagers(this, ret);
};
}
Java.perform(function() {
var Helper
=
Java.use(
"gz.justtrustme.Helper"
);
var TrustManagerFactory
=
Java.use(
'javax.net.ssl.TrustManagerFactory'
);
var TrustManagerFactoryGetTrustManagers
=
TrustManagerFactory.getTrustManagers.overload();
TrustManagerFactoryGetTrustManagers.implementation
=
function() {
var ret
=
TrustManagerFactoryGetTrustManagers.call(this);
/
/
替换getTrustManagers方法逻辑
console.log(
"javax.net.ssl.TrustManagerFactory.getTrustManagers() was hooked!"
);
return
Helper.replaceGetTrustManagers(this, ret);
};
}
public static void setDefaultHostnameVerifier(HostnameVerifier v) {
/
/
啥都不干
}
public void setSSLSocketFactory(SSLSocketFactory sf) {
/
/
啥都不干
}
public static void setDefaultHostnameVerifier(HostnameVerifier v) {
/
/
啥都不干
}
public static void setDefaultHostnameVerifier(HostnameVerifier v) {
/
/
啥都不干
}
public void setSSLSocketFactory(SSLSocketFactory sf) {
/
/
啥都不干
}
public static void setDefaultHostnameVerifier(HostnameVerifier v) {
/
/
啥都不干
}
Java.perform(function() {
var HttpsURLConnection
=
Java.use(
"javax.net.ssl.HttpsURLConnection"
);
var HttpsURLConnectionSetDefaultHostnameVerifier
=
HttpsURLConnection.setDefaultHostnameVerifier.overload(
'javax.net.ssl.HostnameVerifier'
);
HttpsURLConnectionSetDefaultHostnameVerifier.implementation
=
function(v0) {
/
/
什么都不做
console.log(
"javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier('javax.net.ssl.HostnameVerifier') was hooked!"
);
};
var HttpsURLConnectionSetHostnameVerifier
=
HttpsURLConnection.setHostnameVerifier.overload(
'javax.net.ssl.HostnameVerifier'
);
HttpsURLConnectionSetHostnameVerifier.implementation
=
function(v0) {
/
/
什么都不做
console.log(
"javax.net.ssl.HttpsURLConnection.setHostnameVerifier('javax.net.ssl.HostnameVerifier') was hooked!"
);
};
var HttpsURLConnectionSetSSLSocketFactory
=
HttpsURLConnection.setSSLSocketFactory.overload(
'javax.net.ssl.SSLSocketFactory'
);
HttpsURLConnectionSetSSLSocketFactory.implementation
=
function(v0) {
/
/
什么都不做
console.log(
"javax.net.ssl.SSLSocketFactory.setSSLSocketFactory('javax.net.ssl.SSLSocketFactory') was hooked!"
);
};
}
Java.perform(function() {
var HttpsURLConnection
=
Java.use(
"javax.net.ssl.HttpsURLConnection"
);
var HttpsURLConnectionSetDefaultHostnameVerifier
=
HttpsURLConnection.setDefaultHostnameVerifier.overload(
'javax.net.ssl.HostnameVerifier'
);
HttpsURLConnectionSetDefaultHostnameVerifier.implementation
=
function(v0) {
/
/
什么都不做
console.log(
"javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier('javax.net.ssl.HostnameVerifier') was hooked!"
);
};
var HttpsURLConnectionSetHostnameVerifier
=
HttpsURLConnection.setHostnameVerifier.overload(
'javax.net.ssl.HostnameVerifier'
);
HttpsURLConnectionSetHostnameVerifier.implementation
=
function(v0) {
/
/
什么都不做
console.log(
"javax.net.ssl.HttpsURLConnection.setHostnameVerifier('javax.net.ssl.HostnameVerifier') was hooked!"
);
};
var HttpsURLConnectionSetSSLSocketFactory
=
HttpsURLConnection.setSSLSocketFactory.overload(
'javax.net.ssl.SSLSocketFactory'
);
HttpsURLConnectionSetSSLSocketFactory.implementation
=
function(v0) {
/
/
什么都不做
console.log(
"javax.net.ssl.SSLSocketFactory.setSSLSocketFactory('javax.net.ssl.SSLSocketFactory') was hooked!"
);
};
}
public final void init(KeyManager[] km, TrustManager[] tm,
SecureRandom random)
throws KeyManagementException {
tm
=
new TrustManager[]{new ImSureItsLegitTrustManager()};
contextSpi.engineInit(null, tm, null);
}
public final void init(KeyManager[] km, TrustManager[] tm,
SecureRandom random)
throws KeyManagementException {
tm
=
new TrustManager[]{new ImSureItsLegitTrustManager()};
contextSpi.engineInit(null, tm, null);
}
Java.perform(function() {
var SSLContextClz
=
Java.use(
'javax.net.ssl.SSLContext'
);
var SSLContextClzInit
=
SSLContextClz.init.overload(
'[Ljavax.net.ssl.KeyManager;'
,
'[Ljavax.net.ssl.TrustManager;'
,
'java.security.SecureRandom'
);
SSLContextClzInit.implementation
=
function(v0, v1, v2) {
/
/
将第二个参数强制替换为我们自己构造的不安全的TrustManagers
SSLContextClzInit.call(this, v0, Helper.getImSureTrustManagers(), v2);
console.log(
"javax.net.ssl.SSLContext.init('[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom') was hooked!"
);
};
}
Java.perform(function() {
var SSLContextClz
=
Java.use(
'javax.net.ssl.SSLContext'
);
var SSLContextClzInit
=
SSLContextClz.init.overload(
'[Ljavax.net.ssl.KeyManager;'
,
'[Ljavax.net.ssl.TrustManager;'
,
'java.security.SecureRandom'
);
SSLContextClzInit.implementation
=
function(v0, v1, v2) {
/
/
将第二个参数强制替换为我们自己构造的不安全的TrustManagers
SSLContextClzInit.call(this, v0, Helper.getImSureTrustManagers(), v2);
console.log(
"javax.net.ssl.SSLContext.init('[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom') was hooked!"
);
};
}
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk
=
ContextImpl.getImpl(context).mPackageInfo;
ClassLoader appClassLoader
=
context.getClassLoader();
processOkHttp(appClassLoader);
processHttpClientAndroidLib(appClassLoader);
processXutils(appClassLoader);
}
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk
=
ContextImpl.getImpl(context).mPackageInfo;
ClassLoader appClassLoader
=
context.getClassLoader();
processOkHttp(appClassLoader);
processHttpClientAndroidLib(appClassLoader);
processXutils(appClassLoader);
}
Java.perform(function() {
var ApplicationClz
=
Java.use(
'android.app.Application'
);
var ApplicationClzAttach
=
ApplicationClz.attach.overload(
'android.content.Context'
);
ApplicationClzAttach.implementation
=
function(context) {
ApplicationClzAttach.call(this, context);
/
/
注意justTrustMe使用的是afterHookedMethod,所以我们用frida也必须在原方法call完之后执行我们的代码
var classLoader
=
context.getClassLoader();
};
}
Java.perform(function() {
var ApplicationClz
=
Java.use(
'android.app.Application'
);
var ApplicationClzAttach
=
ApplicationClz.attach.overload(
'android.content.Context'
);
ApplicationClzAttach.implementation
=
function(context) {
ApplicationClzAttach.call(this, context);
/
/
注意justTrustMe使用的是afterHookedMethod,所以我们用frida也必须在原方法call完之后执行我们的代码
var classLoader
=
context.getClassLoader();
};
}
public void check(String
str
,
List
<Certificate>
list
) {
/
/
原代码校验失败会throw new throw new SSLPeerUnverifiedException(sb.toString());
/
/
hook之后相当于什么都不操作
}
public void check(String
str
,
List
<Certificate>
list
) {
/
/
原代码校验失败会throw new throw new SSLPeerUnverifiedException(sb.toString());
/
/
hook之后相当于什么都不操作
}
public boolean verify(String
str
, SSLSession sSLSession) {
return
true;
}
public boolean verify(String
str
, X509Certificate x509Certificate) {
return
true;
}
public boolean verify(String
str
, SSLSession sSLSession) {
return
true;
}
public boolean verify(String
str
, X509Certificate x509Certificate) {
return
true;
}
function processOkHttp() {
/
/
知道你为什么有时候用JustTrustMe失败吗,因为app代码混淆了下面这些类你改到对应的类和方法就行啦
if
(classExists(
"com.squareup.okhttp.CertificatePinner"
)) {
var squareupOkhttp3CertificatePinnerClz
=
Java.use(
'com.squareup.okhttp.CertificatePinner'
);
var squareupOkhttp3CertificatePinnerClzCheck
=
squareupOkhttp3CertificatePinnerClz.check.overload(
'java.lang.String'
,
'java.util.List'
);
squareupOkhttp3CertificatePinnerClzCheck.implementation
=
function(v0, v1) {
/
/
什么都不做
console.log(
"com.squareup.okhttp.CertificatePinner.check('java.lang.String', 'java.util.List') was hooked!"
);
};
}
else
{
console.error(
"没找到com.squareup.okhttp.CertificatePinner类,这是android系统自带的类没找到就算求了。不同系统不一样,不用找了!!!"
);
}
if
(classExists(
"okhttp3.CertificatePinner"
)) {
try
{
var okhttp3CertificatePinnerClz
=
Java.use(
'okhttp3.CertificatePinner'
);
var okhttp3CertificatePinnerClzCheck
=
okhttp3CertificatePinnerClz.check.overload(
'java.lang.String'
,
'java.util.List'
);
okhttp3CertificatePinnerClzCheck.implementation
=
function(v0, v1) {
/
/
什么都不做
console.log(
"okhttp3.CertificatePinner.check('java.lang.String', 'java.util.List') was hooked!"
);
};
} catch (error) {
console.error(
"okhttp3.CertificatePinner的check方法可能被混淆了。你可以jadx反编译下还原回来!"
);
}
}
else
{
console.error(
"没找到okhttp3.CertificatePinner类,可能被混淆了。你可以jadx反编译下还原回来!"
);
}
if
(classExists(
"okhttp3.internal.tls.OkHostnameVerifier"
)) {
try
{
var OkHostnameVerifierClz
=
Java.use(
'okhttp3.internal.tls.OkHostnameVerifier'
);
var OkHostnameVerifierClzVerify_5791
=
OkHostnameVerifierClz.verify.overload(
'java.lang.String'
,
'javax.net.ssl.SSLSession'
);
OkHostnameVerifierClzVerify_5791.implementation
=
function(v0, v1) {
/
/
强制返回true
console.log(
"okhttp3.internal.tls.OkHostnameVerifier.verify('java.lang.String', 'javax.net.ssl.SSLSession') was hooked!"
);
return
true;
};
var OkHostnameVerifierVerify_8978
=
OkHostnameVerifierClz.verify.overload(
'java.lang.String'
,
'java.security.cert.X509Certificate'
);
OkHostnameVerifierVerify_8978.implementation
=
function(v0, v1) {
/
/
强制返回true
console.log(
"okhttp3.internal.tls.OkHostnameVerifier.verify('java.lang.String', 'java.security.cert.X509Certificate') was hooked!"
);
return
true;
};
} catch (error) {
console.error(
"okhttp3.internal.tls.OkHostnameVerifier的verify方法可能被混淆了。你可以jadx反编译下还原回来!"
);
}
}
else
{
console.error(
"没找到okhttp3.internal.tls.OkHostnameVerifier类,可能被混淆了。你可以jadx反编译下还原回来!"
);
}
}
function processOkHttp() {
/
/
知道你为什么有时候用JustTrustMe失败吗,因为app代码混淆了下面这些类你改到对应的类和方法就行啦
if
(classExists(
"com.squareup.okhttp.CertificatePinner"
)) {
var squareupOkhttp3CertificatePinnerClz
=
Java.use(
'com.squareup.okhttp.CertificatePinner'
);
var squareupOkhttp3CertificatePinnerClzCheck
=
squareupOkhttp3CertificatePinnerClz.check.overload(
'java.lang.String'
,
'java.util.List'
);
squareupOkhttp3CertificatePinnerClzCheck.implementation
=
function(v0, v1) {
/
/
什么都不做
console.log(
"com.squareup.okhttp.CertificatePinner.check('java.lang.String', 'java.util.List') was hooked!"
);
};
}
else
{
console.error(
"没找到com.squareup.okhttp.CertificatePinner类,这是android系统自带的类没找到就算求了。不同系统不一样,不用找了!!!"
);
}
if
(classExists(
"okhttp3.CertificatePinner"
)) {
try
{
var okhttp3CertificatePinnerClz
=
Java.use(
'okhttp3.CertificatePinner'
);
var okhttp3CertificatePinnerClzCheck
=
okhttp3CertificatePinnerClz.check.overload(
'java.lang.String'
,
'java.util.List'
);
okhttp3CertificatePinnerClzCheck.implementation
=
function(v0, v1) {
/
/
什么都不做
console.log(
"okhttp3.CertificatePinner.check('java.lang.String', 'java.util.List') was hooked!"
);
};
} catch (error) {
console.error(
"okhttp3.CertificatePinner的check方法可能被混淆了。你可以jadx反编译下还原回来!"
);
}
}
else
{
console.error(
"没找到okhttp3.CertificatePinner类,可能被混淆了。你可以jadx反编译下还原回来!"
);
}
if
(classExists(
"okhttp3.internal.tls.OkHostnameVerifier"
)) {
try
{
var OkHostnameVerifierClz
=
Java.use(
'okhttp3.internal.tls.OkHostnameVerifier'
);
var OkHostnameVerifierClzVerify_5791
=
OkHostnameVerifierClz.verify.overload(
'java.lang.String'
,
'javax.net.ssl.SSLSession'
);
OkHostnameVerifierClzVerify_5791.implementation
=
function(v0, v1) {
/
/
强制返回true
console.log(
"okhttp3.internal.tls.OkHostnameVerifier.verify('java.lang.String', 'javax.net.ssl.SSLSession') was hooked!"
);
return
true;
};
var OkHostnameVerifierVerify_8978
=
OkHostnameVerifierClz.verify.overload(
'java.lang.String'
,
'java.security.cert.X509Certificate'
);
OkHostnameVerifierVerify_8978.implementation
=
function(v0, v1) {
/
/
强制返回true
console.log(
"okhttp3.internal.tls.OkHostnameVerifier.verify('java.lang.String', 'java.security.cert.X509Certificate') was hooked!"
);
return
true;
};
} catch (error) {
console.error(
"okhttp3.internal.tls.OkHostnameVerifier的verify方法可能被混淆了。你可以jadx反编译下还原回来!"
);
}
}
else
{
console.error(
"没找到okhttp3.internal.tls.OkHostnameVerifier类,可能被混淆了。你可以jadx反编译下还原回来!"
);
}
}
public final void verify(String arg1, String[] arg2, boolean arg3){
/
/
什么都不做
}
public final void verify(String arg1, String[] arg2, boolean arg3){
/
/
什么都不做
}
function processHttpClientAndroidLib() {
if
(classExists(
"ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier"
)) {
var AbstractVerifierClass
=
Java.use(
"ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier"
);
var OkHostnameVerifierClzVerify_5791
=
AbstractVerifierClass.verify.overload(
'java.lang.String'
,
'[Ljava.lang.String;'
,
'[Ljava.lang.String;'
,
'boolean'
);
OkHostnameVerifierClzVerify_5791.implementation
=
function(v0, v1, v2, v3) {
/
/
什么都不做
console.log(
"ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier.verify('java.lang.String', '[Ljava.lang.String;', '[Ljava.lang.String;', 'boolean') was hooked!"
);
};
}
else
{
console.error(
"没找到ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier类,但是这个类用的少。不用找了!"
);
}
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-5-7 10:54
被爬虫不看学历编辑
,原因: