安卓自动化加解密渗透测试工具autoDecoder-实战演示某聊聊天app获取任意用户手机号


autoDecoder

  • Burp插件,根据自定义来达到对数据包的处理(适用于加解密、爆破等),类似mitmproxy,不同点在于经过了burp中转,在自动加解密的基础上,不影响APP、网站加解密正常逻辑等。
    官方地址:https://github.com/f0ng/autoDecoder

    个人理解:在安卓app请求整体被加密了以后用这个很方便下面例子说明

对测试app进行分析

  • 使用jadx进行反编看看这个apk
  • jadx查看
    从上面看不出这个app是什么加固一看是MyApplication 肯定是加固过的

  • 使用查看工具看看
  • 发现使用网易易盾进行加加固

  • 安装app到手机并且进行抓包
  • 找个可用的手机号验证码注册然后设置密码用账号密码登陆这个app。我已经注册并且设置把密码设置好了。你们自行设置。由于这个app处于运行状态涉及到敏感的地方直接打码如果后续你们遇到的话可以尝试一下。这次测试在于掌握autodecoder插件的使用其他东西我直接略过将讲解一下。想要了解详细的步骤过程后续会在飞机内部群里面讲解如果有人对博客发布文章想要详细步骤什么的。废话不多说开始抓包了。

    抓包详情
    通过抓包可以看到数据加密传输。一开始想用frida自吐算法搞一波说干就干。启动frida server。
    附加frida直接奔溃

    Traceback (most recent call last):
      File "D:\python3\lib\threading.py", line 932, in _bootstrap_inner
        self.run()
      File "D:\python3\lib\threading.py", line 870, in run
        self._target(*self._args, **self._kwargs)
      File "D:\python3\lib\site-packages\frida_tools\application.py", line 796, in _run
        work()
      File "D:\python3\lib\site-packages\frida_tools\application.py", line 394, in _try_start
        self._start()
      File "D:\python3\lib\site-packages\frida_tools\repl.py", line 139, in _start
        self._set_autoperform(self._autoperform_option)
      File "D:\python3\lib\site-packages\frida_tools\repl.py", line 472, in _set_autoperform
        if self._is_java_available():
      File "D:\python3\lib\site-packages\frida_tools\repl.py", line 479, in _is_java_available
        script = self._session.create_script(name="java_check", source="rpc.exports.javaAvailable = () => Java.available;", runtime=self._runtime)
      File "D:\python3\lib\site-packages\frida\core.py", line 26, in wrapper
        return f(*args, **kwargs)
      File "D:\python3\lib\site-packages\frida\core.py", line 262, in create_script
        return Script(self._impl.create_script(*args, **kwargs))
    frida.TransportError: the connection is closed

    我们看sapwn的方式 使用命令frida-ps -Ua 查看包名画红线框的这个就是
    使用命令查看目标app的包名
    接下来使用包名启动firda 直接等一会进程就退出了。猜测此肯定检测了frida。并且可能在so层检测。所以我们就要干掉frida检测使用葫芦娃大佬修改版的frida。减少了frida特征但是还是会被检测。思考检测肯定在某个so文件里面的某些个函数进行检测。所以我们通过这个思路可以bypass 对frida的检测干掉检测函数即可。猜测检测可能是网易易盾对frida的检测。本身app代码检测的概率很少。
    spawn

编写frida bypass脚本对抗frida检测

  • 由于网络某些地方都没有公开放出来检测代码这里仅仅演示bypass效果
  • bypass网易易盾的frida检测

使用自吐算法脚本定位算法细节

  • 随便输入一个不存在的手机号显示账号不存在我们配合包就行查找

    通杀算法脚本
    可以看到定位到了加密前的我们提交的数据密文明文上面有我没有截图
    放出堆栈信息

    堆栈信息
    java.lang.Throwable at javax.crypto.Cipher.doFinal(Native Method) at com.xxxxx.utils.SecurityUtil.aesEncrypt(SecurityUtil.java:3) at com.xxxxx.l.d.getBody(KnowAsynHttpRequestDefEncrypt.java:1) at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:12) at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:12) at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:4) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:11) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2)

    直接定位算法aes 算法 AES/ECB/PKCS5Padding 秘钥和key都吐出来了解密一波看看我们
    成功解密证明上述堆栈确实是这个的

    因为app是有加固的所以我们还是使用脱壳工具进行脱壳这里使用frida-dexdump 测试了一下blackdex貌似脱不全。总之两个工具交替使用吧
    定位key
    发现者str2是个字符串那么我们查调用这个加密的
    查找引用
    看看n0.b可能就是秘钥点一下
    查找引用

    定位到确实是用的这个key
    接下来这个引用所有的用frida hook一遍看登陆调用了哪些函数。确定以后一级一级的判断。这里我就不用这个hook通杀算法定位了来一个新的既然是 请求和响应都是base64那么他肯定要把字符串转换成字节所以。我们可以hook转换成字节的方法

