frida工具Jnitrace | Objection | r0tracer

这篇具有很好参考价值的文章主要介绍了frida工具Jnitrace | Objection | r0tracer。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

pip install objection

pip install jnitrace

要求是frida版本大于14点多,目前推荐使用 14.2.18

Frida Version : pip install frida==14.2.18

Jnitrace:

JNItrace是一个基于Frida框架的Hook jni方法的库。https://github.com/chame1eon/jnitrace

直接按照上面的pip安装。

jnitrace -l xxx.so 包名 --ignore-vm

注意:
frida工具Jnitrace | Objection | r0tracer
如果出现这种错误就是用了面具的隐藏 hide ;

Spawn模式及 jnitrace 都是需要关闭面具隐藏( Magisk Hide )
frida工具Jnitrace | Objection | r0tracer
不得不说 这真的是个神器。

另外博主有一些笔记,记录如下,方便后续观看:

加密函数定位:

jni| unicorn | androidemu | frida_hook

https://codeooo.blog.csdn.net/article/details/127105204
https://github.com/lasting-yang/frida_hook_libart.git

dump 脚本修复加密so

https://github.com/lasting-yang/frida_dump

frida hook模板:

so :https://codeooo.blog.csdn.net/article/details/122124012

java:

https://codeooo.blog.csdn.net/article/details/120025814

遍历so方法:

https://codeooo.blog.csdn.net/article/details/120033269

hook 常见算法

https://codeooo.blog.csdn.net/article/details/120025814

r0tracer:

安卓Java层多功能追踪脚本

AKA:精简版 objection + Wallbreaker

比objection增加延时spawn
比objection增加批量hook类\方法\构造函数
Wallbreaker在frida14上还是一直崩
比Wallbreaker增加hook看instance的fields
inspectObject函数可以单独拿出去使用

使用方法:
修改r0tracer.js文件最底部处的代码,开启某一个Hook模式。
frida工具Jnitrace | Objection | r0tracer

var isLite = false;
var ByPassTracerPid = function () {
    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");
            console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));
        }
        return retval;
    }, 'pointer', ['pointer', 'int', 'pointer']));
};
setImmediate(ByPassTracerPid);

(function(){
    let Color = {RESET: "\x1b[39;49;00m", Black: "0;01", Blue: "4;01", Cyan: "6;01", Gray: "7;11", "Green": "2;01", Purple: "5;01", Red: "1;01", Yellow: "3;01"};
    let LightColor = {RESET: "\x1b[39;49;00m", Black: "0;11", Blue: "4;11", Cyan: "6;11", Gray: "7;01", "Green": "2;11", Purple: "5;11", Red: "1;11", Yellow: "3;11"};    
    var colorPrefix = '\x1b[3', colorSuffix = 'm'
    for (let c in Color){
        if (c  == "RESET") continue;
        console[c] = function(message){
            console.log(colorPrefix + Color[c] + colorSuffix + message + Color.RESET);
        }
        console["Light" + c] = function(message){
            console.log(colorPrefix + LightColor[c] + colorSuffix + message + Color.RESET);
        }
    }
})();
function uniqBy(array, key) {
    var seen = {};
    return array.filter(function (item) {
        var k = key(item);
        return seen.hasOwnProperty(k) ? false : (seen[k] = true);
    });
}
function hasOwnProperty(obj, name) {
    try {
        return obj.hasOwnProperty(name) || name in obj;
    } catch (e) {
        return obj.hasOwnProperty(name);
    }
}
function getHandle(object) {
    if (hasOwnProperty(object, '$handle')) {
        if (object.$handle != undefined) {
            return object.$handle;
        }
    }
    if (hasOwnProperty(object, '$h')) {
        if (object.$h != undefined) {
            return object.$h;
        }
    }
    return null;
}
//查看域值
function inspectObject(obj, input) {
    var isInstance = false;
    var obj_class = null;
    if (getHandle(obj) === null) {
        obj_class = obj.class;
    } else {
        var Class = Java.use("java.lang.Class");
        obj_class = Java.cast(obj.getClass(), Class);
        isInstance = true;
    }
    input = input.concat("Inspecting Fields: => ", isInstance, " => ", obj_class.toString());
    input = input.concat("\r\n")
    var fields = obj_class.getDeclaredFields();
    for (var i in fields) {
        if (isInstance || Boolean(fields[i].toString().indexOf("static ") >= 0)) {
            // output = output.concat("\t\t static static static " + fields[i].toString());
            var className = obj_class.toString().trim().split(" ")[1];
            // console.Red("className is => ",className);
            var fieldName = fields[i].toString().split(className.concat(".")).pop();
            var fieldType = fields[i].toString().split(" ").slice(-2)[0];
            var fieldValue = undefined;
            if (!(obj[fieldName] === undefined))
                fieldValue = obj[fieldName].value;
            input = input.concat(fieldType + " \t" + fieldName + " => ", fieldValue + " => ", JSON.stringify(fieldValue));
            input = input.concat("\r\n")
        }
    }
    return input;
}

