关于爬虫:Frida脚本直接Hook-Java代码-RPC方式导出可调用方法-App逆向

Frida脚本

Frida脚本就是 利用Frida动静插桩框架,
应用Frida导出的 Api和办法,对 内存空间里的对象办法 进行 监控、批改和替换
的一段代码
Frida的Api是用 JavaScript实现的,
所以能够充分利用 JavaScript的匿名函数的劣势 以及 大量的Hook钩子函数 和 回调函数的 Api
  • 1.在手机上应用Frida-Server运行起来

    • 查看以后运行的App

      frida-ps -U

  • 2.Hook根底

    import frida
    import sys
    
    # 获取手机设施
    rdev = frida.get_remote_device()
    # 通过attach模式注入app
    session = rdev.attach("com.zdwh.wwdz")
    
    scr = """
    function main(){
        console.log('Frida script loads success.');
        // Java.perform 将脚本的内容注入到Java运行库中
        Java.perform(function () {
            // Java.user() 传入须要Hook的办法所在的类的类名(字符串类型)
            // 为Java类动静获取一个JavaScript Wrapper,艰深的了解为一个JavaScript对象
            let b = Java.use("com.zdwh.wwdz.wwdznet.l.b");
            // implementation 示意实现了b类的a办法,"=" 前面跟着匿名函数,
            // 通过this.a()从新执行原办法,前后能够console.log()输入解决前后的参数值
            b.a.implementation = function(){
                var result = this.a();
                console.log(result);
                return result;
            }
        });
    }
    setTimeout(main, 0);  // 等同于setImmediate 立刻执行
    """
    script = session.create_script(scr)
    script.load()
    sys.stdin.read()
  • 3.Java层被动调用

    强制调用一个办法去执行
    Java中包含静态方法、实例办法
    1. 静态方法,间接应用Java.use() 找到类间接调用(static 润饰的办法)
    2. 实例办法, 间接应用Java.choose() 在Java的堆中找到类的实例去调用办法
    • 静态方法的被动调用

      Java.perform(function () {
          let b = Java.use("com.zdwh.wwdz.wwdznet.l.b");
          b.a();
      });
    • 实例办法的被动调用

      Java.perform(function () {
          Java.choose('com.zdwh.wwdz.wwdznet.l.b', {
              onMatch: function(instance){
                  console.log('找到实例:', instance);
                  instance.a();
              },
              onComplete: function(){
                  console.log('实现实例办法的调用');
              }
          });
      });
  • 4.重载传参,以及输入Map类型数据

    能够overload Java的类型参数,或者自定义的Java类型

    Java.perform(function () {
        var b = Java.use("b.j.a.a.c.a");
        b.a.overload("java.util.Map", "java.lang.String").implementation = function(map, str){
    
            var Map = Java.use('java.util.HashMap');
            var map_x = Java.cast(map, Map);
            send(map_x.toString());
            console.log(str)
            return this.a(map,str);
        }
    });
  • 5.RPC调用

    参考:https://bbs.pediy.com/thread-…

    应用frida hook时必须通过手机操作能力调到办法,
    应用上面的形式能够被动调js export到处的native本地办法取得后果
    • jadx或者jeb反编译工具定位到native办法
    • 手机端启动frida-server
    • 编写脚本

      // 被执行js脚本
      var result;
      
      function encrypt(str_url) {
          Java.perform(function fn() {
              console.log("begin");
              Java.choose("com.mingning179.networkapi.util.JavaNdk", {
                  onMatch: function (x) {
                      console.log("find instance :" + x);
                      console.log("result of fun(string) encrypt:" + str_url);
                      result = x.encryptSrc(Java.use("java.lang.String").$new(str_url));
                  },
                  onComplete: function () {
                      console.log("end");
                  }
              })
          });
          return result;
      }
      
      function decrypt(str_data) {
          Java.perform(function fn() {
              console.log("begin");
              Java.choose("com.mingning179.networkapi.util.JavaNdk", {
                  onMatch: function (x) {
                      console.log("find instance :" + x);
                      console.log("result of fun(string) decrypt:" + str_data);
                      result = x.decryptSrc(Java.use("java.lang.String").$new(str_data));
                  },
                  onComplete: function () {
                      console.log("end");
                  }
              })
          });
          return result;
      }
      
      rpc.exports = {
          decrypt: decrypt,
          encrypt: encrypt,
      };
      import frida
      import json
      from flask import Flask, jsonify, request
      
      
      def on_message(message, data):
          if message['type'] == 'send':
              print("[*] {0}".format(message['payload']))
          else:
              print(message)
      
      
      js = open('test.js', 'r', encoding='utf8').read()
      # session = frida.get_usb_device().attach('me.ele')
      session = frida.get_usb_device().attach('com.wjmt.app')
      script = session.create_script(js)
      script.on('message', on_message)
      script.load()
      
      app = Flask(__name__)
      
      
      @app.route('/decrypt', methods=['POST'])  # data解密
      def decrypt_class():
          data = request.get_data()
          json_data = json.loads(data.decode("utf-8"))
          postdata = json_data.get("data")
          res = script.exports.decrypt(postdata)  #调用Javascript导出的办法
          return res
      
      
      @app.route('/encrypt', methods=['POST'])  # url加密
      def encrypt_class():
          data = request.get_data()
          json_data = json.loads(data.decode("utf-8"))
          postdata = json_data.get("data")
          print(postdata)
          res = script.exports.encrypt(postdata)
          return res
      
      
      if __name__ == '__main__':
          app.run()

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理