[极验SDK]如何绕过在WebView中的SSL校验

一、前言

        之前在破解某个软件中碰到了SSL证书校验的问题,当时的解决方案是搜索TrustManager,SSLContext之类的关键词,模仿JustTrustMe去hook一个加固的APP。


XposedHelpers.findAndHookMethod("javax.net.ssl.SSLContext", classLoader, "init", KeyManager[].class, TrustManager[].class,
                                    SecureRandom.class, new XC_MethodHook() {
                                        @Override
                                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                            super.beforeHookedMethod(param);
                                            param.args[1] = new TrustManager[]{(new X509TrustManager() {
                                                @Override
                                                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                                                }
                                                @Override
                                                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                                                }
                                                @Override
                                                public X509Certificate[] getAcceptedIssuers() {
                                                    return new X509Certificate[0];//就是这里 原代码为return null; 即不信任任何证书 我们使他信任系统默认证书
                                                }
                                            })};
                                            XposedBridge.log(TAG + "geetest hook TrustManager OK");
                                        }
                                        @Override
                                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                                            super.beforeHookedMethod(param);
                                        }
                                    });


        过了一段时间,发现方法失效,猜测有所更新,可是本地代码未曾更新,一时不知所措。不慌,先看代码。



二、逆向分析
        工欲善其事,必先利其器。逆向正式开始前最重要的是找到Log相关代码。幸运的是,极验SDK的Log类简单明了而未经过混淆。


import android.util.Log;

public class GT3Log {
    public static boolean isShowLog = false;

    public static boolean isShowLog() {
        return isShowLog;
    }

    public static void setShowLog(boolean z) {
        isShowLog = z;
    }

    public static void show(String str, String str2) {
        if (isShowLog) {
            Log.i(str, str2);
        }
    }
}

        思路清晰,直接Xposed修改isShowLog为true。同时用JADX查找setShowLog方法的引用,避免开关再被关上。很简单,没有找到引用,可以直接修改。


/**hook 极验Log*/
Class GT3Log = XposedHelpers.findClass("com.geetest.sdk.Bind.GT3Log", classLoader);
XposedHelpers.setStaticObjectField(GT3Log, "isShowLog", true);

        

        然后发现打出了Log: webview加载出错 204s ,遂寻找相关代码

[极验SDK]如何绕过在WebView中的SSL校验_第1张图片

        善良的明文字符串 (小声)

        思路清晰,往上翻找,onReceivedSslError这个方法属于一个内部类,并且一看便知这理解是SSL证书校验的问题所在。


        遂对onReceivedSslError百度之,直接得到有用的信息。

[极验SDK]如何绕过在WebView中的SSL校验_第2张图片

        再看看源码

public class SslErrorHandler extends Handler {

    /**
     * @hide Only for use by WebViewProvider implementations.
     */
    @SystemApi
    public SslErrorHandler() {}

    /**
     * Proceed with the SSL certificate.
     */
    public void proceed() {}

    /**
     * Cancel this request and all pending requests for the WebView that had
     * the error.
     */
    public void cancel() {}
}

        看到这里就稳了,只要重写onReceivedSslError,使其直接proceed,忽略异常就可以了,使用了Xposed的MethodReplacement回调,非常简单。


XposedHelpers.findAndHookMethod("com.geetest.sdk.GT3GtWebView$O00000o", classLoader, "onReceivedSslError", WebView.class, SslErrorHandler.class,
        SslError.class, new XC_MethodReplacement() {
            @Override
            protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
                XposedBridge.log(TAG + "极验geetest repalce handler proceed");
                SslErrorHandler handler = (SslErrorHandler) methodHookParam.args[1];
                handler.proceed();//跳过异常
            }
        });

        重启生效后,就可以正常的抓包了。

三、总结与技术疑问

        总结这次简单的逆向,有一个清晰的思路:

        1. 打开Log开关。

        2. 查看Log信息找字符串,如果没有明文就在hook代码中throw Exception,在StackTrace中定位关键代码。

        3. hook关键API,若是不熟悉的API就正好可以借机学习一波,逆向和开发总是相辅相成的。

        P.S. 如果是我自己开发,我会在proguard的O0o字典基础上,再增加一个混淆明文字符串的保护。

        详参 https://github.com/Qrilee/obfuseSmaliText/ 

        使用异或+十六进制的方式对字符串进行混淆,每个字符串解密对应一个解密key,字符串以byte数组呈现。

        多一道trick总是能让人获得一些恶趣味的快乐


        虽然功能已经实现了,开篇提出的问题并未解决:为什么本地代码没有更新,却又多了一道SSL校验呢?

     TrustManager出现在类GT3Geetest的readContentFromGet()里,而这次遇到的是继承的WebViewClient类里的校验,WebView用来显示验证码图片和加载点击行为的js。然而,去除TrustManager的hook代码后,仍然可以绕过校验。

        由于没有做过SSL相关实际开发,本文不得不虎头蛇尾,还期待有dalao能指点一二。


     

          


    



你可能感兴趣的:(黑科技)