// trace单个类的所有静态和实例方法包括构造方法 trace a specific Java Method
function traceMethod(targetClassMethod) {
    var delim = targetClassMethod.lastIndexOf(".");
    if (delim === -1) return;
    var targetClass = targetClassMethod.slice(0, delim)
    var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length)
    var hook = Java.use(targetClass);
    var overloadCount = hook[targetMethod].overloads.length;
    console.Red("Tracing Method : " + targetClassMethod + " [" + overloadCount + " overload(s)]");
    for (var i = 0; i < overloadCount; i++) {
        hook[targetMethod].overloads[i].implementation = function () {
            //初始化输出
            var output = "";
            //画个横线
            for (var p = 0; p < 100; p++) {
                output = output.concat("==");
            }
            //域值
            if (!isLite) { output = inspectObject(this, output); }
            //进入函数
            output = output.concat("\n*** entered " + targetClassMethod);
            output = output.concat("\r\n")
            // if (arguments.length) console.Black();
            //参数
            var retval = this[targetMethod].apply(this, arguments);
            if (!isLite) {
                for (var j = 0; j < arguments.length; j++) {
                    output = output.concat("arg[" + j + "]: " + arguments[j] + " => " + JSON.stringify(arguments[j]));
                    output = output.concat("\r\n")
                }
                //调用栈
                output = output.concat(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
                //返回值
                output = output.concat("\nretval: " + retval + " => " + JSON.stringify(retval));
            }
            // inspectObject(this)
            //离开函数
            output = output.concat("\n*** exiting " + targetClassMethod);
            //最终输出
            // console.Black(output);
            var r = parseInt((Math.random() * 7).toFixed(0));
            var i = r;
            var printOutput = null;
            switch (i) {
                case 1:
                    printOutput = console.Red;
                    break;
                case 2:
                    printOutput = console.Yellow;
                    break;
                case 3:
                    printOutput = console.Green;
                    break;
                case 4:
                    printOutput = console.Cyan;
                    break;
                case 5:
                    printOutput = console.Blue;
                    break;
                case 6:
                    printOutput = console.Gray;
                    break;
                default:
                    printOutput = console.Purple;
            }
            printOutput(output);
            return retval;
        }
    }
}

