• Frida常用方法


    基础语法

    符号作用
    $init 构造方法 Hook 的时候用
    $new() 实例化对象的时候用
    Hook重载语法
    int类型 int
    float类型 float
    boolean类型 boolean
    string类型 java.lang.String
    byte类型 [B
    char类型 [C
    list结构 java.util.List
    安卓上下文结构 android.content.Context

    主动调用函数

    • 静态函数 static 可以直接调用
    • 动态函数要用choose找到实例才能操作

    静态函数主动调用

    Java.perform(function x(){
        var LoginActivity = Java.use("com.xx.xx.xx.xx");
        LoginActivity.function();
    }
    )
     
    JavaScript

    动态函数主动调用

    Java.perform(function x(){
        Java.choose("com.xx.xx.xx.xx",{
            onMatch: function(instance){
                instance.function();
            },
            onComplete: function(){
    
            }
        });
    }
    )
     
    JavaScript

    修改变量

    APP 代码如下

    public class FridaTest extends BaseFridaTest{
        private static boolean static_bool_var = false;
        private boolean bool_var = false;
        private boolean same_name_bool_var = false;
    }
     
    Java
    • 静态变量 static 可以直接设置值
    • 动态变量要用choose找到实例才能操作

    静态变量

    道理和调用函数相同

    var LoginActivity3 = Java.use("com.xx.xx.xx.xx");
    
    // 设置变量值后面必须加 `.value` 才能设置
    LoginActivity3.static_bool_var.value = true;
     
    JavaScript

    动态变量

    // 动态变量必须 choose 找到示例才能操作
    Java.choose("com.xx.xx.xx.xx",{
        onMatch: function(instance){
            // 设置变量值后面必须加 `.value` 才能设置
            instance.bool_var.value = true;
            
            // 注意! 如果动态变量名与函数名重名了,就需要在前面加 _ 下划线,如下:
            instance._same_name_bool_var.value = true;
        },
        onComplete: function(){
        }
    });
     
    JavaScript

    枚举

    枚举类中方法

    有的情况下我们要hook一个类下所有的方法(不知道他的方法类型和数量),这个时候我们就要用到 java 的反射 getDeclaredMethods()

    //Hook类的所有方法
    Java.perform(function(){
        var md5 = Java.use("com.xxx.xxx.xxx");
        var methods = md5.class.getDeclaredMethods();
        for(var j = 0; j < methods.length; j++){
            var methodName = methods[j].getName();
            console.log(methodName);
            // hook methodNmae 这个类的所有方法(难点在于每个方法的参数是不同的)
            for(var k = 0; k < md5[methodName].overloads.length; k++){
                md5[methodName].overloads[k].implementation = function(){
                    // 这是 hook 逻辑
                    for(var i = 0; i < arguments.length; i++){
                        console.log(arguments[i]);
                    }
                    return this[methodName].apply(this, arguments);  // 重新调用
                }
            }
    
        }
    });
     
    JavaScript

    枚举所有类

    setTimeout(function (){
      Java.perform(function (){
        console.log("
    [*] enumerating classes...");
        Java.enumerateLoadedClasses({
          onMatch: function(_className){
            console.log("[*] found instance of '"+_className+"'");
          },
          onComplete: function(){
            console.log("[*] class enuemration complete");
          }
        });
      });
    });
     
    JavaScript

    Hook 构造对象(自定义参数)

    参数是一个自定义类

    类是这样的

    Java.perform(function () {
        var money = Java.use('com.xx.app.Money')  // 如果要自定义实例化就要获取并重写
        var utils = Java.use('com.xx.app.Utils');
        utils.test.overload("com.xx.app.Money").implementation = function (obj) {
            console.log("参数自定义类Hook中...");
            // 重新实例化  $new()
            var mon = money.$new(999,'我的天')
            send(mon.getInfo());  // 调用 这个对象的 getInfo 
            return mon.getInfo();  // 根据需求return
        }
    });
     
    JavaScript

    Hook interface 接口类

    目前在app逆向中遇到interface搜索其实现还是一顿乱搜。
    可以使用反射得到实现的接口数组,然后打印出来即可,这个问题终于可以解决了。

    Hook 构造函数

    类的内部如下

    Java.perform(function () {
        var Money = Java.use('com.xx.xx.xx');
        Money.$init.implementation = function (a, b) {
            console.log("构造函数Hook中...");
            send(a);
            send(b);
            send("Success!");
            return this.$init(a, b);
        }
    });
     
    JavaScript

    解析:

    • $init 构造函数 和 python语法类似
    • this.$init(a, b) 这里的 this 指代,原始app中的函数,$init() 表示该类的实例化

    Hook 数组(char 和 byte)

    有很多方法我这里直接用 gson.dex 方法,再肉丝的星球中下载

    打印 CharArray 和 byteArray

    Java.perform(function () {
        // 调用 自写dex
        Java.openClassFile("/data/local/tmp/r0gson.dex").load();
        const gson = Java.use('com.r0ysue.gson.Gson');
    
        // CharArray
        Java.use("java.util.Arrays").toString.overload('[C').implementation = function(charArray){
            var result = this.toString(charArray);
            console.log("charArray,result:",charArray,result)
            console.log("charArray Object Object:",gson.$new().toJson(charArray));
            return result;
        }
    
        // byteArray
        Java.use("java.util.Arrays").toString.overload('[B').implementation = function(byteArray){
            var result = this.toString(byteArray);
            console.log("byteArray,result):",byteArray,result)
            console.log("byteArray Object Object:",gson.$new().toJson(byteArray));
            return result;
        }
    });
     
    JavaScript

    生成数组替换结果

    java代码和上面例子相同

    Java.perform(function () {
        // 调用 自写dex
        Java.openClassFile("/data/local/tmp/r0gson.dex").load();
        const gson = Java.use('com.r0ysue.gson.Gson');
    
        // CharArray 替换
        Java.use("java.util.Arrays").toString.overload('[C').implementation = function(charArray){
            var newCharArray = Java.array('char', [ '一','去','二','三','里' ]);
            var result = this.toString(newCharArray);
            console.log("newCharArray,result:",newCharArray,result)
            
            // 利用 gson.dex 来修改
            console.log("newCharArray Object Object:",gson.$new().toJson(newCharArray));
            
            // 官方api方法
            var newResult = Java.use('java.lang.String').$new(Java.array('char', [ '烟','村','四','五','家']))
            return newResult;
        }
    
    });
     
    JavaScript

    Hook 重载方法

    例两个同名的函数。给多少个参数,调用有多少参数的对应方法 必须使用 overload()方法!!!

    • function test(a)
    • function test(a,b,c)

    解决方法 overload() 指定

    • 如果是一个 int 类型的参数那么 overload("int") 要指定参数与类型
    • 如果是 string 类型 overload("java.lang.String") 全路径
    var Utils = Java.use('com.xx.app.Utils');
    Utils.test.overload("int").implementation = function () {
        console.log("重写方法Hook中...");
        send("重写方法 Success!");
        return this.test(55555555);
    }
     
    Python

    Hook 类中的类

    com.xxx.xxx.xxx.xxx$InnerClasses

    利用符号 $ 来操作

    Hook 被混淆的函数名

    有的代码混淆,函数名已经是乱码符号

    // 比如说这
    int ֏(int x) {
        return x + 100;
    }
     
    Java

    甚至有一些不可视, 所以可以先编码打印出来, 再用编码后的字符串去 hook.

    Java.perform(
        function x() {
    
            var targetClass = "com.example.hooktest.MainActivity";
    
            var hookCls = Java.use(targetClass);
            var methods = hookCls.class.getDeclaredMethods();
    
            for (var i in methods) {
                console.log(methods[i].toString());
                console.log(encodeURIComponent(methods[i].toString().replace(/^.*?.([^s.()]+)(.*?$/, "$1")));
            }
    
            hookCls[decodeURIComponent("%D6%8F")]
                .implementation = function (x) {
                    console.log("original call: fun(" + x + ")");
                    var result = this[decodeURIComponent("%D6%8F")](900);
                    return result;
                }
        }
    )
     
    JavaScript

    Hook 函数的参数为 map 等特殊类型

    Java.perform(function () {
        /*
        var ShufferMap = Java.use('com.xx.xx.ShufferMap');
        ShufferMap.show.implementation = function (map) {
            
            var result = "";
            var keyset = map.keySet(); // 
            var it = keyset.iterator();
            while(it.hasNext()){
                var keystr = it.next().toString();
                var valuestr = map.get(keystr).toString();
                result += valuestr;
            }
            send(result);
            return this.show(map);
        }
        */
        var HashMap = Java.use('java.util.HashMap');
        var ShufferMap = Java.use('com.xx.app.ShufferMap');
        ShufferMap.show.implementation = function (map) {
            var hm = HashMap.$new();
            hm.put("user","dajianbang");
            hm.put("pass","87654321");
            hm.put("code","123456");
            return this.show(hm);
        }
    });
     
    JavaScript

    方法2

    Java.perform(function(){
        var ShufferMap = Java.use("com.xx.app.ShufferMap");
        console.log(ShufferMap);
        ShufferMap.show.implementation = function(map){
            console.log(JSON.stringify(map));
            //Java map的遍历
            // var key = map.keySet();
            // var it = key.iterator();
            // var result = "";
            // while(it.hasNext()){
            //     var keystr = it.next();
            //     var valuestr = map.get(keystr);
            //     result += valuestr;
            // }
            // console.log(result);
            // return result;
    
            map.put("pass", "wawa");
            map.put("guanwang", "666");
    
            var retval = this.show(map);
            console.log(retval);
            return retval;
    
        }
    });
     
    Java

    Hook 动态加载的 dex

    先枚举到类, 然后利用Java.classFactory.loader = loader; 切换 classloader

    // 先枚举到类, 然后利用Java.classFactory.loader = loader; 切换 classloader
     Java.perform(function () {
            //hook 动态加载的dex
            Java.enumerateClassLoaders({  // 枚举当前加载的 Java VM类加载器
                onMatch: function (loader) {
                    try {
                        if (loader.findClass("com.example.androiddemo.Dynamic.DynamicCheck")) {
                            console.log(loader);
                            Java.classFactory.loader = loader;      //切换 classloader, 切换好了就可以正常hook了
                        }
                    } catch (error) {
                    }
                }, onComplete: function () {
                }
            });
     
            var DynamicCheck = Java.use("com.example.androiddemo.Dynamic.DynamicCheck");
            console.log(DynamicCheck);
            DynamicCheck.check.implementation = function () {
                console.log("DynamicCheck.check");
                return true;
            }
        });
     
    JavaScript

    Hook 找不到包名的类

    我们要hook类似这种代码的时候,找不到引用包,我们可以通过查看 smali 代码来看到她的引用

    输出调用栈

    function showStacks() {
        send('调用栈输出
    	' + Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
    }
     
    Java

    调用外部 dex

    dex 中变量名尽量取得特殊一点,防止重名。

    使用案例 再上面《Hook 数组(char 和 byte)》 中就有引用肉丝的 dex 例子

    手动注册类

    frida 用 registerClass 自己构造一个类

    Java.perform(function(){
        var liquid = Java.use("com.xx.xx.xx");
        var beer = Java.registerClass({
        name: 'com.xx.xx.xx',
        implements: [liquid],
        methods: {
            flow: function () {
                return "look, beer is flowing!";
            }
        }
        });
        console.log("beer.bubble:",beer.$new().flow())      
    })
  • 相关阅读:
    Python:Day02
    Python:Day01
    学习Python的第二天
    学习Python的第一天
    MySQL插入中文数据乱码问题
    MySQL数据库应用(11)DML之表和字段
    MySQL数据库应用(10)DML之修改表中的记录
    MySQL数据实战(初步增量恢复)
    MySQL数据库应用(9)DQL之select知识
    MySQL数据库应用(8)DML语句之insert知识
  • 原文地址:https://www.cnblogs.com/coffee520/p/14734353.html
Copyright © 2020-2023  润新知