Java.perform(function() {
/
*
hook
list
:
1.SSLcontext
2.okhttp
3.webview
4.XUtils
5.httpclientandroidlib
6.JSSE
7.network
\_security\_config (android
7.0
+
)
8.Apache
Http client (support partly)
9.OpenSSLSocketImpl
10.TrustKit
11.Cronet
*
/
/
/
Attempts to bypass SSL pinning implementations
in
a number of
/
/
ways. These include implementing a new TrustManager that will
/
/
accept
any
SSL certificate, overriding OkHTTP v3 check()
/
/
method etc.
var X509TrustManager
=
Java.use(
'javax.net.ssl.X509TrustManager'
);
var HostnameVerifier
=
Java.use(
'javax.net.ssl.HostnameVerifier'
);
var SSLContext
=
Java.use(
'javax.net.ssl.SSLContext'
);
var quiet_output
=
false;
/
/
Helper method to honor the quiet flag.
function quiet_send(data) {
if
(quiet_output) {
return
;
}
send(data)
}
/
/
Implement a new TrustManager
/
/
ref: https:
/
/
gist.github.com
/
oleavr
/
3ca67a173ff7d207c6b8c3b0ca65a9d8
/
/
Java.registerClass()
is
only supported on ART
for
now(
201803
). 所以android
4.4
以下不兼容,
4.4
要切换成ART使用.
var X509Certificate
=
Java.use(
"java.security.cert.X509Certificate"
);
var TrustManager;
try
{
TrustManager
=
Java.registerClass({
name:
'org.wooyun.TrustManager'
,
implements: [X509TrustManager],
methods: {
checkClientTrusted: function(chain, authType) {},
checkServerTrusted: function(chain, authType) {},
getAcceptedIssuers: function() {
/
/
var certs
=
[X509Certificate.$new()];
/
/
return
certs;
return
[];
}
}
});
} catch (e) {
quiet_send(
"registerClass from X509TrustManager >>>>>>>> "
+
e.message);
}
/
/
Prepare the TrustManagers array to
pass
to SSLContext.init()
var TrustManagers
=
[TrustManager.$new()];
try
{
/
/
Prepare a Empty SSLFactory
var TLS_SSLContext
=
SSLContext.getInstance(
"TLS"
);
TLS_SSLContext.init(null, TrustManagers, null);
var EmptySSLFactory
=
TLS_SSLContext.getSocketFactory();
} catch (e) {
quiet_send(e.message);
}
send(
'Custom, Empty TrustManager ready'
);
/
/
Get a handle on the init() on the SSLContext
class
var SSLContext_init
=
SSLContext.init.overload(
'[Ljavax.net.ssl.KeyManager;'
,
'[Ljavax.net.ssl.TrustManager;'
,
'java.security.SecureRandom'
);
/
/
Override the init method, specifying our new TrustManager
SSLContext_init.implementation
=
function(keyManager, trustManager, secureRandom) {
quiet_send(
'Overriding SSLContext.init() with the custom TrustManager'
);
SSLContext_init.call(this, null, TrustManagers, null);
};
/
*
*
*
okhttp3.x unpinning
*
*
*
/
/
/
Wrap the logic
in
a
try
/
catch as
not
all
applications will have
/
/
okhttp as part of the app.
try
{
var CertificatePinner
=
Java.use(
'okhttp3.CertificatePinner'
);
quiet_send(
'OkHTTP 3.x Found'
);
CertificatePinner.check.overload(
'java.lang.String'
,
'java.util.List'
).implementation
=
function() {
quiet_send(
'OkHTTP 3.x check() called. Not throwing an exception.'
);
}
} catch (err) {
/
/
If we dont have a ClassNotFoundException exception,
raise
the
/
/
problem encountered.
if
(err.message.indexOf(
'ClassNotFoundException'
)
=
=
=
0
) {
throw new Error(err);
}
}
/
/
Appcelerator Titanium PinningTrustManager
/
/
Wrap the logic
in
a
try
/
catch as
not
all
applications will have
/
/
appcelerator as part of the app.
try
{
var PinningTrustManager
=
Java.use(
'appcelerator.https.PinningTrustManager'
);
send(
'Appcelerator Titanium Found'
);
PinningTrustManager.checkServerTrusted.implementation
=
function() {
quiet_send(
'Appcelerator checkServerTrusted() called. Not throwing an exception.'
);
}
} catch (err) {
/
/
If we dont have a ClassNotFoundException exception,
raise
the
/
/
problem encountered.
if
(err.message.indexOf(
'ClassNotFoundException'
)
=
=
=
0
) {
throw new Error(err);
}
}
/
*
*
*
okhttp unpinning
*
*
*
/
try
{
var OkHttpClient
=
Java.use(
"com.squareup.okhttp.OkHttpClient"
);
OkHttpClient.setCertificatePinner.implementation
=
function(certificatePinner) {
/
/
do nothing
quiet_send(
"OkHttpClient.setCertificatePinner Called!"
);
return
this;
};
/
/
Invalidate the certificate pinnet checks (
if
"setCertificatePinner"
was called before the previous invalidation)
var CertificatePinner
=
Java.use(
"com.squareup.okhttp.CertificatePinner"
);
CertificatePinner.check.overload(
'java.lang.String'
,
'[Ljava.security.cert.Certificate;'
).implementation
=
function(p0, p1) {
/
/
do nothing
quiet_send(
"okhttp Called! [Certificate]"
);
return
;
};
CertificatePinner.check.overload(
'java.lang.String'
,
'java.util.List'
).implementation
=
function(p0, p1) {
/
/
do nothing
quiet_send(
"okhttp Called! [List]"
);
return
;
};
} catch (e) {
quiet_send(
"com.squareup.okhttp not found"
);
}
/
*
*
*
WebView Hooks
*
*
*
/
/
*
frameworks
/
base
/
core
/
java
/
android
/
webkit
/
WebViewClient.java
*
/
/
*
public void onReceivedSslError(Webview, SslErrorHandler, SslError)
*
/
var WebViewClient
=
Java.use(
"android.webkit.WebViewClient"
);
WebViewClient.onReceivedSslError.implementation
=
function(webView, sslErrorHandler, sslError) {
quiet_send(
"WebViewClient onReceivedSslError invoke"
);
/
/
执行proceed方法
sslErrorHandler.proceed();
return
;
};
WebViewClient.onReceivedError.overload(
'android.webkit.WebView'
,
'int'
,
'java.lang.String'
,
'java.lang.String'
).implementation
=
function(a, b, c, d) {
quiet_send(
"WebViewClient onReceivedError invoked"
);
return
;
};
WebViewClient.onReceivedError.overload(
'android.webkit.WebView'
,
'android.webkit.WebResourceRequest'
,
'android.webkit.WebResourceError'
).implementation
=
function() {
quiet_send(
"WebViewClient onReceivedError invoked"
);
return
;
};
/
*
*
*
JSSE Hooks
*
*
*
/
/
*
libcore
/
luni
/
src
/
main
/
java
/
javax
/
net
/
ssl
/
TrustManagerFactory.java
*
/
/
*
public final TrustManager[] getTrustManager()
*
/
/
*
TrustManagerFactory.getTrustManagers maybe cause X509TrustManagerExtensions error
*
/
/
/
var TrustManagerFactory
=
Java.use(
"javax.net.ssl.TrustManagerFactory"
);
/
/
TrustManagerFactory.getTrustManagers.implementation
=
function(){
/
/
quiet_send(
"TrustManagerFactory getTrustManagers invoked"
);
/
/
return
TrustManagers;
/
/
}
var HttpsURLConnection
=
Java.use(
"javax.net.ssl.HttpsURLConnection"
);
/
*
libcore
/
luni
/
src
/
main
/
java
/
javax
/
net
/
ssl
/
HttpsURLConnection.java
*
/
/
*
public void setDefaultHostnameVerifier(HostnameVerifier)
*
/
HttpsURLConnection.setDefaultHostnameVerifier.implementation
=
function(hostnameVerifier) {
quiet_send(
"HttpsURLConnection.setDefaultHostnameVerifier invoked"
);
return
null;
};
/
*
libcore
/
luni
/
src
/
main
/
java
/
javax
/
net
/
ssl
/
HttpsURLConnection.java
*
/
/
*
public void setSSLSocketFactory(SSLSocketFactory)
*
/
HttpsURLConnection.setSSLSocketFactory.implementation
=
function(SSLSocketFactory) {
quiet_send(
"HttpsURLConnection.setSSLSocketFactory invoked"
);
return
null;
};
/
*
libcore
/
luni
/
src
/
main
/
java
/
javax
/
net
/
ssl
/
HttpsURLConnection.java
*
/
/
*
public void setHostnameVerifier(HostnameVerifier)
*
/
HttpsURLConnection.setHostnameVerifier.implementation
=
function(hostnameVerifier) {
quiet_send(
"HttpsURLConnection.setHostnameVerifier invoked"
);
return
null;
};
/
*
*
*
Xutils3.x hooks
*
*
*
/
/
/
Implement a new HostnameVerifier
var TrustHostnameVerifier;
try
{
TrustHostnameVerifier
=
Java.registerClass({
name:
'org.wooyun.TrustHostnameVerifier'
,
implements: [HostnameVerifier],
method: {
verify: function(hostname, session) {
return
true;
}
}
});
} catch (e) {
/
/
java.lang.ClassNotFoundException: Didn't find
class
"org.wooyun.TrustHostnameVerifier"
quiet_send(
"registerClass from hostnameVerifier >>>>>>>> "
+
e.message);
}
try
{
var RequestParams
=
Java.use(
'org.xutils.http.RequestParams'
);
RequestParams.setSslSocketFactory.implementation
=
function(sslSocketFactory) {
sslSocketFactory
=
EmptySSLFactory;
return
null;
}
RequestParams.setHostnameVerifier.implementation
=
function(hostnameVerifier) {
hostnameVerifier
=
TrustHostnameVerifier.$new();
return
null;
}
} catch (e) {
quiet_send(
"Xutils hooks not Found"
);
}
/
*
*
*
httpclientandroidlib Hooks
*
*
*
/
try
{
var AbstractVerifier
=
Java.use(
"ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier"
);
AbstractVerifier.verify.overload(
'java.lang.String'
,
'[Ljava.lang.String'
,
'[Ljava.lang.String'
,
'boolean'
).implementation
=
function() {
quiet_send(
"httpclientandroidlib Hooks"
);
return
null;
}
} catch (e) {
quiet_send(
"httpclientandroidlib Hooks not found"
);
}
/
*
*
*
android
7.0
+
network_security_config TrustManagerImpl hook
apache httpclient partly
*
*
*
/
var TrustManagerImpl
=
Java.use(
"com.android.org.conscrypt.TrustManagerImpl"
);
/
/
try
{
/
/
var Arrays
=
Java.use(
"java.util.Arrays"
);
/
/
/
/
apache http client pinning maybe baypass
/
/
/
/
https:
/
/
github.com
/
google
/
conscrypt
/
blob
/
c88f9f55a523f128f0e4dace76a34724bfa1e88c
/
platform
/
src
/
main
/
java
/
org
/
conscrypt
/
TrustManagerImpl.java
/
/
TrustManagerImpl.checkTrusted.implementation
=
function (chain, authType, session, parameters, authType) {
/
/
quiet_send(
"TrustManagerImpl checkTrusted called"
);
/
/
/
/
Generics currently result
in
java.lang.
Object
/
/
return
Arrays.asList(chain);
/
/
}
/
/
/
/
} catch (e) {
/
/
quiet_send(
"TrustManagerImpl checkTrusted nout found"
);
/
/
}
try
{
/
/
Android
7
+
TrustManagerImpl
TrustManagerImpl.verifyChain.implementation
=
function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
quiet_send(
"TrustManagerImpl verifyChain called"
);
/
/
Skip
all
the logic
and
just
return
the chain again :P
/
/
https:
/
/
www.nccgroup.trust
/
uk
/
about
-
us
/
newsroom
-
and
-
events
/
blogs
/
2017
/
november
/
bypassing
-
androids
-
network
-
security
-
configuration
/
/
/
https:
/
/
github.com
/
google
/
conscrypt
/
blob
/
c88f9f55a523f128f0e4dace76a34724bfa1e88c
/
platform
/
src
/
main
/
java
/
org
/
conscrypt
/
TrustManagerImpl.java
return
untrustedChain;
}
} catch (e) {
quiet_send(
"TrustManagerImpl verifyChain nout found below 7.0"
);
}
/
/
OpenSSLSocketImpl
try
{
var OpenSSLSocketImpl
=
Java.use(
'com.android.org.conscrypt.OpenSSLSocketImpl'
);
OpenSSLSocketImpl.verifyCertificateChain.implementation
=
function(certRefs, authMethod) {
quiet_send(
'OpenSSLSocketImpl.verifyCertificateChain'
);
}
quiet_send(
'OpenSSLSocketImpl pinning'
)
} catch (err) {
quiet_send(
'OpenSSLSocketImpl pinner not found'
);
}
/
/
Trustkit
try
{
var Activity
=
Java.use(
"com.datatheorem.android.trustkit.pinning.OkHostnameVerifier"
);
Activity.verify.overload(
'java.lang.String'
,
'javax.net.ssl.SSLSession'
).implementation
=
function(
str
) {
quiet_send(
'Trustkit.verify1: '
+
str
);
return
true;
};
Activity.verify.overload(
'java.lang.String'
,
'java.security.cert.X509Certificate'
).implementation
=
function(
str
) {
quiet_send(
'Trustkit.verify2: '
+
str
);
return
true;
};
quiet_send(
'Trustkit pinning'
)
} catch (err) {
quiet_send(
'Trustkit pinner not found'
)
}
try
{
/
/
cronet pinner hook
/
/
weibo don't invoke
var netBuilder
=
Java.use(
"org.chromium.net.CronetEngine$Builder"
);
/
/
https:
/
/
developer.android.com
/
guide
/
topics
/
connectivity
/
cronet
/
reference
/
org
/
chromium
/
net
/
CronetEngine.Builder.html
netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.implementation
=
function(arg) {
/
/
weibo
not
invoke
console.log(
"Enables or disables public key pinning bypass for local trust anchors = "
+
arg);
/
/
true to enable the bypass, false to disable.
var ret
=
netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true);
return
ret;
};
netBuilder.addPublicKeyPins.implementation
=
function(hostName, pinsSha256, includeSubdomains, expirationDate) {
console.log(
"cronet addPublicKeyPins hostName = "
+
hostName);
/
/
var ret
=
netBuilder.addPublicKeyPins.call(this,hostName, pinsSha256,includeSubdomains, expirationDate);
/
/
this 是调用 addPublicKeyPins 前的对象吗? Yes,CronetEngine.Builder
return
this;
};
} catch (err) {
console.log(
'[-] Cronet pinner not found'
)
}
});