介于黄河科技学院开发的app,翻转校园app的逆向分析,Frida hook JAVA层
这个APP用的阿里OSS,腾讯浏览器框架,
- 先抓包,,我们会发现直接抓包抓不到,这里我用Frida hook该app的ssl
- Frida Hook ssl代码:
# -*- coding: UTF-8 -*- import frida, sys jscode = """ //Hook SLL检测 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') } }); """ def on_message(message, data): if message['type'] == 'send': print("[*] {0}".format(message['payload'])) else: print(message) pass # 查找USB设备并附加到目标进程 session = frida.get_usb_device(1000).attach('翻转校园') # 在目标进程里创建脚本 script = session.create_script(jscode) # 注册消息回调 script.on('message', on_message) print('[*] Start attach') # 加载创建好的javascript脚本 script.load() # 读取系统输入 sys.stdin.read()
Hook完ssl后就可以正常抓包了
- 分析参数
device 00000000-6fd2-5a75-ffff-ffffca01fdf4 password vv7F7Mzn9YGUElFoJCfN4Q== random F0A28BBDE391B7F0A6BEA2F09D999EE5BCA3 login_type password key 118342203120011
发现device应该是本地生成的,password是加密过的,random 和cookie里的PHPSESSID 都是第一个请求连接返回的值 ,key是账号
- 今天主要目的是解决登录,实现登录功能就行,接下来进入分析app环节
分析APP:
- 先查壳,将App拖入到PKiD
- 查询发现是 普通的360壳
- 我用的是Youpk脱壳,如果手下没Google pixel 的话 可以用xposed的模块脱壳,或者其他第三方工具脱壳(我已将脱完壳未修复放到蓝奏云里,需要可下载)
- 将脱壳后的app拖入到Jadx里面,搜索Url关键词,或者是Url的请求名称,
- 这里我搜索”sso.schoopia.com/login” ,,进入这个登录代码
-
ResponseLogin responseLogin = (ResponseLogin) JsonProvider.parseJson(HttpProvider.postMessageWithSendStatus("https://sso.schoopia.com/login", requestLogin.requestLoginArgs(), getSessionValue()), ResponseLogin.class);
请求的参数在这里 requestLoginArgs(),按着Ctrl鼠标点击跟踪到定义处插图005 这里面是将本地的password传到map里面然后返回map的,所以我们要看看本地的password是在哪被赋值的
- 鼠标右键查看用例,发现只有一处调用,跟过去看看
- 发现关键词encrypt加密方法,传的值是咱们输入的密码和第一处请求的时候返回的Random, 跟进去看看encrypt的定义
- 发现是个修改过的md5 外加AES加密,,
-
package edu.hhstu.hhstutalent.provider; import android.util.Base64; import android.util.Log; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; public class AesEncryption { private static AesEncryption sInstance = null; private static String value = ".youcai.diot"; public static AesEncryption getInstance() { if (sInstance == null) { sInstance = new AesEncryption(); } return sInstance; } public String encrypt(String str, String str2) { String stringToMD5 = stringToMD5(str2 + value); Log.i("MD5 ", stringToMD5); try { Cipher instance = Cipher.getInstance("AES/ECB/PKCS7Padding"); instance.init(1, new SecretKeySpec(stringToMD5.getBytes(), "AES")); return Base64.encodeToString(instance.doFinal(str.getBytes()), 0); } catch (Exception e) { e.printStackTrace(); return null; } } public String decrypt(String str, String str2) { String stringToMD5 = stringToMD5(str2 + value); Log.i("MD5 ", stringToMD5); try { byte[] decode = Base64.decode(str.getBytes(), 0); Cipher instance = Cipher.getInstance("AES/ECB/PKCS7Padding"); instance.init(2, new SecretKeySpec(stringToMD5.getBytes(), "AES")); return new String(instance.doFinal(decode), "UTF-8"); } catch (Exception e) { e.printStackTrace(); return null; } } public String stringToMD5(String str) { try { byte[] digest = MessageDigest.getInstance("MD5").digest(str.getBytes("UTF-8")); StringBuilder sb = new StringBuilder(digest.length * 2); for (byte b : digest) { int i = b & 255; if (i < 16) { sb.append("0"); } sb.append(Integer.toHexString(i)); } return sb.toString().substring(8, 24); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } catch (UnsupportedEncodingException e2) { e2.printStackTrace(); return null; } } public String stringToMD5WithKey(String str) { try { byte[] digest = MessageDigest.getInstance("MD5").digest((str + value).getBytes("UTF-8")); StringBuilder sb = new StringBuilder(digest.length * 2); for (byte b : digest) { int i = b & 255; if (i < 16) { sb.append("0"); } sb.append(Integer.toHexString(i)); } return sb.toString().substring(8, 24); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } catch (UnsupportedEncodingException e2) { e2.printStackTrace(); return null; } } }
stringToMD5(String str) 本身是个md5方法,但是return的时候 裁剪了一下 return sb.toString().substring(8, 24); ,取了 8-24位置之间的字符串
- 用Frida hook一下 看看是不是这个位置,
- 该处Frida 代码
-
Java.perform(function () { var AesEncryption = Java.use('edu.hhstu.hhstutalent.provider.AesEncryption'); AesEncryption.encrypt.implementation = function (arg1, arg2) { console.log("AES密码加密"); send("arg1 "+arg1); send("arg2 "+arg2); var a=this.encrypt(arg1, arg2); send("返回值 "+a); return a; } AesEncryption.decrypt.implementation = function (arg1, arg2) { console.log("AES 解密"); send("arg1 "+arg1); send("arg2 "+arg2); var a=this.decrypt(arg1, arg2); send("返回值 "+a); return a; } AesEncryption.stringToMD5.implementation = function (arg1) { console.log("md5加密 stringToMD5"); send("arg1 "+arg1); var a=this.stringToMD5(arg1); send("返回值 "+a); return a; } AesEncryption.stringToMD5WithKey.implementation = function (arg1) { console.log("md5加密 stringToMD5WithKey"); send("arg1 "+arg1); var a=this.stringToMD5WithKey(arg1); send("返回值 "+a); return a; } });
重启软件,attach Frida,
- 点击登录 我输入的账号密码是
118342203129999 blog.lzonel.cn
- frida hook到了,,位置确实是这里,,先是md5加密,,然后又AES加密
- md5加密
- E8B5B3F0A49D90E282AEEC8A9EF0A5B89AE0AC9A.youcai.diot Random+App里面的key
- md5(E8B5B3F0A49D90E282AEEC8A9EF0A5B89AE0AC9A.youcai.diot) 返回 2621dce3a543cd85cb0433bb9659c420
- (2621dce3a543cd85cb0433bb9659c420).substring(8, 24) 取第8位至24位之间字符串 返回 a543cd85cb0433bb
AES加密 需要md5加密后的值当做key ECB模式, PKCS7Padding填充 加密也就这了,纯Java层,
Device Java层生成方法与找密码加密方法相同
public static String getSerial(Context context) { return new UUID((long) ("LT" + Build.BOARD + Build.BRAND + Build.DEVICE + Build.MANUFACTURER + Build.PRODUCT).hashCode(), (long) "serial".hashCode()).toString(); }
总体Frida Hook代码
# -*- coding: UTF-8 -*- import frida, sys jscode = """ Java.perform(function () { var AesEncryption = Java.use('edu.hhstu.hhstutalent.provider.AesEncryption'); AesEncryption.encrypt.implementation = function (arg1, arg2) { console.log("AES密码加密"); send("arg1 "+arg1); send("arg2 "+arg2); var a=this.encrypt(arg1, arg2); send("返回值 "+a); return a; } AesEncryption.decrypt.implementation = function (arg1, arg2) { console.log("AES 解密"); send("arg1 "+arg1); send("arg2 "+arg2); var a=this.decrypt(arg1, arg2); send("返回值 "+a); return a; } AesEncryption.stringToMD5.implementation = function (arg1) { console.log("md5加密 stringToMD5"); send("arg1 "+arg1); var a=this.stringToMD5(arg1); send("返回值 "+a); return a; } AesEncryption.stringToMD5WithKey.implementation = function (arg1) { console.log("md5加密 stringToMD5WithKey"); send("arg1 "+arg1); var a=this.stringToMD5WithKey(arg1); send("返回值 "+a); return a; } }); //Hook SLL检测 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') } }); """ def on_message(message, data): if message['type'] == 'send': print("[*] {0}".format(message['payload'])) else: print(message) pass # 查找USB设备并附加到目标进程 session = frida.get_usb_device(1000).attach('翻转校园') # 在目标进程里创建脚本 script = session.create_script(jscode) # 注册消息回调 script.on('message', on_message) print('[*] Start attach') # 加载创建好的javascript脚本 script.load() # 读取系统输入 sys.stdin.read()
评论抢沙发