三 常用API 
1.JAVA 
(1)Java.perform(fn) 
frida的main,注意:所有的脚本必须放在这里面,示例:

Java.perform(function () {                                                                                     
    var Activity = Java.use(“android.app.Activity”);//获得类包相当于js的new()                                                       
    Activity.onResume.implementation = function () {//改变onResume函数      
            send("onResume() got called! Let's call the original implementation”);                              
         this.onResume();                                           
    };                                                      
});                         

(2)Java.use(className) 
动态获取一个类的对象,为以后改变对象方法的实现,或者用new()实例化对象,new()实例化对象,dispose()销毁对象,示例:

Java.perform(function () {                                      
    var Activity = Java.use("android.app.Activity");                        
    var Exception = Java.use("java.lang.Exception");                        
    Activity.onResume.implementation = function () {                        
        throw Exception.$new(“Hello World!");                          
    };                                                      
});                                                     

(3)Java.enumerateLoadedClasses(callbacks) 
列出当前已经加载的类,用回调函数处理 
回调函数onMatch:function(className){ } 
找到加载的每个类的时候被调用,参数就是类的名字,这个参数可以传给java.use()来获得一个js类包 
回调函数onComplete: function () 
列出所有类之后被调用 
2.JavaScript 
(1)Interceptor.attach(target, callbacks) 
在target指定的位置进行函数调用拦截,target是一个NativePointer参数,用来指定你想要拦截的函数的地址。callbacks参数是一个对象: 
onEnter: function(args): 被拦截函数调用之前回调,其中原始函数的 参数使用args数组(NativePointer对象数组)来表示,可以在这里修改函数的调用参数。 
onLeave: function(retval): 被拦截函数调用之后回调,其中retval表示原始函数的返回值,retval是从NativePointer继承来的,是对原始返回值的一个封装,可以使用retval.replace(1337)调用来修改返回值的内容。注意:retval对象只在 onLeave函数作用域范围内有效,因此如果你要保存这个对象以备后续使用的话,一定要使用深拷贝来保存对象,比如:ptr(retval.toString()) 
示例:

Interceptor.attach(Module.findExportByName(“libc.so”,”read”),{              
    onEnter:function(args){                                     
        this.fileDescriptor = args[0].toInt32();                        
    },                                                  
    onLeave:function(retval){                                   
        if(retval.toInt32( ) > 0){                                  
            /* do something with this.fileDescriptor */             
        }                                               
    }                                                   
});                                     

此外,this 对象还包含了一些额外的比较有用的属性:

returnAddress: 返回NativePointer类型的 address 对象
context: 包含 pc,sp,以及相关寄存器比如 eax, ebx等,可以在回调函数中直接修改
errno: (UNIX)当前线程的错误值
lastError: (Windows) 当前线程的错误值
threadId: 操作系统线程Id
depth: 函数调用层次深度

(2)Interceptor.detachAll() 
取消之前所有的拦截调用 
(3)Interceptor.replace(target, replacement): 
函数实现代码替换,注意:这种情况主要用于想要完全替换掉一个原有函数的实现,replacement参数使用JavaScript形式的一个NativeCallback来实现,后续如果想要取消这个替换效果,可以使用 Interceptor.revert调用来实现

以上转自:https://blog.csdn.net/qingemengyue/article/details/80061491

精选 教程:

1、https://www.cnblogs.com/qwangxiao/p/9255328.html

 

2、https://bbs.pediy.com/thread-248848.htm

 

更多使用,可以官网查阅。一定要多编写、多练习

https://www.frida.re/docs/javascript-api/

import frida
import sys
import io
import os

device = frida.get_usb_device()

pid = device.spawn(["com.example.seccon2015.rock_paper_scissors"])
session = device.attach(pid)


#hook native 函数
src = """
function str2ArrayBuffer(str){
    var buf = new ArrayBuffer(str.length);
    var uit8Array = new Uint8Array(buf);
    for(var i = 0, len = str.length; i < len; i++){
        uit8Array[i] = str.charCodeAt(i);
    }
    return buf;
}
var openPtr = Module.findExportByName("libc.so", "open");
Interceptor.attach(openPtr, {
     onEnter : function(args){
         var pathPtr = args[0];
         var pathstring = pathPtr.readUtf8String();
         var arrayBuffer = str2ArrayBuffer(pathstring);
         //pathPtr.writeUtf8String("122");
         //send("open called ! path=" + pathPtr.readUtf8String());
         send("水电费收费open called ! ", Memory.readByteArray(args[0], 256));
         //send("水电费收费open called ! ", arrayBuffer);
     },
     onLeave : function(retval){
         //send("open leave.....");
     }
});
"""
#hook java 函数
src_java = """
Java.perform(function(){
    var application = Java.use("android.app.Activity");
    send("application=" + application);
    application.onCreate.overload("android.os.Bundle").implementation = function(bundle){
        console.log("application onCreate called !");
        //send(" onCreate called !.....");
        this.onCreate(bundle); 
    }
    application.onResume.implementation = function(){
         send(" onResume called !.....");
         this.onResume(); 
    }
});

"""

src_java_application = """
Java.perform(function(){
    var ApplicationInfo = Java.use("android.content.pm.ApplicationInfo");
    var application = Java.use("android.app.Application");
    send("application=" + application + ",ApplicationInfo=" + ApplicationInfo );
    application.onCreate.implementation = function(){
        var applicationInfo = Java.cast(this.getApplicationInfo(), ApplicationInfo);
        //var className = Java.cast(this.applicationInfo.className, JavaString);
        console.log("application onCreate called !packageName=" + this.getPackageName() + "," + this.getApplicationInfo().$className("className")
        + "," + this.mLoadedApk);       
        this.onCreate(); 
    }
  
});

"""

src_java_baseClassLoader = """
Java.perform(function(){
    if(0){
        var dexclassLoader = Java.use("dalvik.system.DexClassLoader");
        console.log("dexclassLoader=" + dexclassLoader); 
        dexclassLoader.$init.implementation = function(dexPath,  optimizedDirectory,  librarySearchPath,  parent){
            console.log("dexPath=" + dexPath );
            console.log("optimizedDirectory=" + optimizedDirectory);
            console.log("librarySearchPath=" + librarySearchPath);
            console.log("parent=" + parent);
            this.$init(dexPath, optimizedDirectory,  librarySearchPath,  parent);
        }
    }
    
    if(0){
       var index = 0;
       var dexclassLoader = Java.use("dalvik.system.BaseDexClassLoader");
        console.log("dexclassLoader=" + dexclassLoader); 
        dexclassLoader.$init.overload("java.lang.String", "java.io.File", "java.lang.String", "java.lang.ClassLoader").implementation = function(dexPath,  optimizedDirectory,  librarySearchPath,  parent){
           console.log( ++index +"、--------------------------");
            console.log("dexPath=" + dexPath );
            console.log("optimizedDirectory=" + optimizedDirectory);
            console.log("librarySearchPath=" + librarySearchPath);
            console.log("parent=" + parent);           
            this.$init(dexPath, optimizedDirectory,  librarySearchPath,  parent);
        }
        dexclassLoader.$init.overload("[Ljava.nio.ByteBuffer;", "java.lang.ClassLoader").implementation = function(byteBuffer,   parent){
            console.log(++index +"、--------------------------");
            console.log("byteBuffer=" + byteBuffer );           
            console.log("parent=" + parent);            
            this.$init(byteBuffer, parent);
        }
    }
    
    if(1){
         var dexclassLoader = Java.use("dalvik.system.BaseDexClassLoader");
         var ClassUse = Java.use("java.lang.Class");
         dexclassLoader.loadClass.overload("java.lang.String").implementation = function(className){
             console.log("className=" + className);
             var result = this.loadClass(className);
             var resultCast = Java.cast(result, ClassUse);
             console.log("methods=" + resultCast.getMethods());
             return result;
         }
    }
});

"""



log_path = "e://log.txt"

#message["payload"] message为map,取出key payload 的value
def on_message(message, data):
    print(message)
    
def on_byte_message(message, data):
    if(1):
        line_bytes =  data.split(b'\x00')[0]        
    else:
        line_bytes = data        
    print(str(line_bytes, "utf8"))                   
    file = open(log_path, "ab+")
    file.write(message["payload"].encode())
    file.write(line_bytes)
    file.write("\n".encode())
    file.close()
        
if(os.path.exists(log_path)):
      os.remove(log_path)    
            
script = session.create_script(src_java_baseClassLoader)
#设置message 回调函数为 on_message。js 调用send 就会发到 on_message
#script.on("message", on_byte_message)
script.on("message", on_message)
script.load()
device.resume(pid)
sys.stdin.read()
            

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