首页
论坛
专栏
课程

[原创]介召几个frida在安卓逆向中使用的脚本以及延时Hook手法

lykseek 2019-1-7 17:34 1590

0x00 frida简介

   frida是近几年才推出的一款全平台的逆向神器。功能上主要采用动态hook的方式,加入log,修改逻辑等。可以对java,native等hook。

   具体使用情况,谁用谁知道。废话不多说,直接上干货。

   这里仅仅讨论安卓上面的情况,其他平台的咱不做研究

0x01 在java中的一些应用

    1、延时Hook
        安卓有一些多包的问题,另外有一些类是通过动态加载的方式来加载的。可能在hook触发的那个时间点,不会找到未加载的代码。
        这个时候,可以通过在class loader上面加hook的方式,在hook的代码下进行二次绑定加载。
       这里没有代码,需要各位同学自己尝试一下。
    2、打印调用栈
       调用栈,这个很有用。在分析的过程中,不一定会一定找到需要分析或者hook的函数。可能根据字符串等蛛丝马迹,仅仅找到一部分信息。
    使用java调用栈,就可以找到方法的调用关系。
      代码如下
      
Java.perform(function () {                                      
   var thread = Java.use('java.lang.Thread');
   var instance = thread.$new();

   function where(stack){
   	var at = ""
   	for (var i = 0; i < stack.length; i++){
   		at += stack[i].toString() + "\n";
   	}

   	return at;
   }

   var ConnectionErrorMessages = Java.use("com.google.android.gms.common.internal.ConnectionErrorMessages");
   ConnectionErrorMessages.getErrorMessage.overload('android.content.Context','int').implementation = function(mContext,mI){

   		console.log("gms i:"+ mI);

   		var ret = this.getErrorMessage(mContext,mI);

   		console.log("return:" + ret);

   		var stack = instance.currentThread().getStackTrace();
   		var full_call_stack = where(stack);

   		console.log(full_call_stack);

   		return ret;
   };
});   
如上所示,可以把所用调用了ConnectionErrorMessages.getErrorMessage这个方法的栈给打印出来。
3、关于java的重载 
  这个载frida中设计比较友好,如果不知道重载方法如何写。只需要写上方法名,运行一次,frida就会把所有的方法,通过错误日志的形式给打印出来。照抄即可。
  
    // overload 是用于定位hook哪一个方法的

    .overload()
    .overload('java.lang.String')
    .overload('android.app.Activity')
    .overload('int')
    .overload('[B') // byte array
    .overload('float')
    .overload('android.content.Context')
    .overload('[C')
    .overload('android.content.Context', 'android.view.View')
    .overload('android.app.Activity', 'com.cherrypicks.hsbcpayme.model.object.PayMeNotification')
    .overload('android.content.Context', 'boolean')
    .overload('android.content.Context', 'int')
    .overload('android.content.Context', 'java.lang.String')
    .overload('android.app.Activity', 'int')
    .overload('java.lang.String', 'java.lang.String')
    .overload('android.content.Context', 'android.graphics.Bitmap')
    .overload('java.lang.String', 'java.io.File')
    .overload('android.content.Context', 'java.lang.String', 'java.util.List')
    .overload('java.lang.String', 'java.lang.String', 'java.lang.String')
    .overload('java.lang.String', '[B', '[B')
    .overload('java.lang.String', 'java.lang.String', 'android.content.Context')
    .overload('android.app.Activity', 'com.cherrypicks.hsbcpayme.model.object.PayMeNotification', 'int')
    .overload('[B', '[B', '[B')
    .overload('android.content.Context', 'java.lang.String', 'java.lang.String')
    .overload('android.app.Activity', 'int', 'int', 'int', 'boolean')


// 一个列子
Java.perform(function () { 
    var AssetManager = Java.use("android.content.res.AssetManager");
    var FileInputStream = Java.use("java.io.FileInputStream");
    AssetManager.open.overload("java.lang.String").implementation = function(str) {
        send("hook asset")
        if(str.endsWith(".xxx")){
            return FileInputStream.$new("/data/local/tmp/xxxxx");
        }
        return this.open(str)
    }
});
  如上图所示,就是AssetManager 的 open方法的各种方法。

0x02 在C语言中的Hook

   1、同样的延时Hook 
      这里的Hook可以绑定到程序启动时,这个时候可以针对脱壳以及一些其他只有在启动时才会触发的逻辑起作用。如下面的代码所示,可以先把hook的代码,放在libc.so 的open方法上面,等到指定的so加载的时刻,在触发自需要hook的逻辑。
      
