Compare commits
3 Commits
358c51a054
...
deb6e8fb4c
| Author | SHA1 | Date |
|---|---|---|
|
|
deb6e8fb4c | |
|
|
fc56cd8c54 | |
|
|
7dc4eb24fd |
|
|
@ -1,101 +1,118 @@
|
||||||
console.log("Script loaded successfully");
|
console.log("Script loaded successfully");
|
||||||
|
// hook_okhttp_client()
|
||||||
if (Java.available) {
|
if (Java.available) {
|
||||||
Java.perform(function () {
|
Java.perform(function() {
|
||||||
console.log("start hook java.net.URL");
|
try {
|
||||||
get_request_info()
|
var OkHttpClient = Java.use("okhttp3.OkHttpClient");
|
||||||
var URL = Java.use('java.net.URL');
|
console.log("OkHttp detected in the app");
|
||||||
URL.$init.overload('java.lang.String').implementation = function (spec) {
|
} catch (e) {
|
||||||
if (spec.includes("appsflyer")) {
|
console.log("OkHttp not detected in the app");
|
||||||
console.log("URL request: " + spec);
|
|
||||||
if (spec.includes("conversions")){
|
|
||||||
// check_conversion_loaded()
|
|
||||||
var stackTrace = Java.use('java.lang.Exception').$new().getStackTrace().toString();
|
|
||||||
console.log(stackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.$init(spec);
|
|
||||||
};
|
|
||||||
// JSONObject.$init.overload('java.lang.String').implementation = function (jsonString) {
|
|
||||||
// var result = this.$init.overload('java.lang.String').call(this, jsonString);
|
|
||||||
// if (typeof result.toString !== "undefined") {
|
|
||||||
// console.log("result: " + result.toString())
|
|
||||||
// var msgData = jsonString.toString();
|
|
||||||
//
|
|
||||||
// if (msgData.contains("install_time") &&
|
|
||||||
// (msgData.contains("af_siteid") || msgData.contains("af_channel") ||
|
|
||||||
// msgData.contains("af_status") || msgData.contains("af_message")) &&
|
|
||||||
// (!msgData.contains("is_first_launch"))) {
|
|
||||||
// console.log("msgdata: " + msgData)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return result;
|
|
||||||
// };
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function check_conversion_loaded() {
|
|
||||||
Java.perform(function() {
|
|
||||||
var found = false;
|
|
||||||
Java.enumerateLoadedClasses({
|
|
||||||
onMatch: function(className) {
|
|
||||||
if (className.includes("AppsFlyer2dXConversionCallback")) {
|
|
||||||
console.log("Found: " + className);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onComplete: function() {
|
|
||||||
if (!found) {
|
|
||||||
console.log("AppsFlyer2dXConversionCallback class not loaded.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
Java.perform(function () {
|
||||||
|
console.log("start hook java.net.URL");
|
||||||
}
|
var URL = Java.use('java.net.URL');
|
||||||
|
URL.$init.overload('java.lang.String').implementation = function (spec) {
|
||||||
function get_request_info() {
|
if (spec.includes("appsflyer")) {
|
||||||
console.log("start running get_request_info")
|
console.log("URL request: " + spec);
|
||||||
var HttpURLConnection = Java.use('java.net.HttpURLConnection');
|
if (spec.includes("conversions")) {
|
||||||
var ByteArrayOutputStream = Java.use('java.io.ByteArrayOutputStream');
|
var stackTrace = Java.use('java.lang.Exception').$new().getStackTrace().toString();
|
||||||
console.log(HttpURLConnection,ByteArrayOutputStream)
|
console.log(stackTrace);
|
||||||
printMethods('java.net.HttpURLConnection');
|
}
|
||||||
printMethods('java.io.ByteArrayOutputStream');
|
}
|
||||||
HttpURLConnection.getRequestMethod.implementation = function () {
|
return this.$init(spec);
|
||||||
var url = this.getURL().toString();
|
};
|
||||||
var method = this.getRequestMethod();
|
});
|
||||||
console.log("URL: " + url + " | Request Method: " + method);
|
|
||||||
return method;
|
|
||||||
};
|
|
||||||
HttpURLConnection.setRequestProperty.implementation = function (key, value) {
|
|
||||||
if (this.getURL().toString().includes("conversions")){
|
|
||||||
console.log("Header: " + key + ": " + value);
|
|
||||||
}
|
|
||||||
return this.setRequestProperty(key, value);
|
|
||||||
};
|
|
||||||
HttpURLConnection.getOutputStream.implementation = function() {
|
|
||||||
var outputStream = this.getOutputStream();
|
|
||||||
var byteArrayOutputStream = ByteArrayOutputStream.$new();
|
|
||||||
var bytes = Java.array('byte', [1024]);
|
|
||||||
var len;
|
|
||||||
while ((len = outputStream.read(bytes)) != -1) {
|
|
||||||
byteArrayOutputStream.write(bytes, 0, len);
|
|
||||||
}
|
|
||||||
var requestBody = byteArrayOutputStream.toString();
|
|
||||||
if (this.getURL().toString().includes("conversions")) {
|
|
||||||
console.log("Request Body: " + requestBody);
|
|
||||||
}
|
|
||||||
return outputStream;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function printMethods(className) {
|
function printMethods(className) {
|
||||||
var jclass = Java.use(className);
|
var jclass = Java.use(className);
|
||||||
var methods = jclass.class.getDeclaredMethods();
|
var methods = jclass.class.getDeclaredMethods();
|
||||||
console.log("Printing methods of " + className + ":\n");
|
console.log("Printing methods of " + className + ":\n");
|
||||||
methods.forEach(function(method) {
|
methods.forEach(function (method) {
|
||||||
console.log(method);
|
console.log(method);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hook_okhttp_client() {
|
||||||
|
if (Java.available) {
|
||||||
|
Java.perform(function () {
|
||||||
|
try {
|
||||||
|
var OkHttpClient = Java.use("okhttp3.OkHttpClient");
|
||||||
|
|
||||||
|
OkHttpClient.newCall.overload('okhttp3.Request').implementation = function (request) {
|
||||||
|
console.log("OkHttp Request URL: " + request.url().toString());
|
||||||
|
console.log("OkHttp Request Headers: " + request.headers().toString());
|
||||||
|
|
||||||
|
if (request.method() == "POST") {
|
||||||
|
console.log("OkHttp Request Body: " + request.body().contentType().toString());
|
||||||
|
// Here you can further extract the request body if needed.
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = this.newCall(request).execute();
|
||||||
|
console.log("OkHttp Response: " + response.body().string());
|
||||||
|
|
||||||
|
// Note: Calling response.body().string() consumes the response body.
|
||||||
|
// You might need to recreate the response if the app expects to read it again.
|
||||||
|
|
||||||
|
return this.newCall(request);
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Error hooking OkHttp: " + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hook_HttpURLConnection_stream() {
|
||||||
|
console.log("start hook_HttpURLConnection_stream")
|
||||||
|
if (Java.available) {
|
||||||
|
Java.perform(function () {
|
||||||
|
var HttpURLConnection = Java.use("java.net.HttpURLConnection");
|
||||||
|
|
||||||
|
HttpURLConnection.getOutputStream.implementation = function () {
|
||||||
|
var outputStream = this.getOutputStream();
|
||||||
|
var OutputStreamWrapper = Java.use("java.io.OutputStream");
|
||||||
|
|
||||||
|
var newOutputStream = Java.registerClass({
|
||||||
|
name: "CustomOutputStream",
|
||||||
|
superClass: OutputStreamWrapper,
|
||||||
|
methods: {
|
||||||
|
write: function (buffer, byteOffset, byteCount) {
|
||||||
|
var data = Array.prototype.slice.call(buffer.slice(byteOffset, byteOffset + byteCount));
|
||||||
|
console.log("Request data: " + String.fromCharCode.apply(null, data));
|
||||||
|
outputStream.write(buffer, byteOffset, byteCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newOutputStream.$new(outputStream);
|
||||||
|
};
|
||||||
|
|
||||||
|
HttpURLConnection.getInputStream.implementation = function () {
|
||||||
|
var inputStream = this.getInputStream();
|
||||||
|
var InputStreamWrapper = Java.use("java.io.InputStream");
|
||||||
|
|
||||||
|
var newInputStream = Java.registerClass({
|
||||||
|
name: "CustomInputStream",
|
||||||
|
superClass: InputStreamWrapper,
|
||||||
|
methods: {
|
||||||
|
read: function (buffer, byteOffset, byteCount) {
|
||||||
|
var bytesRead = inputStream.read(buffer, byteOffset, byteCount);
|
||||||
|
if (bytesRead != -1) {
|
||||||
|
var data = Array.prototype.slice.call(buffer.slice(byteOffset, byteOffset + bytesRead));
|
||||||
|
console.log("Response data: " + String.fromCharCode.apply(null, data));
|
||||||
|
}
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newInputStream.$new(inputStream);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,366 @@
|
||||||
|
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使用.
|
||||||
|
/*
|
||||||
|
06-07 16:15:38.541 27021-27073/mi.sslpinningdemo W/System.err: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
|
||||||
|
06-07 16:15:38.542 27021-27073/mi.sslpinningdemo W/System.err: at android.net.http.X509TrustManagerExtensions.<init>(X509TrustManagerExtensions.java:73)
|
||||||
|
at mi.ssl.MiPinningTrustManger.<init>(MiPinningTrustManger.java:61)
|
||||||
|
06-07 16:15:38.543 27021-27073/mi.sslpinningdemo W/System.err: at mi.sslpinningdemo.OkHttpUtil.getSecPinningClient(OkHttpUtil.java:112)
|
||||||
|
at mi.sslpinningdemo.OkHttpUtil.get(OkHttpUtil.java:62)
|
||||||
|
at mi.sslpinningdemo.MainActivity$1$1.run(MainActivity.java:36)
|
||||||
|
*/
|
||||||
|
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#471
|
||||||
|
// 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#L650
|
||||||
|
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#enablePublicKeyPinningBypassForLocalTrustAnchors(boolean)
|
||||||
|
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')
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue