• 【Frida Hook 学习记录】Frida Hook Android 常用方法


    1 概述

    在逆向过程中,Frida是非常常用的Hook工具,这个工具在日常使用的过程中,有很多通用方法,这里记录一下,方便查阅,部分函数使用的时候,可能需要稍微修改一下,本文记录是Android的方法,不涉及其他的
    主要是搬迁的一下参考文章的片段
    Android逆向之旅—Hook神器家族的Frida工具使用详解
    Frida官方文档
    看雪 Frida官方手册 - JavaScript API(篇一)
    看雪 Frida官方手册 - JavaScript API(篇二)
    Js中几种String Byte转换方法
    Frida learn by example
    补充一个参考文章–Hook 属性

    2 启动方式

    2.1 使用js脚本启动

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

    其中js脚本的写作方式如下

    setImmediate(function() { //prevent timeout
        console.log("[*] Starting script");
    
        Java.perform(function() {
          myClass = Java.use("com.package.name.xxActivity");
          myClass.implementation = function(v) {
             // do sth.
          }
    
        })
    })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.2 使用python脚本启动

    import frida, sys
    
    def on_message(message, data):
        if message['type'] == 'send':
            print("[*] {0}".format(message['payload']))
        else:
            print(message)
    
    jscode = """
    Java.perform(function () {
        // Function to hook is defined here
        var MainActivity = Java.use('com.example.hook.MainActivity');
        // hook method is setString
        MainActivity.setString.implementation = function (str) {
            // Show a message to know that the function got called
            send('hook success');
            console.log('string is: ' + str));
        };
    });
    """
    
    process = frida.get_usb_device().attach('com.example.hook')
    #pid = device.spawn(["com.android.chrome"])
    #session = device.attach(pid)
    #device.resume(pid)
    script = process.create_script(jscode)
    script.on('message', on_message)
    print('[*] Hook Start Running')
    script.load()
    sys.stdin.read()
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    3 Android 常用Hook方法汇总

    3.1 Hook 一般函数—使用implementation

    var MainActivity = Java.use('ese.xposedtest.MainActivity');
    //外部类 修改返回值
    MainActivity.OutClass.implementation = function (arg) {
        var ret = this.OutClass(arg);
        console.log('Done:' + arg);
        return ret;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.2 Hook 重载函数—使用overload

    // If two methods of a class have the same name
    // you need to use 'overload'
    // hook method 1
    myClass.myMethod.overload().implementation = function(){
      // do sth
    }
    
    myClass.myMethod.overload("[B", "[B").implementation = function(param1, param2) {
      // do sth
    }
    
    myClass.myMethod.overload("android.context.Context", "boolean").implementation = function(param1, param2){
      // do sth
    }
    
    // hook method 2
    //待补充
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3.3 Hook 构造函数—使用$init

    // Intercept the initialization of java.lang.Stringbuilder's overloaded constructor.
    // Write the partial argument to the console.
    const StringBuilder = Java.use('java.lang.StringBuilder');
    //We need to overwrite .$init() instead of .$new(), since .$new() = .alloc() + .init()
    StringBuilder.$init.overload('java.lang.String').implementation = function (arg) {
        var partial = "";
        var result = this.$init(arg);
        if (arg !== null) {
             partial = arg.toString().replace('
    ', '').slice(0,10);
        }
        // console.log('new StringBuilder(java.lang.String); => ' + result)
        console.log('new StringBuilder("' + partial + '");')
        return result;
    }
    console.log('[+] new StringBuilder(java.lang.String) hooked');
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3.4 Hook 生成对象—使用$new

    const JavaString = Java.use('java.lang.String');
    var exampleString1 = JavaString.$new('Hello World, this is an example string in Java.');
    console.log('[+] exampleString1: ' + exampleString1);
    • 1
    • 2
    • 3

    3.5 Hook 内部类—使用$

    var inInnerClass = Java.use('ese.xposedtest.MainActivity$inInnerClass');
    
    inInnerClass.methodInclass.implementation = function()
    {
        var arg0 = arguments[0];
        var arg1 = arguments[1];
        send("params1: "+ arg0 +" params2: " + arg1);
        return this.formInclass(1,"Frida");
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.6 Hook native 函数

    Interceptor.attach(Module.findExportByName("xxx.so" , "xxxx"), {
        onEnter: function(args) {
            send("open(" + Memory.readCString(args[0])+","+args[1]+")");
        },
        onLeave:function(retval){
        
        }
    });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.7 Hook 静态变量(属性)/参考文章中有反射的方法

    var ah = Java.use("com.ah");
    console.log("To Log: " + ah.a.value);
    ah.a.value = true;
    • 1
    • 2
    • 3

    3.8 打印堆栈

    AndroidLog = Java.use("android.util.Log")
    AndroidException = Java.use("java.lang.Exception")
    function printStackTrace(){
    	console.log(AndroidLog .getStackTraceString(AndroidException .$new()));
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    3.9 byte转String

    function byte2string(array){
        var result = "";
        for(var i = 0; i < array.length; ++i){
            result+= (String.fromCharCode(array[i]));
        }
       return result;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.10 字符串转Uint8Array

    function string2byte(str){
      for (var i = 0,arr=[]; i < str.length;i++){
        arr.push(str.charCodeAt(i));
      }
      return new Uint8Array(arr);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.11 int转bytes

    function intTobytes(n) {
      var bytes = [];
      for (var i = 0; i < 2; i++) {
        bytes[i] = n >> (8 - i * 8);
     
      }
      return bytes;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.12 string转ArrayBuffer

    function str2arraybuffer(str) {
      var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
      var bufView = new Uint16Array(buf);
      for (var i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
      }
      return buf;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.13 ArrayBuffer转String

    function ab2str(buf) {
      return String.fromCharCode.apply(null, new Uint8Array(buf));
    }
    • 1
    • 2
    • 3

    3.14 添加时间戳

     console.log(new Date(new Date().getTime())
    • 1

    3.15 byte转Hex

    这个非常常用,因为有些byte是没有办法转成string的,只能转成hex,用来查看
    参考文章

    function byteToHexString(uint8arr) {
      if (!uint8arr) {
        return '';
      }
      
      var hexStr = '';
      for (var i = 0; i < uint8arr.length; i++) {
        var hex = (uint8arr[i] & 0xff).toString(16);
        hex = (hex.length === 1) ? '0' + hex : hex;
        hexStr += hex;
      }
      
      return hexStr.toUpperCase();
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3.16 Hex转byte

    function hexStringToByte(str) {
      if (!str) {
        return new Uint8Array();
      }
      
      var a = [];
      for (var i = 0, len = str.length; i < len; i+=2) {
        a.push(parseInt(str.substr(i,2),16));
      }
      
      return new Uint8Array(a);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    Vue的生命周期(钩子函数)
    Vue.set全局操作
    Vue.extend提供自定义组件的构造器
    Vue.directive自定义指令
    vuejs全局api概念
    v-pre原样输出&&v-once只加载一次
    v-model双向数据绑定
    OpenGL:基本算法
    OpenGL:基本图形绘画二
    OpenGL:基本图形绘画
  • 原文地址:https://www.cnblogs.com/du-jun/p/14303380.html
Copyright © 2020-2023  润新知