Reber's Blog

只会一点点编程、只会一点点渗透


使用 Hook 框架 frida 进行调试

0x00 frida

1、手机端安装一个 server 程序
2、然后把手机端的端口转到 PC 端
3、PC 端写 js 脚本进行通信

frida -U -f com.package.name -l exploit.js

function hook() {
  console.log("[*] Starting script")
    
  Java.perform(function () {
    var <class_reference> = Java.use("<package_name>.<class>");
    <class_reference>.<method>.implementation = function(<args>) {
      console.log("hook <class_reference>.<method>()")
      console.log("args is:", args)
      
      var ret = this.<method_to_hook>(args);
      return ret
    }
  })
}

0x01 JAVA 层 - 直接调用函数

  • 调用静态函数

    package com.example.test.ui.test;
    
    public class TestFrida {
        public static String staticFunc(boolean isOk) {
            if (isOk){
                return "flag{sdfjwiejflkjf}";
            } else {
                return "nonono";
            }
        }
    }
    
    function hook_static_func() {
      console.log("[*] Starting script")
    
      Java.perform(function () {
        var TestFrida = Java.use("com.example.test.ui.test.TestFrida")
        var str = TestFrida.staticFunc(true)
        console.log(str)
      })
    }
    
  • 调用非静态函数

     package com.example.test.ui.test;
    
     public class TestFrida {
         public String noStaticFunc(boolean isOk){
             if (isOk){
                 return "flag{orjkwjflkjd}";
             } else {
                 return "nonono";
             }
         }
     }
    
    function hook_no_static_func() {
      console.log("[*] Starting script")
    
      Java.perform(function () {
        var TestFrida = Java.use("com.example.test.ui.test.TestFrida")
        var testFrida = TestFrida.$new();
        var str = testFrida.noStaticFunc(true);
        console.log(str)
      })
    }
    

0x02 JAVA 层 - hook 一般函数

  • hook 函数返回值

    package com.example.test.ui.test;
    
    public static String checkState(boolean state) {
        if (state) {
            return "flag !!!";
        } else {
            return "nonono";
        }
    }
    
    function hook_func_return() {
      console.log("[*] Starting script")
    
      Java.perform(function () {
        var TestFrida = Java.use("com.example.test.ui.test.TestFrida")
        TestFrida.checkState.implementation = function(arg) {
          console.log("hook TestFrida.checkState()")
    
          return "flag"
        }
      })
    }
    
  • hook 函数的参数

    package com.example.test.ui.test;
    
    public class Use {
        public static void testReturn(Context context, boolean state) {
            String msg = checkState(state);
            Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
        }
    
        public static String checkState(boolean state) {
            if (state) {
                return "flag !!!";
            } else {
                return "nonono";
            }
        }
    }
    

    调用 TestFrida.testReturn(requireContext(), false);

    function hook_func_arg() {
      console.log("[*] Starting script")
    
      Java.perform(function () {
        var TestFrida = Java.use("com.example.test.ui.test.TestFrida")
        TestFrida.checkState.implementation = function(arg) {
          console.log("hook TestFrida.checkState()")
          console.log("arg is:", arg)
    
          arg = true
    
          var ret = this.checkState(arg);
          return ret
        }
      })
    }
    

0x03 JAVA 层 - hook 内部类的函数

  • hook 类内静态变量
    package com.example.test.ui.test;
    
    public class TestFrida {
        static class InnerClass {
            public String innerFunc(String msg) {
                return msg;
            }
        }
    
        public static String useInnerFunc() {
            InnerClass inner = new InnerClass();
            return inner.innerFunc("this is useInnerFunc()");
        }
    }
    
    function hook_inner_class() {
      console.log("[*] Starting script")
    
      Java.perform(function () {
        var InnerClass = Java.use("com.example.test.ui.test.TestFrida$InnerClass")
        InnerClass.innerFunc.implementation = function(){
          var ret = this.innerFunc("test msg")
          return ret
        }
      })
    }
    