function traceClass(targetClass) {
    //Java.use是新建一个对象哈,大家还记得么?
    var hook = Java.use(targetClass);
    //利用反射的方式,拿到当前类的所有方法
    var methods = hook.class.getDeclaredMethods();    
    //建完对象之后记得将对象释放掉哈
    hook.$dispose;
    //将方法名保存到数组中
    var parsedMethods = [];
    var output = "";    
    output = output.concat("\tSpec: => \r\n")
    methods.forEach(function (method) {
        output = output.concat(method.toString())
        output = output.concat("\r\n")
        parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]);
    });
    //去掉一些重复的值
    var Targets = uniqBy(parsedMethods, JSON.stringify);
    // targets = [];
    var constructors = hook.class.getDeclaredConstructors();
    if (constructors.length > 0) {
        constructors.forEach(function (constructor) {
            output = output.concat("Tracing ", constructor.toString())
            output = output.concat("\r\n")
        })
        Targets = Targets.concat("$init")
    }
    //对数组中所有的方法进行hook,
    Targets.forEach(function (targetMethod) {
        traceMethod(targetClass + "." + targetMethod);
    });
    //画个横线
    for (var p = 0; p < 100; p++) {
        output = output.concat("+");
    }
    console.Green(output);
}
function hook(white, black, target = null) {
    console.Red("start")
    if (!(target === null)) {
        console.LightGreen("Begin enumerateClassLoaders ...")
        Java.enumerateClassLoaders({
            onMatch: function (loader) {
                try {
                    if (loader.findClass(target)) {
                        console.Red("Successfully found loader")
                        console.Blue(loader);
                        Java.classFactory.loader = loader;
                        console.Red("Switch Classloader Successfully ! ")
                    }
                }
                catch (error) {
                    console.Red(" continuing :" + error)
                }
            },
            onComplete: function () {
                console.Red("EnumerateClassloader END")
            }
        })
    }
    console.Red("Begin Search Class...")
    var targetClasses = new Array();
    Java.enumerateLoadedClasses({
        onMatch: function (className) {
            if (className.toString().toLowerCase().indexOf(white.toLowerCase()) >= 0 &&
               (black == null || black == '' || className.toString().toLowerCase().indexOf(black.toLowerCase()) < 0)) {
                console.Black("Found Class => " + className)
                targetClasses.push(className);
                traceClass(className);
            }
        }, onComplete: function () {
            console.Black("Search Class Completed!")
        }
    })
    var output = "On Total Tracing :"+String(targetClasses.length)+" classes :\r\n";
    targetClasses.forEach(function(target){
        output = output.concat(target);
        output = output.concat("\r\n")        
    })
    console.Green(output+"Start Tracing ...")
}
function main() {
    Java.perform(function () {
        console.Purple("r0tracer begin ... !")
        //0. 增加精简模式,就是以彩虹色只显示进出函数。默认是关闭的,注释此行打开精简模式。
        //isLite = true;
        /*
        //以下三种模式,取消注释某一行以开启
        */
        //A. 简易trace单个函数
        traceClass("javax.crypto.Cipher")
        //B. 黑白名单trace多个函数,第一个参数是白名单(包含关键字),第二个参数是黑名单(不包含的关键字)
        // hook("javax.crypto.Cipher", "$");
        //C. 报某个类找不到时,将某个类名填写到第三个参数,比如找不到com.roysue.check类。(前两个参数依旧是黑白名单)
        // hook("com.roysue.check"," ","com.roysue.check");        
    })
}
/*
//setImmediate是立即执行函数,setTimeout是等待毫秒后延迟执行函数
//二者在attach模式下没有区别
//在spawn模式下,hook系统API时如javax.crypto.Cipher建议使用setImmediate立即执行,不需要延时
//在spawn模式下,hook应用自己的函数或含壳时,建议使用setTimeout并给出适当的延时(500~5000)
*/
setImmediate(main)
//
// setTimeout(main, 2000);


// 玄之又玄,众妙之门
// Frida的崩溃有时候真的是玄学,大项目一崩溃根本不知道是哪里出的问题,这也是小而专的项目也有一丝机会的原因
// Frida自身即会经常崩溃,建议多更换Frida(客/服要配套)版本/安卓版本,我自己常用的组合是两部手机,Frida12.8.0全家桶+安卓8.1.0,和Frida14.2.2全家桶+安卓10 

肉佬:https://github.com/r0ysue/r0tracer

