【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
原文地址:https://www.cnblogs.com/du-jun/p/14303380.html