0x04 JAVA 层 - hook 重载函数

  • hook 重载函数
    package com.example.test.ui.test;
    
    public class TestFrida {
        public static void testArg(Context context, String a) {
            Toast.makeText(context, a, Toast.LENGTH_SHORT).show();
        }
    
        public static void testArg(Context context, String a, String b) {
            Toast.makeText(context, a+","+b, Toast.LENGTH_SHORT).show();
        }
    }
    
    调用 TestFrida.testArg(context, "aaa", "bbb"); 使用 overload 来 hook 两个参数的那个 testArg()
    function hook_class_static_variables() {
      console.log("[*] Starting script")
    
      Java.perform(function () {
        var TestFrida = Java.use("com.example.test.ui.test.TestFrida")
        TestFrida.testArg.overload(
          "android.content.Context", "java.lang.String", "java.lang.String"
        ).implementation = function(context, arg1, arg2) {
          console.log("hook TestFrida.testArg(String a, String b)")
          console.log("arg is:", context, arg1, arg2)
    
    
          var ret = this.testArg(context, arg1, arg2);
          return ret
        }
      })
    }
    

0x05 JAVA 层 - hook 构造函数

  • hook 构造函数

    package com.example.test.ui.test;
    
    public class TestFrida {
        int num = 0;
    
        public TestFrida(int num) {
            this.num = num;
        }
    
        public static String test() {
            if (this.num > 10) {
                return "flag !!!";
            } else {
                return "nonono";
            }
        }
    }
    

    调用的函数

    public static void ttt(Context context) {
        TestFrida testFrida = new TestFrida(5);
        String msg = testFrida.test();
        Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show();
    }
    
    function hook_init() {
      console.log("[*] Starting script")
    
      Java.perform(function () {
        var TestFrida = Java.use("com.example.test.ui.test.TestFrida")
        TestFrida.$init.implementation = function (arg){
            console.log("arg is: ", arg);
            this.$init(20);
    
            console.log(this.test()) // flag !!!
        }
      })
    }
    

0x06 JAVA 层 - hook 静态变量

  • hook 类内静态变量
    package com.example.test.ui.test;
    
    public class TestFrida {
        private static String msg="ccc";
        public static void testReturn(Context context, boolean state) {
            Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
        }
    }
    
    function hook_class_static_variables() {
      console.log("[*] Starting script")
    
      Java.perform(function () {
        var TestFrida = Java.use("com.example.test.ui.test.TestFrida")
    
        console.log("hook TestFrida.msg")
        TestFrida.msg.value = "new value"
      })
    }
    

0x07 JAVA 层 - MainActivity 中的函数

  • 调用 MainActivity 中的函数 直接调用 MainActivity 中的函数时会出现:Error: java.lang.ClassNotFoundException 因为安卓组件(如 Activity)的子类依赖于应用程序上下文运行,而 Frida 中没有必要的上下文

    public class MainActivity extends AppCompatActivity {
        public String test1() {
            return "call function MainActivity.test()";
        }
    
        public static String test2() {
            return "call static function MainActivity.test1()";
        }
    }
    
    function hook_main_activity_func() {
      console.log("[*] Starting script")
    
      Java.performNow(function() {
        Java.choose('com.example.test.MainActivity', {
          onMatch: function(MainActivity) {
            var str1 = MainActivity.test1()
            console.log(str1)
            // call function MainActivity.test1()
    
            var str2 = MainActivity.test2()
            console.log(str2)
            // call static function MainActivity.test2()
          },
          onComplete: function() {}
        });
      });
    }
    

0x08 NATIVE 层

  • 改 strlen
    setImmediate(function() {
      Interceptor.attach(Module.findExportByName("libc.so", "strlen"), {
        onEnter: function(args) {
          console.log(Memory.readUtf8String(args[0]))
        },
        onLeave: function(retval) {
          console.log(retval)
          return this.retval
        }
      });
    })
    

参考资料