字节定位分析app请求框架

  • 定位效果不错

  • 堆栈信息
    java.lang.Throwable at java.lang.String.Bytes(Native Method) at com.networkbench.agent.impl.util.j.a(SourceFile:33) at com.networkbench.agent.impl.instrumentation.NBSTransactionStateUtil.setCrossProcessHeader(SourceFile:7) at com.networkbench.agent.impl.instrumentation.NBSHttpsURLConnectionExtension.<init>(SourceFile:8) at com.networkbench.agent.impl.instrumentation.NBSInstrumentation.openConnection(SourceFile:4) at com.android.volley.toolbox.HurlStack.createConnection(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.openConnection(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:9) at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:4) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:11) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2) java.lang.Throwable at java.lang.String.Bytes(Native Method) at xxxxx.utils.SecurityUtil.aesEncrypt(SecurityUtil.java:2) at xxxxx.l.d.getBody(KnowAsynHttpRequestDefEncrypt.java:1) at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:12) at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:12) at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:4) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:11) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2) java.lang.Throwable at java.lang.String.Bytes(Native Method) at xxxxx.utils.SecurityUtil.aesEncrypt(SecurityUtil.java:3) at xxxxx.l.d.getBody(KnowAsynHttpRequestDefEncrypt.java:1) at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:12) at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:12) at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:4) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:11) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2) java.lang.Throwable at java.lang.String.Bytes(Native Method) at xxxxx.utils.SecurityUtil.aesDecrypt(SecurityUtil.java:2) at xxxxx.utils.SecurityUtil.aesDecrypt(Native Method) at xxxxx.l.d.parseNetworkResponse(KnowAsynHttpRequestDefEncrypt.java:1) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:17) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2)
  • 我们发现了一堆com.android.volley.toolbox 名字猜测有可能是发包用的 百度搜索一下

    果然是发包的
    随便搜索一个看看内置框架没办法看源码于是看看包有什么特点发现这里Port=PhoneLogin&CheckCode=0000000000;6.08.2.0;android;0;0 不变搜索一波
    瞬间柳暗花明
    随便点一个函数。看到super 一看继承StringRequest点一下看看发现点不动。看看这包名。import com.android.volley.toolbox.StringRequest;
    突破点
    百度一下import com.android.volley.toolbox.StringRequest; 如何发包不就行了https://blog.csdn.net/nuli888/article/details/52169679

    * @param path   请求路径
         * @param map    请求参数
         * @param entity 需要解析的类
         * @return
         */
        public void StringRequest_POST(final Handler handler, String path, final Map<String, String> map, final Object entity) {
    
    
    
       * get请求
         *
         * @param path   请求路径
         * @param entity 需要解析的类
         * @return
         */
        public void StringRequest_GET(final Handler handler, String path, final Object entity) 
    
    调用
    StringRequest request_post = new StringRequest(Request.Method.POST,
                    path, succes, error) {
    

    可以看出第二个参数是请求url ,如果是post第三个是参数的key 和value

编写frida hook脚本

  • frida编写脚本提示信息
  • Error: StringRequest(): has more than one overload, use .overload(<signature>) to choose from:
            .overload('java.lang.String', 'com.android.volley.Response$Listener', 'com.android.volley.Response$ErrorListener')
            .overload('int', 'java.lang.String', 'com.android.volley.Response$Listener', 'com.android.volley.Response$ErrorListener')
        at X (frida/node_modules/frida-java-bridge/lib/class-factory.js:563)
        at K (frida/node_modules/frida-java-bridge/lib/class-factory.js:558)
        at set (frida/node_modules/frida-java-bridge/lib/class-factory.js:926)
        at <anonymous> (/stringRequest.js:5)
        at <anonymous> (frida/node_modules/frida-java-bridge/lib/vm.js:12)
        at _performPendingVmOps (frida/node_modules/frida-java-bridge/index.js:238)
        at <anonymous> (frida/node_modules/frida-java-bridge/index.js:213)
        at <anonymous> (frida/node_modules/frida-java-bridge/lib/vm.js:12)
        at _performPendingVmOpsWhenReady (frida/node_modules/frida-java-bridge/index.js:232)
        at perform (frida/node_modules/frida-java-bridge/index.js:192)
        at <eval> (/stringRequest.js:14)

    看这个比较像 ‘int’, ‘java.lang.String hook一下 这样我们可以获取到任意url,至于请求数据的话直接获取密钥解密就完事了。
    说明没有问题
    搜索一下解密的内容直接定位
    组包关键函数
    解密内容

    这会儿请求的url有了返回的直接hook aes解密算法就行了。
    脚本

使用脚本分析登陆以后的操作

    下图显示登陆成功了返回的数据。

    脚本运行截图

  • 看个登陆以后返回什么在看个人信息那里明文请求是什么
  • 登陆画红框的memberid就是登陆者的id好 portpassword 是动态aes的秘钥

    登陆返回

    在看个人信息那分析包以后用hook方式发现用的是AES/ECB/PKCS5Padding 采用的动态秘钥方式 登陆成功以后给你一个动态key。所有请求用这个key进行加密响应也是用这个进行解密。
    直接用秘钥解密请求成功解密

配置bp插件autodecoder测试

autodecoder配置
Charles 转发请求到bp,直接修改id就可以获取到铭感信息
信息一
手机号信息,至此此app只要绑定手机号只要知道对方id号就可以获取手机号码
信息二

总结

此app采用的动态秘钥方式 登陆成功以后给你一个动态key。AES/ECB/PKCS5Padding 所有请求用这个key进行加密响应也是用这个进行解密。关注频道后续还会带来精彩的实战内容。和小姐姐聊天不给手机号怎么办搞他(前提是有漏洞哈哈哈)


文章作者: peiqiF4ck
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 peiqiF4ck !
  目录