• 解密SuperWebview的一种另类方法


    解密SuperWebview的一种另类方法

    什么是SuperWebview

    SuperWebview是APICloud官方推出的另一项重量级API生态产品,以SDK方式提供,致力于提升和改善移动设备Webview体验差的整套解决方案。APP通过嵌入SuperWebview替代系统Webview,即可在HTML5中使用APICloud平台现有的所有端API,以及包括增量更新、版本管理、数据云、推送云、统计分析、积木式模块化开发、所有已经聚合的开方平台服务等在内的云服务能力,增强用户体验,解决移动设备Webview使用过程中出现的兼容能力弱、加载速度慢、功能缺陷等任何问题,帮助开发者解决使用Webview过程中的所有痛点。

    SuperWebview继承APICloud终端引擎的包括跨平台能力,模块扩展机制,生命周期管理,窗口系统,事件模型,APP级别的用户体验等在内的所有优秀能力,并且全面打通html5与android和iOS之间的交互,同步提供APICloud平台最新的API技术能力和服务,APICloud团队将保持对SuperWebview的持续更新和优化,兼容Html5的新特性,持续推出优质服务。

    -----要弄别人,总得知道别人是谁。

    总结来说有三点:

    • 安卓原生Webview的扩展
    • 结合native app 和 web app
    • APICloud实现安卓框架,自己开发web

    上个图,一目了然:

    SuperWebview1

    SuperWebview的安全措施

    全包加密

    • 网页全包加密:对网页中全包的html,css,javascript代码进行加密,加密后的网友代码都是不可读的,并且不能通过常用的格式化工具恢复。代码在运行前都是加密的,在运行时进行动态解密。
    • 一键加密、运行时解密 在开发过程中无需对代码做任何特殊处理,在云编译时选择代码加密即可。
    • 零修改、零影响 加密后不改变代码的大小,不影响运行效率。
    • 安全盒子 定义了一个安全盒子,在盒子内的代码按照加密和解密进行处理,其他代码不受影响。
    • 重新定义资源标准 对保护的代码进行统一资源管理,加速资源加载,加速代码运行。

    为什么要去解密

    使用SuperWebview,安卓app基本上就是框架,一般的核心代码都放在web中。最近遇到一个灰色的软件,需要利用其中的一些东西。经过大半个星期的逆向,最终确定核心代码在web里。

    上点直观的东西

    加密后的文件

    如图:云端加密,本地运行时解密

    SuperWebview2

    解密后的文件

    如图:对于一个web app来说,这就是核心代码

    SuperWebview3

    如果要做,HOW?

    准备工作

    • 目标安卓app(最好没有加固,有加固的需要脱壳。vmp的搞不定。)
    • 一台root的手机
    • 安装xposed框架
    • 安卓开发环境(Android Studio)

    原理概述

    由于SuperWebview要兼容原生的Webview(或者说由其派生而来),所以这决定了web的代码必须要符合规范,即:必须是能让浏览器引擎识别的有效代码。很明白,在引擎中执行的都是明文。所以一下就找到一个核心点:怎么样从Webview中dump出代码。不论百度还是google都能找到方法。可以先看看这篇博客

    简单来说有4步:

    1. 开启SuperWebview/Webview的JavaScript功能
    2. 自定义本地JavaScript的接口
    3. 向网页中添加自定义接口
    4. 调用js,实现dump网页

    具体操作

    • 开启JavaScript支持功能

      一般来说,使用SuperWebview的app有99%的都开启了这个功能的。可以使用jadx打开app,全包搜索setJavaScriptEnabled函数,如果不放心,可以在找到的地方通过xposed再调用一次。

      webView.getSettings().setJavaScriptEnabled(true);
      

      搜索setJavaScriptEnabled函数
      SuperWebview4

    • 自定义JavaScript接口

      注意添加@JavascriptInterface声明

      /*
      原因:only public methods that are annotated with 
      {@link android.webkit.JavascriptInterface} can be accessed 
      from JavaScript.
      */
      import android.webkit.JavascriptInterface;
      
      final class LocalJavaScript {
      	 @JavascriptInterface
          public String dumpSource(String html) {
              return html;
          }
      }
      
    • 向网页中添加自定义接口

      这一步很关键,需要额外说明一下。先看看addJavascriptInterface函数的注释,其中有这样一句:

      Note that injected objects will not appear in JavaScript until the page is next (re)loaded.

      意思是这次加载的JavaScript代码要重载页面的时候才会生效。所以调用webView.addJavascriptInterface的时机就很重要,如果太迟则会导致后面的webView.loadUrl执行实效(因为没有添加上本地的接口):

      webView.addJavascriptInterface(new JsObject(), "injectedObject");
      webView.loadData("", "text/html", null);
      webView.loadUrl("javascript:alert(injectedObject.toString())");

      怎样确定addJavascriptInterface函数调用的时机呢?

      好简单。因为SuperWebview一定会调用这个接口的(框架决定的),利用jadx定位到该方法所在的函数,hook该函数再调用addJavascriptInterface就行了。

      对于SuperWebview,一般是在com.uzmap.pkg.uzcore.uzmodule.b包中的public void a(boolean r, String d)函数里调用:

       webView.addJavascriptInterface(new LocalJavaScript(),"dump_html");
      

      搜索addJavascriptInterface函数:
      SuperWebview5

    • 注入JS代码,dump页面

      对于SuperWebview,一般是在com.uzmap.pkg.uzcore.x包中的public void onPageFinished(WebView view, String url)函数里调用:

    webView.loadUrl("javascript:alert(dump_html.dumpSource(''+document.getElementsByTagName('html')[0].innerHTML+''))");
    ```

    代码执行效果:

    SuperWebview6

    写xposed代码的tips

    • 如果需要hook的函数里有自定义类型怎么办?

      加载该类,然后作为参数传递:

    Class<?> UZWebView =null;
    UZWebView =lpparam.classLoader.loadClass("com.uzmap.pkg.uzcore.UZWebView");

           
    * 如何获取对象的成员属性?
    
    	通过反射调用:
    	
    	```java
    // 获取实例对象
    Class clazz = param.thisObject.getClass();
    // 获取类成员属性
    Field field = clazz.getDeclaredField("a");
    field.setAccessible(true);
    // 获取指定对象的成员属性
    WebView webView = (WebView) field.get(param.thisObject);
    // 调用该对象的方法
    webView.addJavascriptInterface(new InJavaScriptLocalObj(), "dump_html");
    	```
    	
    	注1:如果成员属性是自定类型的,暂时还不知道该怎么办。在此向大神们请教。谢谢。  
    	注2:如果hook的是静态方法,是不能获取到对象的属性的。
    	
    * 如何调用对象的方法?
    
    	通过反射调用:只能调用对象实现的方法,如果该方法在本类中没有实现(如调用父类的方法),则无法成功
    	
    	```java
    // 获取实例对象---也有可能是从参数获取,如param.args[0]
    Class clazz = param.thisObject.getClass();
    // 如果类有该方法就可以用反射调用的方式
    Method c = a.getClass().getDeclaredMethod("c", int.class);
    c.invoke(a,12);
    	```
    * 如何hook函数?
    
    	hook构造函数使用:**findAndHookConstructor**
    	
    	```java
    	findAndHookConstructor(className,
                    lpparam.classLoader,
                    param,
                    new XC_MethodHook() {
                     @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
    							//do something
                        }
    
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    							//do something
                        }
                    }
            );
    	```
    	
    	hook一般函数使用:**findAndHookMethod**
    	
    	```java
    	 findAndHookMethod(className,
                    lpparam.classLoader,
                    methods,
                    param,
                    new XC_MethodHook() {
                     @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            // do somethin
                }
    
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            // do somethin
                }
            });
    
    	```
    	
    * 如何查看调用流程?
    
    	抛出异常,打印调用栈:
    	
    	```java
    	String exceptionName = "whatever";
    	new Exception(exceptionName).printStackTrace();
    XposedBridge.log(new Exception(exceptionName));
    	```
    
    ## 总结
    
    诚然通过这种方式是无法获取到所有的解密文件的。例如html里面加载的js脚本,css文件。我也曾想通过注入js的方法来获取加载的js文件,但并未成功。
    
    诚然最简单的方法还是去逆向SuperWebview,找到核心函数,可以获取到所有的解密文件。
    
    诚然这个过程并没有帮助我达到最终的目的,可它还是很有趣。
    
    目的不是想教大家怎么去逆向别人的产品,只是在研究学习的过程中发现了一些有趣好玩的iead。特别想将这个idea分享一下。无他。
    
    当然,对于这款灰色的软件,最终还是达到了最初的目的。只是并非使用了如此手段。
    
    
    ## 后记
    
    技术的道路看不到尽头。或者只身一人,或者三五成群,有时狂奔,有时懒散。我们终究停不下这个脚步,逢山翻山,遇水淌水。也许那里也有一片天,一片地。保持初心,勇敢前行。
  • 相关阅读:
    SQL注入原理解说,非常不错!
    Asp.Netserver控件开发的Grid实现(三)列编辑器
    Windows下搭建deepnet环境
    reactor设计模式
    C++ 表达式语句 海伦的故事
    [ArcGIS必打补丁]ArcGIS 10.1 SP1 for (Desktop, Engine, Server) Quality Improvement Patch
    四个好看的CSS样式表格
    UVA 10047 The Monocycle (状态记录广搜)
    二叉搜索树相关性质的应用
    广播(broadcast)、电视与电视网络
  • 原文地址:https://www.cnblogs.com/ddvv/p/7060071.html
Copyright © 2020-2023  润新知