推荐使用Frida14版本,并且将日志使用-o参数进行输出保存

frida -U -f com.r0ysue.example -l r0tracer.js --no-pause -o saveLog5.txt

“-f” 为 Spawn模式,去掉"-f" 为Attach模式

Frida版本=<12时,要加上–runtime=v8选项

frida -U com.r0ysue.example -l r0tracer.js --runtime=v8 --no-pause -o
saveLog6.txt

objection:

objection 启动界面:
frida工具Jnitrace | Objection | r0tracer
使用objection需要在手机上启动frida-sesver,再使用objection注入需要hook的应用

objection -g <包名> explore

下面指令中,有hook类,hook方法,前进程模块,导出函数等

Memory 指令
    memory list modules               //枚举当前进程模块
    memory list exports [lib_name]    //查看指定模块的导出函数
    memory list exports libart.so --json /root/libart.json //将结果保存到json文件中
    memory search --string --offsets-only                  //搜索内存

android heap 指令
    //堆内存中搜索指定类的实例, 可以获取该类的实例id
    search instances search instances com.xx.xx.class
     
    //直接调用指定实例下的方法
    android heap execute [ins_id] [func_name]
     
    //自定义frida脚本, 执行实例的方法
    android heap execute [ins_id]

android 指令
    android root disable   //尝试关闭app的root检测
    android root simulate  //尝试模拟root环境
    
    android ui screenshot [image.png]    //截图
    android ui FLAG_SECURE false         //设置FLAG_SECURE权限

内存漫游
    android hooking list classes    //列出内存中所有的类
     
    //在内存中所有已加载的类中搜索包含特定关键词的类
    android hooking search classes [search_name] 
     
    //在内存中所有已加载的方法中搜索包含特定关键词的方法
    android hooking search methods [search_name] 
     
    //直接生成hook代码
    android hooking generate simple [class_name]

hook 方式
    /*
        hook指定方法, 如果有重载会hook所有重载,如果有疑问可以看
        --dump-args : 打印参数
        --dump-backtrace : 打印调用栈
        --dump-return : 打印返回值
    */
    android hooking watch class_method com.xxx.xxx.methodName --dump-args --dump-backtrace --dump-return
     
    //hook指定类, 会打印该类下的所有调用
    android hooking watch class com.xxx.xxx
     
    //设置返回值(只支持bool类型)
    android hooking set return_value com.xxx.xxx.methodName false

Spawn 方式 Hook
    objection -g packageName explore --startup-command '[obejection_command]'

activity 和 service 操作
    android hooking list activities                   //枚举activity
    android intent launch_activity [activity_class]   //启动activity
    android hooking list services                     //枚举services
    android intent launch_service [services_class]    //启动services

任务管理器
    jobs list            // 查看任务列表
    jobs kill [task_id]  // 关闭任务

关闭 app 的 ssl 校验
    android sslpinning disable

监控系统剪贴板
    // 获取Android剪贴板服务上的句柄并每5秒轮询一次用于数据。 
    // 如果发现新数据,与之前的调查不同,则该数据将被转储到屏幕上。
    help android  clipboard

执行命令行
    help android shell_exec [command]

查看当前可用的activity或者service:

android hooking list activities/services

这个也可以使用adb查看:文章来源地址https://www.toymoban.com/news/detail-511119.html

(1)查看当前Activity :adb shell "dumpsys window w | grep name="

(2)查看当前栈顶的Activity :adb shell "dumpsys activity | grep mFocusedActivity"

或者:adb shell dumpsys activity activities | grep mResumedActivity

(3)查看当前栈顶的Activity的Fragment :adb shell dumpsys activity 包名

