|
1、//基础数据类型char
var char= Java.use("java.lang.Class").getPrimitiveClass("char")
2、挂钩dlopen函数
- //第一种方式(针对较老的系统版本)
- var dlopen = Module.findExportByName(null, "dlopen");
- console.log(dlopen);
- if(dlopen != null){
- Interceptor.attach(dlopen,{
- onEnter: function(args){
- var soName = args[0].readCString();
- console.log(soName);
- if(soName.indexOf("libc.so") != -1){
- this.hook = true;
- }
- },
- onLeave: function(retval){
- if(this.hook) {
- dlopentodo();
- };
- }
- });
- }
-
- //第二种方式(针对新系统版本)
- var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
- console.log(android_dlopen_ext);
- if(android_dlopen_ext != null){
- Interceptor.attach(android_dlopen_ext,{
- onEnter: function(args){
- var soName = args[0].readCString();
- console.log(soName);
- if(soName.indexOf("libc.so") != -1){
- this.hook = true;
- }
- },
- onLeave: function(retval){
- if(this.hook) {
- dlopentodo();
- };
- }
- });
- }
- function dlopentodo(){
- //todo ...
- }
复制代码
3、打印java层堆栈
- function show_java_trace(){
- Java.perform(function(){
- var MessageDigest = Java.use("java.security.MessageDigest");
- MessageDigest.digest.overload().implementation = function(){
- //var stack = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
- var stack = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new());
- console.log(stack);
- return this.digest();
- }
- });
- }
复制代码
4、打印Native堆栈
- function show_native_trace(){
- var func = Module.findBaseAddress("libil2cpp.so").add(0x56FCA8);
- Interceptor.attach(func, {
- onEnter: function(args){
- console.log("called from:\n"+
- Thread.backtrace(this.context,Backtracer.ACCURATE)
- .map(DebugSymbol.fromAddress).join("\n"));
- },
- onLeave: function(retval){
-
- }
- });
- }
复制代码
5、挂钩Java中的loadLibrary并打印堆栈
- function hook_library(){
- Java.perform(function() {
- const System = Java.use('java.lang.System');
- const Runtime = Java.use('java.lang.Runtime');
- const VMStack = Java.use('dalvik.system.VMStack');
-
- System.loadLibrary.implementation = function(library) {
- try {
- console.log('System.loadLibrary("' + library + '")');
- console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
- const loaded = Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), library);
- return loaded;
- } catch(ex) {
- console.log(ex);
- }
- };
-
- System.load.implementation = function(library) {
- try {
- console.log('System.load("' + library + '")');
- console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
- const loaded = Runtime.getRuntime().load0(VMStack.getCallingClassLoader(), library);
- return loaded;
- } catch(ex) {
- console.log(ex);
- }
- };
- });
- }
复制代码
6、String转Byte
- function stringToBytes(str) {
- var ch, st, re = [];
- for (var i = 0; i < str.length; i++ ) {
- ch = str.charCodeAt(i);
- st = [];
- do {
- st.push( ch & 0xFF );
- ch = ch >> 8;
- }
- while ( ch );
- re = re.concat( st.reverse() );
- }
- return re;
- }
复制代码
7、hexToBytes
- function hexToBytes(str) {
- var pos = 0;
- var len = str.length;
- if (len % 2 != 0) {
- return null;
- }
- len /= 2;
- var hexA = new Array();
- for (var i = 0; i < len; i++) {
- var s = str.substr(pos, 2);
- var v = parseInt(s, 16);
- hexA.push(v);
- pos += 2;
- }
- return hexA;
- }
复制代码
8、bytes2Hex
- function bytes2Hex(arr) {
- var str = "[";
- for (var i = 0; i < arr.length; i++) {
- var z = parseInt(arr[i]);
- if (z < 0) z = 255 + z;
- var tmp = z.toString(16);
- if (tmp.length == 1) {
- tmp = "0" + tmp;
- }
- str = str + " " + tmp;
- }
- return (str + " ]").toUpperCase();
- }
复制代码
9、ArrayBuffer 转换
- function ab2Hex(buffer) {
- var arr = Array.prototype.map.call(new Uint8Array(buffer), function (x) {return ('00' + x.toString(16)).slice(-2)}).join(" ").toUpperCase();
- return "[" + arr + "]";
- }
-
- function ab2Str(buffer) {
- return String.fromCharCode.apply(null, new Uint8Array(buffer));
- }
复制代码
10、jstring, jbytearray显示
- function jstring2Str(jstring) {
- var ret;
- Java.perform(function() {
- var String = Java.use("java.lang.String");
- ret = Java.cast(jstring, String);
- });
- return ret;
- }
-
- function jbyteArray2Array(jbyteArray) {
- var ret;
- Java.perform(function() {
- var b = Java.use('[B');
- var buffer = Java.cast(jbyteArray, b);
- ret = Java.array('byte', buffer);
- });
- return ret;
- }
复制代码
11、主线程调用
- function RunOnMain(){
- Java.perform(function(){
- var cls_main = null
- //获取Context
- Java.choose("com.lzy.ndk.MainActivity",{
- onMatch:function(clazz){
- cls_main = clazz
- },
- onComplete:function(){}
- })
- //动态注册一个类实现Runnable方法
- var cls_run = Java.registerClass({
- name:"com.lzy.frida.runnable",
- implements:[Java.use("java.lang.Runnable")],
- //创建类成员变量
- fields:{
- description: 'java.lang.String',
- limit: 'int'
- },
- //创建方法以及重载方法的用法
- methods:{
- run:function(){
- Java.use("android.widget.Toast").makeText(cls_main,Java.use("java.lang.String").$new("this is a test Toast"),1).show()
-
- },
- add:[{
- returnType:'java.lang.String',
- argumentTypes:['java.lang.String','java.lang.String'],
- implementation:function(str1,str2){
- return str1+"+++"+str2
- }
- },
- {
- returnType:'java.lang.String',
- argumentTypes:['java.lang.String'],
- implementation:function(str1){
- return str1+"==="
- }
- }
- ]
- }
- })
- //这里的实现主线程调用方法很多,这里举例一种
- //1.随便在MainActivity找一个View,View.post(Runnable)
- cls_main.bt1.value.post(cls_run.$new())
- //2.Activity的方法runOnUiThread()
- cls_main.runOnUiThread(cls_run.$new())
- //3.new Handler(getMainLooper()).post()
- Java.use("android.os.Handler").$new(cls_main.getMainLooper()).post(cls_run.$new())
- //4.Java.scheduleOnMainThread(function(){}) 不推荐,不好用总是出问题
- Java.scheduleOnMainThread(function(){
- console.log(Java.isMainThread())
- })
- })
- }
复制代码
12、批量断点定位调用
- function add_native_break_points(){
-
- // 结合Il2CppDumper使用,用于批量快速下断点,跟踪native函数调用
- // frida -U -f <PackageName> -l C:\Users\lzy\utils\bpoints.js --no-pause
-
- const soName = "libil2cpp.so"
-
- const arrayAddr =
- ['0x71541c', '0x715b38', '0x715be4', '0x715c61']
-
- const arrayName =
- ['GameManager$Awake', 'GameManager$GetParam', 'GameManager$SaveParam', 'GameManager$ActivatePrivacyButton']
-
- function breakPoints(){
-
- const soAddr = Module.findBaseAddress(soName);
- console.error('\nsoAddr:' + soAddr + "\n");
-
- Java.perform(function(){
- arrayAddr
- .map(function(temp){return soAddr.add(temp)})
- .forEach(function(value,index,array){
- console.log("-------------------------");
- console.log('currentAddr:' + value);
- try{
- funcTmp(value,index,arrayName);
- }catch(e){
- //Thumb指令集地址要加一
- funcTmp(value.add(1),soAddr,index,arrayName);
- }
- console.log("\t\t---->"+index,value+" is prepared ");
- })
- console.log("\n")
- })
-
- function funcTmp(currentAddr,index,arrayName){
- Interceptor.attach(currentAddr, {
- onEnter: function(args){
- console.log("called : "+arrayName[index]+" ----- addr : " + currentAddr.sub(soAddr) +"\n");
- this.temp = currentAddr.sub(soAddr);
- if(this.temp === 0xef3080) {
- console.log('CCCryptorCreate called from:\n' +
- Thread.backtrace(this.context, Backtracer.ACCURATE)
- .map(DebugSymbol.fromAddress).join('\n') + '\n');
- }
- },
- onLeave: function(retval){
-
- }
- });
- }
- }
-
- function hook_dlopen() {
- // const dlopen = Module.findExportByName(null, "dlopen");
- const dlopen = Module.findExportByName(null, "android_dlopen_ext");
-
- if (dlopen != null) {
- Interceptor.attach(dlopen, {
- onEnter: function (args) {
- var l_soName = args[0].readCString()
- console.log(l_soName)
- if (l_soName.indexOf(soName) != -1) {
- this.hook = true
- }
- },
- onLeave: function (retval) {
- if (this.hook) {
- console.warn("\nLoaded "+soName + " add break points")
- breakPoints()
- }
- }
- })
- }
- }
-
- setImmediate(hook_dlopen())
- }
复制代码
13、TracerPid fgets 反调试
- var anti_fgets = function () {
- show_log("anti_fgets");
- var fgetsPtr = Module.findExportByName("libc.so", "fgets");
- var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
- Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
- var retval = fgets(buffer, size, fp);
- var bufstr = Memory.readUtf8String(buffer);
- if (bufstr.indexOf("TracerPid:") > -1) {
- Memory.writeUtf8String(buffer, "TracerPid:\t0");
- // dmLogout("tracerpid replaced: " + Memory.readUtf8String(buffer));
- }
- return retval;
- }, 'pointer', ['pointer', 'int', 'pointer']));
- };
复制代码
14、日志打印
- function log(str){
- var threadid = Process.getCurrentThreadId()
- var date = new Date()
- var month = date.getMonth() + 1
- var strDate = date.getDate()
- var hour = date.getHours()
- var Minutes = date.getMinutes()
- var Seconds = date.getSeconds()
- if (month >= 1 && month <= 9) {
- month = "0" + month
- }
- if (strDate >= 0 && strDate <= 9) {
- strDate = "0" + strDate
- }
- if (hour >= 0 && hour <= 9) {
- hour = "0" + hour
- }
- if (Minutes >= 0 && Minutes <= 9) {
- Minutes = "0" + Minutes
- }
- if (Seconds >= 0 && Seconds <= 9) {
- Second = "0" + Seconds
- }
- var currentDate = date.getFullYear() + "-" + month + "-" + strDate
- + " " + hour + ":" + Minutes + ":" + Seconds
- var log = "["+threadid+"][" + currentDate + "] --- " + str
- console.log('\x1b[3' + '6;01' + 'm', log, '\x1b[39;49;00m')
- }
复制代码
15、内存dump so(脱壳upx壳)
- function dump_so(so_name) {
- Java.perform(function () {
- var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
- var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
- var libso = Process.getModuleByName(so_name);
- console.error("------------------------------");
- console.warn("[name]:", libso.name);
- console.warn("[base]:", libso.base);
- console.warn("[size]:", libso.size);
- console.warn("[path]:", libso.path);
- console.error("------------------------------");
- var file_path = dir + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so";
- var file_handle = new File(file_path, "wb");
- if (file_handle && file_handle != null) {
- Memory.protect(ptr(libso.base), libso.size, 'rwx');
- var libso_buffer = ptr(libso.base).readByteArray(libso.size);
- file_handle.write(libso_buffer);
- file_handle.flush();
- file_handle.close();
- console.log("[dump]:", file_path);
- }
- });
- }
复制代码
16、动态加载dex
- function loadDex(){
- //这里只是提一下可以使用Frida提供的Api加载dex,你也可以解包再打包,但是显然这个方便得多
- //手动去加载一些工具类(Gson,AndroidUtilCode,自己写的工具类等等)
- Java.openClassFile("/data/local/tmp/helper.dex").load()
- var gson = Java.use("com.google.gson.Gson").$new()
- ...
- }
复制代码
17、计划任务
- function ScheduledTask(){
- //用在Spawn启动的时候
- setImmediate(function(){
- console.log("立即执行,只执行一次")
- })
- setTimeout(function(){
- console.log("一秒后执行,只执行一次")
- },1000)
- //Frida Api
- setInterval(function(){
- console.log("每隔一秒执行一次")
- },1000)
- // Java Api
- Java.perform(function(){
- Java.registerClass({
- name:"com.lzy.frida.tsk",
- superClass:Java.use("java.util.TimerTask"),
- methods:{
- run:function(){
- console.log("等待两秒后每隔一秒调用一次")
- }
- }
- })
- Java.use("java.util.Timer").$new().schedule(Java.use("com.lzy.frida.tsk").$new(),2000,1000)
- })
- }
复制代码
18、JNI函数Trace Demo
- function TraceJni(){
- Java.perform(function(){
-
- var pSize = Process.pointerSize
- var env = Java.vm.getEnv()
-
- //JNI函数相对env偏移位置参考:
- //https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#NewStringUTF
- var GetStaticMethodID = 113,findclass = 6,RegisterNatives = 215;
-
- function getNativeAddress(idx) {
- return env.handle.readPointer().add(idx * pSize).readPointer()
- }
-
- Interceptor.attach(getNativeAddress(findclass),{
- onEnter:function(args){
- console.error("-------------findClass-------------")
- console.warn("env\t--->\t"+args[0])
- console.warn("class\t--->\t"+args[1].readCString())
- },
- onLeave:function(retval){}
- })
-
- Interceptor.attach(getNativeAddress(GetStaticMethodID),{
- onEnter:function(args){
- console.error("\n-------------GetStaticMethodID-------------")
- console.warn(args[0])
- console.warn(args[1])
- console.warn(args[2].readCString())
- },
- onLeave:function(retval){}
- })
-
- //RegisterNative结构体参照:
- //https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#129
- Interceptor.attach(getNativeAddress(RegisterNatives), {
- onEnter: function(args) {
- console.log(parseInt(args[3]))
- for (var i = 0,nMethods = parseInt(args[3]); i < nMethods; i++) {
- var structSize = pSize * 3; // = sizeof(JNINativeMethod)
- var methodsPtr = ptr(args[2]);
- var signature = methodsPtr.add(i * structSize + pSize).readPointer();
- var fnPtr = methodsPtr.add(i * structSize + (pSize * 2)).readPointer(); // void* fnPtr
- var jClass = jclassAddress2NameMap[args[0]].split('/');
- var methodName = methodsPtr.add(i * structSize).readPointer().readCString();
- console.log('\x1b[3' + '6;01' + 'm', JSON.stringify({
- module: DebugSymbol.fromAddress(fnPtr)['moduleName'],
- // https://www.frida.re/docs/javascript-api/#debugsymbol
- package: jClass.slice(0, -1).join('.'),
- class: jClass[jClass.length - 1],
- method: methodName,
- // methodsPtr.readPointer().readCString(), // char* name
- signature: signature.readCString(),
- // char* signature TODO Java bytecode signature parser { Z: 'boolean', B: 'byte', C: 'char', S: 'short', I: 'int', J: 'long', F: 'float', D: 'double', L: 'fully-qualified-class;', '[': 'array' } https://github.com/skylot/jadx/blob/master/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java
- address: fnPtr
- }), '\x1b[39;49;00m');
- }
- }
- });
- })
- }
复制代码
19、Native Log日志Hook
- #int __android_log_print(int prio, const char* tag, const char* fmt, ...)
- function hookLog() {
- Interceptor.attach(Module.findExportByName("liblog.so","__android_log_print"), {
- onEnter: function (args) {
- // var level = ""
- // var level_i = parseInt(args[0])
- // if(level_i == 0){
- // level = "ANDROID_LOG_UNKNOWN"
- // }else if(level_i == 1){
- // level = "ANDROID_LOG_DEFAULT"
- // }else if(level_i == 2){
- // level = "ANDROID_LOG_VERBOSE"
- // }else if(level_i == 3){
- // level = "ANDROID_LOG_DEBUG"
- // }else if(level_i == 4){
- // level = "ANDROID_LOG_INFO"
- // }else if(level_i == 5){
- // level = "ANDROID_LOG_WARN"
- // }else if(level_i == 6){
- // level = "ANDROID_LOG_ERROR"
- // }else if(level_i == 7){
- // level = "ANDROID_LOG_FATAL"
- // }else if(level_i == 8){
- // level = "ANDROID_LOG_SILENT"
- // }
- // if(level_i==5){
- // console.warn(level+"\t"+args[1].readCString()+"\t"+args[2].readCString())
- // }else if(level_i > 5){
- // console.error(level+"\t"+args[1].readCString()+"\t"+args[2].readCString())
- // }else{
- // console.log(level+"\t"+args[1].readCString()+"\t"+args[2].readCString())
- // }
- console.log(args[1].readCString()+"\t"+args[2].readCString())
- }
- });
- }
复制代码
20、Native函数断点/调用/替换
- //主动调用native函数
- var soAddr = Module.findBaseAddress("libil2cpp.so");
- new NativeFunction(soAddr.add(0x4c33b0),"void",['pointer'])(Java.vm.tryGetEnv())
-
- //替换native函数
- //支持的类型:void,pointer,int,uint,long,ulong,char,uchar,float,double,int8,uint8,int16,uint16,int32,uint32,int64,uint64,bool
- Interceptor.replace(new NativeFunction(soAddr.add(0x58F0F4),'void', ['pointer']), new NativeCallback(function (arg) {
- console.log("called from:\n"+
- Thread.backtrace(this.context,Backtracer.FUZZY)
- .map(DebugSymbol.fromAddress).join("\n"));
- }, 'void', ['pointer']));
-
- //拦截native函数
- Interceptor.attach(soAddr.add(0xb7a93c),{
- onEnter:function(arg){
- console.log("called 0xb7a93c")
- },
- onLeave:function(retval){
- console.warn(retval)
- }
- })
复制代码
21、获取参数类型
- function getParamType(obj) {
- return obj == null ? String(obj) : Object.prototype.toString.call(obj).replace(/\[object\s+(\w+)\]/i, "$1") || "object";
- }
复制代码
22、hook 所有重载函数
- function hookAllOverloads(targetClass, targetMethod) {
- Java.perform(function () {
- var targetClassMethod = targetClass + '.' + targetMethod;
- var hook = Java.use(targetClass);
- var overloadCount = hook[targetMethod].overloads.length;
- for (var i = 0; i < overloadCount; i++) {
- hook[targetMethod].overloads[i].implementation = function() {
- var retval = this[targetMethod].apply(this, arguments);
- //这里可以打印结果和参数
- return retval;
- }
- }
- });
- }
复制代码
|
|