function hookopen(){
	var openPtr = Module.findExportByName("libcrypt-lib.so", ".open");
	console.log("openPtr:",JSON.stringify(openPtr));
}

function hookfopen(){
	var fopenPtr = Module.findExportByName("libcrypt-lib.so", ".fopen");
	console.log("fopenPtr:",JSON.stringify(fopenPtr));
}


function hookOpen(){
	var openPtr = Module.findExportByName("libc.so", "open");
	var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
	Interceptor.replace(openPtr, new NativeCallback(function (pathPtr, flags) {
    var path = Memory.readUtf8String(pathPtr);
    console.log("Opening '" + path + "'");
    var fd = open(pathPtr, flags);
    console.log("Got fd: " + fd);
    return fd;
}, 'int', ['pointer', 'int']));
}


var libc=Module.findExportByName(null,"dlopen");
var find = 0;
Interceptor.attach(libc,{
		
		onEnter: function(args) {

			hookOpen();

			var addr = args[0];
			var str = Memory.readCString(addr);
	        // console.log("dlopen ",str);
	        if (str.indexOf("libcrypt-lib.so") > 0){
	        	find = 1;
	        }else{
	        	find = 0;
	        }
	    },
	    onLeave:function(retval){
	    	if (find > 0){	    	

	    	}
	    }
});借宿把
   2、C语言中打印调用关系
     c中可以打印到该方法,是由那个so调用的。如open函数,在这里就可以知道是由那个so调用了,然后打印出该so具体的打开了那几个文件。根据打开的文件,进而可以猜测出使用了那些设备的信息以及一些其他操作。
  关键的打印调用 就是这一行代码:Thread.backtrace
     
var openFile = new File("/sdcard/openFile.txt","a+");
function hookOpen(){
	var openPtr = Module.findExportByName("libc.so", "open");
	var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
	Interceptor.replace(openPtr, new NativeCallback(function (pathPtr, flags) {
    var path = Memory.readUtf8String(pathPtr);

    var fd = open(pathPtr, flags);
    // console.log("Got fd: " + fd);

    var trace = Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n");
    if (trace.indexOf("libcrypt-lib.so") > 0){
    	console.log("trace:"+trace);
    	console.log("Opening '" + path + "'");

    	openFile.write(path+"\n");
    	openFile.flush();
	}

    return fd;
}, 'int', ['pointer', 'int']));
}

0x03 结语

   如果纰漏,请各位同学加以指出。
   最后放上脚本的git地址  https://github.com/lykmoon/frida-tools.git


[推荐]看雪企服平台,提供APP等级保护加固等安全服务!

最新回复 (9)
misskings 2019-1-7 21:54
2

1

最近也是在用frida来hook。但是只是简单的运用。感觉这样的js好陌生。没用过Module、Memory这些的。我想问下。这样的js运用的基础要去查什么用法啊?我查到的都是控制html相关的。
情迁 2019-1-8 09:18
3

1

牛逼
情迁 2019-1-8 09:19
4

1

破解门槛又降低了,哈哈哈
dou逗你玩 2019-1-8 17:51
5

1

var Log = Java.use("android.util.Log");
var Throwable = Java.use("java.lang.Throwable");
console.log(Log.getStackTraceString(Throwable.$new()));
打堆栈不用那么麻烦,这样就行了
雅鸦歌 2019-1-9 11:53
6

1

var trace = Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress);
var offaddr = trace[0]; 
var offaddr1 = offaddr - 基址;
console.log("地址|" + offaddr1.toString(16));
直接打印就好

deadxing 2019-1-9 15:57
7

1

月莫
葫芦娃 1 2019-1-9 16:15
8

1

dou逗你玩 var&nbsp;Log&nbsp;=&nbsp;Java.use("android.util.Log"); var&nbsp;Throwable ...
你这打的是虚拟机的堆栈,不是一个东西
Fido 2019-1-9 16:15
9

1

对art支持如何了?
SevenSir 1 6天前
10

0

misskings 最近也是在用frida来hook。但是只是简单的运用。感觉这样的js好陌生。没用过Module、Memory这些的。我想问下。这样的js运用的基础要去查什么用法啊?我查到的都是控制html相关的。
当然是去frida官网看帮助文档啊,然后结合JavaScript的的相关API来做处理。有必要时Frida还支持Python和JavaScript之间的通讯。用过最好的框架也应该是目前最流行的的吧。
返回