当前位置: 首页 > article >正文

网络安全 逆向 apk 网络安全逆向分析

🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快

[网安实践III] 实验3.逆向分析

1 流量分析

借助Wireshark抓取Android模拟器中“QQ同步助手”登录和同步数据时的流量,回答以下问题:  
(1)筛选流量中,对应域名 "mpssync.3g.qq.com" 的IP地址;
(2)同步报文的TCP流量源IP:端口,目的IP:端口;
(3)分析同步流量的数据特征,并根据这些特征,能否获取报文的一些信息,例如密文长度信息;
(4)保存并上传流量分组文件。
    1. mpssync.3g.qq.com 的IP地址: 183.3.225.36 和 113.96.237.110
    2. 同步报文 TCP 流量, 源 IP 为 10.12.181.187, 源端口为 3550, 目的 IP 为 113.96.237.110, 目的端口为 14000.
    3. 同步流量的数据特征: 传输数据的前4个字节表示后面加密数据的长度(单位字节), 数据的加密类型为分组加密.
    4. 流量分组文件:  lab3.pcapng
    分析过程
    1. 通过 Wireshark 截包, 过滤条件为 dns, 容易找到对域名 mpssync.3g.qq.com 的 DNS 查询和响应包, 如下图所示, 可以得到该域名对应的 IP 地址有 183.3.225.36 和 116.96.237.110.
    • 注: 在使用同步助手时, 要先下载 QQ, 使用 QQ 账号进行快捷登录才能成功登录 QQ 同步助手. 此外, 需要在模拟器中添加联系人, 这样才能进行数据同步.
    1. 使用过滤条件来过滤与域名 mpssync.3g.qq.com 相关的数据包. 过滤条件如下, 即数据包的源或目的 IP 为域名的IP.
    ip.src==113.96.237.110 or ip.dst == 113.96.237.110 or ip.dst == 183.3.225.36 or ip.src==183.3.225.36
    • 1.

    如下图为过滤后得到的数据包.

    网络安全 逆向 apk 网络安全逆向分析_数据

    由于本机的 IP 地址是 10.12.181.187, 因此可以得出, 同步报文的 TCP 流量源 IP 为本机的 IP 10.12.181.187, 源端口为 3550, 目的 IP 为域名 mpssync.3g.qq.com 的其中一个 IP 地址 113.96.237.110, 目的端口为 14000.

    3. 选择其中一个报文, 右键"追踪流"并使用"Hex 转储"模式查看上述报文的传输数据.

    网络安全 逆向 apk 网络安全逆向分析_网络安全 逆向 apk_02

    通过观察上述数据可以发现, 传输的数据是经过加密的, 而且前四个字节表示了加密的数据长度(即传输的数据长度-4), 如上图报文长度为 158h, 加密的数据长度为 154h, 而前 4 个字节的数据即为 154h. 而提供了数据长度的加密类型一般是分组加密.

    2 函数调用栈动态跟踪

    借助AndroidKiller分析和DDMS的“Method Profiling”功能,分析“QQ手机助手”登录和同步时的函数调用栈,回答以下问题:
    (1)程序的包名是什么?
    (2)在DDMS中对“QQ手机助手”进行动态跟踪时,PC端与手机(或模拟器)端连接的端口是多少,并参考实验手册中6.2节中的示例,附上截图。
    (3)trace文件中,列举若干涉及加解密函数的调用栈(附上截图)。
    (4)上传trace文件。
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.

    网络安全 逆向 apk 网络安全逆向分析_数据_03

    1. 程序包名: com.tencent.qqpim
    2. PC端与手机模拟器连接的端口为 8600
    3. trace 文件中涉及加解密函数的调用栈

    网络安全 逆向 apk 网络安全逆向分析_安全_04

    网络安全 逆向 apk 网络安全逆向分析_安全_05

    网络安全 逆向 apk 网络安全逆向分析_IP_06

    网络安全 逆向 apk 网络安全逆向分析_安全_07

    网络安全 逆向 apk 网络安全逆向分析_安全_08

    • com.tencent.tccsync.TccTeaEncryptDecrypt.tccXXTeaDecrypt
    • com.tencent.tccsync.TccTeaEncryptDecrypt.encrypt
    • com.tencent.tccsync.TccTeaEncryptDecrypt.decrypt
    • com.tencent.tccsync.TccTeaEncryptDecrypt.tccXXTeaEncrypt
    • com.tencent.tccsync.TccTeaEncryptDecrypt.getXXTccTeaEncryptDecryptKey
    1. trace 文件: 略
    分析过程

    网络安全 逆向 apk 网络安全逆向分析_安全_09

    1. 使用 AndroidKiller 打开 QQ手机助手的 APK, 即可得到程序包名: com.tencent.qqpim
    2. 在手机模拟器(此处使用的雷电模拟器)正在运行, 且其中运行有 QQ手机助手时, 启动 DDMS. 可以看到跟踪到的设备"雷电模拟器"对应的 emulator-5554, 其中可以看到进程列表中有运行的 QQ手机助手的包名, 选中后点击上面的 “Start Method Profiling” 按钮, 并选择 “Trace based profiling” 选项开始跟踪.
    • 注: DDMS 工具通过 Android SDK 的 tools/monitor.bat 文件进行启动, 要求 JDK 版本不能超过 1.8.
    1. 然后在手机模拟器上使用 QQ手机助手进行同步, 之后再点击按钮 “Stop Method Profiling”, 关闭跟踪. 如图在 Temp 路径下得到了跟踪的 trace 文件.
    2. 使用 Android SDK 工具 Traceview 查看上述得到的 trace 文件. 该工具由 tools/tracview.bat 文件启动, 使用如下命令打开 trace 文件.
    PS> .\traceview.bat E:\xxx\ddms_lab3.trace    # 需要trace文件的绝对路径
    • 1.

    网络安全 逆向 apk 网络安全逆向分析_数据_10

    在 Find 文本框中输入"encrypt"和"decrypt"来搜索和加密相关的函数, 具体的搜索结果和截图见上文的答案.

    3 函数参数动态跟踪

    安装Frida工具,编写Python脚本,基于动态跟踪结果,回答以下问题:
    (1)基于DDMS动态跟踪结果,列举同步过程中,调用了哪些加解密函数,并分析函数参数列表中的参数含义,比如,明文、密文和密钥。
    (2)针对每一加解密函数,编写Python脚本,跟踪函数的输入和输出,分析可能采用的密钥、明文或密文数组。
    (3)在跟踪函数参数时,同时利用Wireshark抓取同步时的报文,将报文与跟踪的函数参数(密文)进行比对。
    (4)上传相关脚本和跟踪结果文件。
      1. 同步过程中使用的加解密函数及其参数含义:
      • byte[] com.tencent.tccsync.TccTeaEncryptDecrypt.tccXXTeaDecrypt(byte[] arg1, byte[] arg2): 参数1为密文, 参数2为密钥, 返回值为明文.
      • byte[] com.tencent.tccsync.TccTeaEncryptDecrypt.tccXXTeaEncrypt(byte[] arg1, byte[] arg2): 参数1为明文, 参数2为密钥, 返回值为密文.
      • byte[] com.tencent.tccsync.TccTeaEncryptDecrypt.encrypt(byte[] arg1): 参数1为明文, 返回值为密文.
      • byte[] com.tencent.tccsync.TccTeaEncryptDecrypt.decrypt(byte[] arg1): 参数1为密文, 返回值为明文.
      • byte[] com.tencent.tccsync.TccTeaEncryptDecrypt.getXXTccTeaEncryptDecryptKsyy(): 返回值为密钥.
      1. 通过分析:
      • tccXXTeaEncrypt和 tccXXTeaDecrypt 函数可能采用的密钥有: [8,6,3,8,1,8,0,2,6,9,6,3,3,3,1,h,^,J,9,o,`][1,7,7,2,7,0,1,4,9,7,&,C,O,M,N,:,8,6,3,8,1,8,0,2,6,9,6,3,3,3,1,&,1,2,3,8,5,9,0,5,6,9,&,1,6,2,1,6,6,9,5,1,0][D,F,G,#,$,%,^,#,%,$,R,G,H,R,(,&,*,M,<,>,<].
      • tccXXTeaDecrypt解密的明文有一些类似网址的数据.
      • tccXXTeaEncypt和 encrypt 加密的明文数据难以识别, 猜测应该是编码格式不正确. 不过在其中找到了个人的QQ号等信息
      • decrypt 函数中能在解密数据中看到一些类似网址的信息.
      • getXXTccTeaEncryptDecryptKsyy() 函数并没有截获到.
      1. 如下图可以看到, 使用 tccXXTeaEncypt 加密的数据与实际 Wireshark 截获的发送的数据是一致的. 同样的, decrypt 待解密的数据与 Wireshark 截获的收到的数据是一致的. 不同之处在于实际在发送时会在加密数据前添加了 4 个字节表示数据长度.
      2. 脚本代码
      import frida
      import sys
      
      # 获取设备
      redev = frida.get_remote_device()
      print("redev:", redev)
      # 获取应用进程
      front_app = redev.get_frontmost_application()
      print("front_app:", front_app)
      qqtb = "com.tencent.qqpim"
      session = redev.attach(qqtb)
      
      # Js脚本对应字符串
      jscode = """
      //转换为数组
      var toStr = function(title, obj){
          return title + ":["+JSON.parse(JSON.stringify(obj))+"] ";
      } 
      //函数标题
      var funcTitle = function(funcName) {
          return "Hooked Function: "+funcName+" "
      }
      //转换为ASCII码输出
      var toAscii = function(arr) {
          var s=[];
          for(var i=0;i<arr.length;i++){
              s.push(String.fromCharCode(arr[i]));
          }
          return s;
      }
      //转换为16进制字符串输出
      var toHex = function(arr) {
          var s=[];
          for(var i=0;i<arr.length;i++){
              s.push((arr[i]&0xff).toString(16));
          }
          return s;
      }
      Java.perform(function () {
          //选择捕获包
          var tted = Java.use("com.tencent.tccsync.TccTeaEncryptDecrypt");
          //设置捕获函数 tccXXTeaDecrypt
          tted.tccXXTeaDecrypt.implementation = function (arg1, arg2) {
              var msg = funcTitle("tccXXTeaDecrypt");
              msg += toStr("arg1(Hex)", toHex(arg1));
              msg += toStr("arg2(ASCII)", toAscii(arg2));
              //输出返回值
              var rtn = this.tccXXTeaDecrypt(arg1, arg2);
              msg += toStr("rtn(ASCII)", toAscii(rtn));
              send(msg);
              return rtn;
          };
          //设置捕获函数 tccXXTeaEncrypt
          tted.tccXXTeaEncrypt.implementation = function (arg1, arg2) {
              var msg = funcTitle("tccXXTeaEncrypt");
              msg += toStr("arg1(ASCII)",toAscii(arg1));
              msg += toStr("arg2(ASCII)", toAscii(arg2));
              //输出返回值
              var rtn = this.tccXXTeaEncrypt(arg1, arg2);
              msg += toStr("rtn(Hex)", toHex(rtn));
              send(msg);
              return rtn;
          }
          //设置捕获函数 encrypt
          tted.encrypt.implementation = function (arg1) {
              var msg = funcTitle("encrypt");
              msg += toStr("arg1(ASCII)", toAscii(arg1));
              var rtn = this.encrypt(arg1);
              msg += toStr("rtn(Hex)",toHex(rtn));
              send(msg);
              return rtn;
          }
          //设置捕获函数 decrypt
          tted.decrypt.implementation = function (arg1) {
              var msg = funcTitle("decrypt");
              msg += toStr("arg1(Hex)", toHex(arg1));
              var rtn = this.decrypt(arg1);
              msg += toStr("rtn(ASCII)",toAscii(rtn));
              send(msg);
              return rtn;
          }
          //设置捕获函数 getXXTccTeaEncryptDecryptKey
          tted.getXXTccTeaEncryptDecryptKey = function () {
              var msg = funcTitle("getXXTccTeaEncryptDecryptKey");
              var rtn = this.getXXTccTeaEncryptDecryptKey();
              msg += toStr("rtn(Hex)",toHex(rtn));
              send(msg);
              return rtn;
          }
      });
      """
      script = session.create_script(jscode)
      
      def on_message(message,data):
          print(message)
      
      
      script.on('message', on_message)
      script.load()
      sys.stdin.read()
        分析过程
        1. 安装 Frida 及其相关工具:
          在安装有 python 的基础上, 使用 pip 工具下载 Frida 及其工具
        PS> pip install frida    # 安装Frida
        PS> pip install frida-tools    # 安装frida-tools
        PS> frida --version    # 查看Frida版本

          如图所示, 当前下载的 Frida 版本为 14.2.18

          网络安全 逆向 apk 网络安全逆向分析_IP_11

          1. 安装 frida-server 并启动:
            在 GitHub 上下载对应的服务端程序, 对应雷电模拟器, 下载的为 frida-server-14.2.18-android-x86.
            雷电模拟器的根目录下提供了 adb 工具, 使用该工具将 frida-server 传至手机模拟器中.
            使用 adb devices 指令可以查看当前连接的设备列表, 在启动雷电模拟器的情况下, 是自动连接的, 如下图所示, "-"后的数字即为连接的端口号.

            使用 push 命令将 frida-server 传至手机模拟器.
          PS>  .\adb.exe push .\frida-server-14.2.18-android-x86 /data/local/tmp
          • 1.

          使用 chmod 命令更高 frida-server 的权限, 然后启动.

          PS> ./adb.exe shell
          # cd /data/local/tmp
          # chmod 777 frida-server-14.2.18-android-x86    # 更改权限
          # ./frida-server-14.2.18-android-x86     # 启动

            在一个新的控制台窗口使用命令 frida-ps -U 查看是否有正常输出.

            网络安全 逆向 apk 网络安全逆向分析_web安全_12

            1. 采用 frida 跟踪 Java 函数参数:
              编写如下 Python 代码:
            import frida
            import sys
            
            # 获取设备
            redev = frida.get_remote_device()
            print("redev:", redev)
            # 获取应用进程
            front_app = redev.get_frontmost_application()
            print("front_app:", front_app)
            qqtb = "com.tencent.qqpim"
            session = redev.attach(qqtb)
            # Js脚本对应字符串
            jscode = """
            Java.perform(function () {
                //选择捕获函数TccTeaEncryptDecrypt
                var tted = Java.use("com.tencent.tccsync.TccTeaEncryptDecrypt");
                //设置捕获函数
                tted.tccXXTeaDecrypt.implementation = function (arg1, arg2) {
                    //捕获到了函数
                    send("Hook start ...");
                    //输出参数1
                    send("arg1:");
                    send(arg1);
                    //输出参数2
                    send("arg2:");
                    var ss = [];
                    for (var i = 0; i < arg2.length; i++) {
                        //将参数有ASCII码转为字符
                        ss.push(String.fromCharCode(arg2[i]));
                    }
                    send(ss.toString());
                    //输出返回值
                    var rtn = this.tccXXTeaDecrypt(arg1, arg2);
                    send("rtn:");
                    send(rtn);
                    return rtn;
                };
            });
            """
            script = session.create_script(jscode)
            
            def on_message(message,data):
                print(message)
            
            script.on('message', on_message)
            script.load()
            sys.stdin.read()

              该脚本实际上就是选择了 QQ 手机助手中的解密函数 com.tencent.tccsync.TccTeaEncryptDecrypt 进行了捕获操作, 将其函数参数和返回结果进行了输出.

              1. 在手机模拟器中开启 QQ 手机助手后运行脚本. 并在手机模拟器中使用 QQ 手机助手进行同步操作, 即可捕获到数据.

                如图为脚本捕获的数据, 经分析可以看出, 对于该函数 TccTeaEncryptDecrypt, 其第一个参数值有正有负, 应该是密文; 第二个参数长度固定, 且在后续的捕获中重复出现, 应该是解密用的密钥; 返回值为 128 以内的数字, 应该是明文.
              • 注: 运行脚本时出现 frida.ServerNotRunningError: unable to connect to remote frida-server 的错误, 则需要开启端口转发, 使用如下命令:
              PS> .\adb.exe forward tcp:27042 tcp:27042
              • 1.
              1. 同理, 使用上述方法, 通过修改脚本中的捕获函数, 可以对其它几个加解密函数进行捕获分析.
                最终脚本如下:
              import frida
              import sys
              
              # 获取设备
              redev = frida.get_remote_device()
              print("redev:", redev)
              # 获取应用进程
              front_app = redev.get_frontmost_application()
              print("front_app:", front_app)
              qqtb = "com.tencent.qqpim"
              session = redev.attach(qqtb)
              
              # Js脚本对应字符串
              jscode = """
              //转换为数组
              var toStr = function(title, obj){
                  return title + ":["+JSON.parse(JSON.stringify(obj))+"] ";
              } 
              //函数标题
              var funcTitle = function(funcName) {
                  return "Hooked Function: "+funcName+" "
              }
              //转换为ASCII码输出
              var toAscii = function(arr) {
                  var s=[];
                  for(var i=0;i<arr.length;i++){
                      s.push(String.fromCharCode(arr[i]));
                  }
                  return s;
              }
              //转换为16进制字符串输出
              var toHex = function(arr) {
                  var s=[];
                  for(var i=0;i<arr.length;i++){
                      s.push((arr[i]&0xff).toString(16));
                  }
                  return s;
              }
              Java.perform(function () {
                  //选择捕获包
                  var tted = Java.use("com.tencent.tccsync.TccTeaEncryptDecrypt");
                  //设置捕获函数 tccXXTeaDecrypt
                  tted.tccXXTeaDecrypt.implementation = function (arg1, arg2) {
                      var msg = funcTitle("tccXXTeaDecrypt");
                      msg += toStr("arg1(Hex)", toHex(arg1));
                      msg += toStr("arg2(ASCII)", toAscii(arg2));
                      //输出返回值
                      var rtn = this.tccXXTeaDecrypt(arg1, arg2);
                      msg += toStr("rtn(ASCII)", toAscii(rtn));
                      send(msg);
                      return rtn;
                  };
                  //设置捕获函数 tccXXTeaEncrypt
                  tted.tccXXTeaEncrypt.implementation = function (arg1, arg2) {
                      var msg = funcTitle("tccXXTeaEncrypt");
                      msg += toStr("arg1(ASCII)",toAscii(arg1));
                      msg += toStr("arg2(ASCII)", toAscii(arg2));
                      //输出返回值
                      var rtn = this.tccXXTeaEncrypt(arg1, arg2);
                      msg += toStr("rtn(Hex)", toHex(rtn));
                      send(msg);
                      return rtn;
                  }
                  //设置捕获函数 encrypt
                  tted.encrypt.implementation = function (arg1) {
                      var msg = funcTitle("encrypt");
                      msg += toStr("arg1(ASCII)", toAscii(arg1));
                      var rtn = this.encrypt(arg1);
                      msg += toStr("rtn(Hex)",toHex(rtn));
                      send(msg);
                      return rtn;
                  }
                  //设置捕获函数 decrypt
                  tted.decrypt.implementation = function (arg1) {
                      var msg = funcTitle("decrypt");
                      msg += toStr("arg1(Hex)", toHex(arg1));
                      var rtn = this.decrypt(arg1);
                      msg += toStr("rtn(ASCII)",toAscii(rtn));
                      send(msg);
                      return rtn;
                  }
                  //设置捕获函数 getXXTccTeaEncryptDecryptKey
                  tted.getXXTccTeaEncryptDecryptKey = function () {
                      var msg = funcTitle("getXXTccTeaEncryptDecryptKey");
                      var rtn = this.getXXTccTeaEncryptDecryptKey();
                      msg += toStr("rtn(Hex)",toHex(rtn));
                      send(msg);
                      return rtn;
                  }
              });
              """
              script = session.create_script(jscode)
              
              def on_message(message,data):
                  print(message)
              
              
              script.on('message', on_message)
              script.load()
              sys.stdin.read()

                截获到的相关函数截图:

                网络安全 逆向 apk 网络安全逆向分析_IP_13

                网络安全 逆向 apk 网络安全逆向分析_数据_14

                网络安全 逆向 apk 网络安全逆向分析_IP_15

                网络安全 逆向 apk 网络安全逆向分析_网络安全 逆向 apk_16

                1. 在跟踪的同时打开 Wireshark 进行截包, 按上述的过滤条件找到与域名 mpssync.3g.qq.com 的 IP 相关的数据包, 跟踪流后进行数据包和使用脚本捕获的数据进行对比, 可以看到是一致的, 具体见上述结果.

                4 二进制代码分析

                借助IDA Pro分析“QQ手机助手”中与同步相关的so文件,回答以下问题:
                (1)与同步操作有关的文件名称;
                (2)比较Java代码(借助AndroidKiller分析)与二进制代码中对应函数参数列表的差异;
                (3)还原与加密密钥相关的二进制代码,以C代码形式呈现;
                (4)还原二进制代码中核心的加解密代码,以C代码形式呈现;
                (5)上传还原的C代码(说明其主要功能)。
                  1. 与同步操作有关的文件名称: lib/armeabi/libSync.so
                  2. 二进制代码中, 只有 getXXTccTeaEncryptDecryptKey 函数同 Java 代码一样, 函数参数均为 0; 其余 4 个加解密函数, 二进制代码比 Java 代码多 2 个参数: 第一个参数的类型为 JNIEnv*, 第二个参数的类型为 jobject.
                  3. 还原的 C 代码:  encdec.c
                  4. 相关函数的主要功能:
                  • getXXTccTeaEncryptDecryptKey: 获取固定密钥 DFG#$%^#%$RGHR(&*M<><
                  • 调用函数: 调用函数: sub_16F4
                  • decrypt: 给定密文使用固定密钥进行解密.
                  • 调用函数: sub_16F4sub_183C
                  • encrypt: 给定明文使用固定密钥进行加密.
                  • 调用函数: sub_16F4sub_183C
                  • tccXXTeaDecrypt: 给定明文和密钥进行解密.
                  • 调用函数: sub_183C
                  • tccXXTeaEncrypt: 给定密文和密钥进行解密.
                  • 调用函数: sub_183C
                  • sub_16F4: 获取固定密钥 DFG#$%^#%$RGHR(&*M<><
                  • sub_183C: 给定待处理的数据, 密钥和模式(加密或者解密)进行加解密.
                  • 调用函数: sub_C62Csub_C49C
                  • sub_C62C: 加密函数. 六个参数分别为明文数组指针, 明文长度, 密钥数组指针, 密钥长度, 用于存放密文的缓冲区指针及其长度. 函数的返回值为密文的长度.
                  • 调用函数: sub_C4D8
                  • sub_C49C: 解密函数. 六个参数分别为密文数组指针, 密文长度, 密钥数组指针, 密钥长度, 用于存放明文的缓冲区指针及其长度. 函数的返回值为明文的长度.
                  • 调用函数: sub_C340
                  • sub_C4D8: 具体的加密函数, 参数和返回值同 sub_C62C, 对密钥进行 MD5 哈希后使用类似 XXTEA 的加密算法进行数据加密.
                  • 调用函数: sub_C2C4sub_144C0
                  • sub_C340: 具体的解密函数, 参数和返回值同 sub_C49C, 对密钥进行 MD5 哈希后使用类似 XXTEA 的解密算法进行数据解密.
                  • 调用函数: sub_C2C4sub_144C0
                  • sub_C2C4: MD5 哈希算法
                  • sub_144C0: 除法运算.
                  分析过程
                  1. 首先借助 AndroidKiller 工具通过加解密函数所在的包名 com.tencent.tccsync.TccTeaEncryptDecrypt找到对应的 smali 文件, 并进行反编译, 得到其 Java 代码.

                    可以看到, 上述提到的加解密函数此处只有定义, 因此是原生函数, 而该类中有一个静态初始化块, 其中有函数 getLibName(), 因此可以得知这些函数是通过外部加载的, 点击该函数跳转到其所在的类, 可以得到加载的库文件名 “Sync”, 因此最终可以确定加解密的函数应该在库文件 libSync.so 中实现.
                  2. 使用 IDA Pro 打开 lib/armeabi/libSync.so 文件, 可以在函数列表中找到这些加解密函数.

                    如图为 tccTeaEncrypt 函数反编译后的 C 代码, 可以看到其有 4 个参数, 比 Java 代码中的参数多了 2 个, 其他几个函数也是如此. 只有没有参数的 getXXTccTeaEncryptDecryptKey, 其反汇编后的 C 代码也没有参数. 根据 .so 库中有关 Java 导出函数的参数的约定,第一个参数的类型是结构体指针 JNIEnv*,第二个参数的类型一定是 jobject
                  3. 经过对反汇编的函数进行分析得到. 和加解密相关的一共有 5 个函数.
                    其中 tccXXTeaDecrypttccXXTeaEncryptencrypt 和 decrypt 四个函数中都调用了 sub_183C 函数. 进过分析, 该 sub_183C 函数是进行数据加解密的核心函数, 其完整的函数签名为 jbyteArray __fastcall sub_183C(JNIEnv *env, jbyteArray srcArray, jbyteArray key, int doEncrypt). 其中第二个参数是待处理的数据的 byte[] 类型数组, 加密时是明文, 解密时是密文; 第三个参数是密钥的 byte[] 数组; 第四个参数是一个标记参数, 为 1 时表示加密, 为 0 时表示解密. 此外, 对于 tccXXTeaDecrypttccXXTeaEncrypt两个函数, 密钥数组是直接由参数传递给 sub_183C 函数; 而对于 encrypt 和 decrypt 函数, 密钥是由 sub_16F4函数得到的, 而实际上其返回的是一个固定的密钥 DFG#$%^#%$RGHR(&*M<><. 而函数 getXXTccTeaEncryptDecryptKey 就是直接调用的 sub_16F4 获取的这一固定密钥.
                    对于 sub_183C 函数即核心的加解密函数, 其主要分为三部分, 第一部分是由 GetByteArrayElements 和 GetArrayLength 分别获取待处理数组 SRCArray 和密钥 key 所对应的原始 byte 数组的指针以及数组的长度. 接下来第二部分通过判断第四个参数 doEncrypt 来对数据进行加密或者解密, 加密调用函数 subC62C, 解密调用函数 sub_C49C. 最后第三部分是通过 NewByteArray 函数为加密或解密后的数据创建 Java 的 byte数组, 然后通过 SetByteArrayRegion 将由第二部分的函数得到的加密或解密的数据存储到 Java 的数组中.
                    因此, 对于加密数据, 主要是通过调用函数 sub_C62C. 其函数签名为 jsize __fastcall sub_C62C(jbyte *plainBuf, jsize plainLen, jbyte *key, jsize keyLen, void *cipherBuf, int bufLen). 六个参数分别为明文数组指针, 明文长度, 密钥数组指针, 密钥长度, 用于存放密文的缓冲区指针及其长度. 函数的返回值为密文的长度. 在该函数中主要进行了 cipherBuf 的特殊情况处理, 然后主要是通过调用 sub_C4D8 函数完成的数据加密.
                    同样的, 对于解密数据, 主要是通过调用函数 sub_C49C. 其函数签名为 jsize __fastcall sub_C49C(jbyte *cipherBuf, jsize cipherLen, jbyte *keyBuf, jsize keyLen, char *plainBuf, int bufLen). 六个参数分别为密文数组指针, 密文长度, 密钥数组指针, 密钥长度, 用于存放明文的缓冲区指针及其长度. 函数的返回值为明文的长度. 在该函数中, 主要的解密操作是通过调用函数 sub_C340 得到的.
                    对于 sub_C4D8 和 sub_C340函数, 它们的函数签名分别和调用它们的函数 sub_C62C和 sub_C49C 是相同的. 通过分析和查阅有关资料, 通过一些比较有特点的数值, 如 52 和 0x9e3779b9可以得到, 这两个函数的核心算法与 XXTEA 加解密算法是相同的. 不过在此之前, 均使用了 sub_C2C4 函数进行了处理. 在 sub_C2C4 函数中调用的 sub_C160 中有 1732584193-271733879 等一组数字, 而这些数字是在 MD5 算法中用到的, 因此可以推测 sub_C2C4 函数实际上为 MD5 哈希函数, 也就是说密钥在使用之前都会进行 MD5 的哈希操作.
                  • PS: 逆向的 libSync.so 文件及相应的 IDA 文件:  libSync.so libSync.idb

                  5 报文还原测试(选做)

                  根据抓取的报文,跟踪的密钥和还原代码,测试对跟踪和分析结果的正确性。上传分析过程和结果。

                  最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

                  上述所有都有配套的资料,这些资料,对于做【网络安全】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。


                    http://www.kler.cn/a/554800.html

                    相关文章:

                  • 图数据库Neo4j面试内容整理-建模实践
                  • 云原生监控体系建设:Kubernetes架构下的全面监控策略
                  • Openssl之SM2加解密命令
                  • 我国首条大型无人机城际低空物流航线成功首航
                  • 【时时三省】(C语言基础)三种基本结构和改进的流程图
                  • 计算机视觉之图像处理-----SIFT、SURF、FAST、ORB 特征提取算法深度解析
                  • 一周学会Flask3 Python Web开发-response响应格式
                  • 基于GraphQL的电商API性能优化实战
                  • 项目管理的核心是什么?
                  • DeepSeek vs ChatGPT:AI 领域的华山论剑,谁主沉浮?
                  • 【机器学习】衡量线性回归算法最好的指标:R Squared
                  • unity学习50:NavMeshAgent 区域Areas和cost
                  • ES三种查询方式,为什么searchAfter效率高
                  • 全志A133 android10 适配SLM770A 4G模块
                  • 网络安全入门攻击与防御实战(四)
                  • 卷积神经网络实战宠物狗识别
                  • 从硬件工程师视角解析宇树机器人:四足机器人的核心设计与技术挑战
                  • leetcode876.链表的中间结点
                  • HBuilderX中,VUE生成随机数字,vue调用随机数函数
                  • Cannot import to svn: ‘C:\Program‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。