到了这里,关于frida工具Jnitrace | Objection | r0tracer的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Hadoop实战】Windows环境下编译Hadoop2(2.10.2-R0)

    前提 根据Hadoop源码包解压之后编译帮助文件 BUILDING.txt 中关于windows的要求来准备环境 本机环境 JDK1.8 Windows 10 64位专业版 maven 3.9.2 git 2.41.0 ProtocolBuffer 2.5.0 这个要求要满足不然有报错(Github地址) cmake 2.36.4 Visual Studio 2022 Professional cygwin 安装包 IDEA 2022.2.5 编译方式 使用VS2022的

    2024年02月11日
    浏览(44)
  • 安卓应用层抓包通杀脚本r0capture

    安卓应用层抓包通杀脚本r0capture r0ysue: https://github.com/r0ysue/r0capture Spawn 模式: python r0capture.py -U -f 包名 仅限安卓平台,测试安卓7、8、9、10、11 可用 ; 无视所有证书校验或绑定,不用考虑任何证书的事情; 通杀TCP/IP四层模型中的应用层中的全部协议; 通杀协议包括:Http,

    2024年02月12日
    浏览(32)
  • [Frida集成篇]FB_01.内置frida-inject到手机系统

    主要内容: frida-inject 工具使用及说明 内置 frida-inject 工具到手机系统 frida-inject 是 frida 中提供的可以直接放到手机端执行注入 js 脚本到 App 程序进行 hook 的工具。也就是说使用 frida-inject 命令可以脱离 PC 端执行注入了。 平时我们用 frida 进行 App 注入的时候,多半都是 PC 端安

    2024年02月16日
    浏览(24)
  • frida https抓包

    web端导入证书、https代理即可解决大部分需求,但是,有些app需要处理ssl pinning验证。 废话不多说。frida处理ssl pin的步骤大体如下。 安装python3.x,并在python环境中安装frida: 下载frida-server,并使用adb命令push到/data/local/tmp目录下,并运行: 注意:此处的 f r i d a − s e r v e r 和 f

    2024年01月20日
    浏览(70)
  • frida安装配置教程

    frida版本和python版本以及Android要对应,python版本过高会导致frida不可用,以下是不严谨的版本对应关系 frida12.3.6 -- python3.7 -- Android5-6 frida12.8.0 --Python3.8–Android7-8 frida14–Python3.8–Android9 查看python版本 python --version 安装指定版本的frida 我用的夜神模拟器安卓9版本,所以安装14版

    2024年02月13日
    浏览(29)
  • android frida检测绕过

    Frida检测是一种常见的安卓逆向技术,常用于防止应用程序被反向工程。如果您遇到了Frida检测,您可以尝试以下方法来绕过它: 使用Magisk Hide模块:Magisk是一个强大的安卓root工具,它附带了一个Magisk Hide模块,可以帮助您隐藏root权限。这可以帮助您绕过Frida检测。 使用Xpos

    2024年02月15日
    浏览(38)
  • so层检测frida绕过

    如果是在so层里开一个线程检测frida; 我们思路是可以frida加载那个so, 然后打印出检测线程的偏移; 然后干掉这个线程,完成!

    2024年02月12日
    浏览(43)
  • Frida-OC操作

    frida操作oc及hook示例:

    2024年02月11日
    浏览(35)
  • 最新2023:Frida完美安装方案

    原文是安装最新frida的步骤。但是我在使用过程中,如果安卓版本比较低的话,最新版frida不是很稳定。推荐安卓7、8安装frida 12.8.0版本,安卓10/frida14,安卓12/frida16。 2023:Frida完美安装方案指路 这个是frida12.8.0安装教程 逆向第一步,从frida开始! 用我自己的理解,说一下fr

    2024年02月06日
    浏览(31)
  • MacOS微信逆向分析-Frida

    PC下的微信二次开发相信大家都会了,那么本篇文章将带领大家使用Frida框架对Mac下微信来进行 二次开发 ! PS:还有一种静态注入的方式也不错,但是考虑到大家xcode安装包太大就不在这里展开啦。 PS:frida如何去使用大家得自己去学,本文不过多展开。 主要功能涉及如下:

    2024年02月04日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包