前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >frida trace

frida trace

作者头像
小小咸鱼YwY
发布于 2023-02-03 03:23:01
发布于 2023-02-03 03:23:01
1.4K00
代码可运行
举报
文章被收录于专栏:python-爬虫python-爬虫
运行总次数:0
代码可运行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
 * raptor_frida_android_trace.js - Code tracer for Android
 * Copyright (c) 2017 Marco Ivaldi <raptor@0xdeadbeef.info>
 *
 * Frida.re JS script to trace arbitrary Java Methods and
 * Module functions for debugging and reverse engineering.
 * See https://www.frida.re/ and https://codeshare.frida.re/
 * for further information on this powerful tool.
 *
 * "We want to help others achieve interop through reverse
 * engineering" -- @oleavr
 *
 * Many thanks to @inode-, @federicodotta, @leonjza, and
 * @dankluev.
 *
 * Example usage:
 * # frida -U -f com.target.app -l raptor_frida_android_trace.js --no-pause
 *
 * Get the latest version at:
 * https://github.com/0xdea/frida-scripts/
 */



var logContentArray = new Array();

var singlePrefix = "|----"

// generic trace
function trace(pattern)
{
	// indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置,未出现则返回-1
	var type = (pattern.toString().indexOf("!") === -1) ? "java" : "module";

	if (type === "module") {
		console.log("is--module")
		// trace Module
		var res = new ApiResolver("module");
		var matches = res.enumerateMatchesSync(pattern);
		var targets = uniqBy(matches, JSON.stringify);
		targets.forEach(function(target) {
			traceModule(target.address, target.name);
		});

	} else if (type === "java") {
		console.log("is--java")

		// trace Java Class, 遍历加载的类,判断追踪的是否是类
		var found = false;
		Java.enumerateLoadedClasses({
			onMatch: function(aClass) {
				// console.log("is--java--1--"+aClass.toString())

				if (aClass.match(pattern)) {

					console.log("is--java--2--"+aClass.toString())

					found = true;
					//match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
					// 该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置。
					var className = aClass.match(/[L](.*);/)[1].replace(/\//g, ".");

					console.log('('+aClass.toString()+')-----'+className.toString());

					traceClass(className);
				}
			},
			onComplete: function() {}
		});

		// trace Java Method, 追踪方法
		if (!found) {
			try {
				console.log('trace---method---'+pattern.toString())
				traceMethod(pattern);
			}
			catch(err) { // catch non existing classes/methods
				console.error(err);
			}
		}
	}
}

// find and trace all methods declared in a Java Class
function traceClass(targetClass)
{
	var hook = Java.use(targetClass);
	var methods = hook.class.getDeclaredMethods();
	hook.$dispose;

	var parsedMethods = [];
	methods.forEach(function(method) {
		parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]);
	});

	var targets = uniqBy(parsedMethods, JSON.stringify);
	targets.forEach(function(targetMethod) {
		traceMethod(targetClass + "." + targetMethod);
	});
}

// trace a specific Java Method
function traceMethod(targetClassMethod)
{
	var delim = targetClassMethod.lastIndexOf(".");
	if (delim === -1) return;

	// slice() 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分
	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.log("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]");

	for (var i = 0; i < overloadCount; i++) {

		// hook方法
		hook[targetMethod].overloads[i].implementation = function() {

			var logContent_1 = "entered--"+targetClassMethod;

			var prefixStr = gainLogPrefix(logContentArray);

			logContentArray.push(prefixStr + logContent_1);

			console.warn(prefixStr + logContent_1);

			// print backtrace, 打印调用堆栈
			// Java.perform(function() {
			// 	var bt = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
			// 	console.log(prefixStr +"Backtrace:" + bt);
			// });

			// print args
			// if (arguments.length) console.log();

			// 打印参数
			for (var j = 0; j < arguments.length; j++)
			{
				var tmpLogStr = prefixStr + "arg[" + j + "]: " + arguments[j];
				console.log(tmpLogStr);
				logContentArray.push(tmpLogStr);
			}

			// print retval
			var retval = this[targetMethod].apply(this, arguments); // rare crash (Frida bug?)
			// 打印返回值
			// console.log("\n"+ targetClassMethod +"--retval: " + retval);

			var tmpReturnStr = prefixStr + "retval: " + retval;
			logContentArray.push(tmpReturnStr);
			console.log(tmpReturnStr);

			//结束标志
			var logContent_ex = "exiting--" + targetClassMethod;
			logContentArray.push(prefixStr + logContent_ex);
			console.warn(prefixStr + logContent_ex);


			return retval;
		}
	}
}

// 获取打印前缀
function gainLogPrefix(theArray)
{
	var lastIndex = theArray.length - 1;

	if (lastIndex<0)
	{
		return singlePrefix;
	}


	for (var i = lastIndex; i >= 0; i--)
	{
		var tmpLogContent = theArray[i];
		var cIndex = tmpLogContent.indexOf("entered--");

		if ( cIndex == -1)
		{
			var cIndex2 = tmpLogContent.indexOf("exiting--");
			if ( cIndex2 == -1)
			{
				continue;
			}
			else
			{
				//与上个方法平级
				var resultStr = tmpLogContent.slice(0,cIndex2);
				return resultStr;
			}
		}
		else
		{
			//在上个方法的内部
			var resultStr = singlePrefix + tmpLogContent.slice(0,cIndex);//replace(/entered--/, "");
			// console.log("("+tmpLogContent+")前缀是:("+resultStr+")");
			return resultStr;

		}
	}


	return "";

}



// 获取打印前缀
function gainLogPrefix_Module(theArray,status)
{
	var lastIndex = theArray.length - 1;

	if (lastIndex<0)
	{
		return singlePrefix;
	}


	for (var i = lastIndex; i >= 0; i--)
	{
		var tmpLogContent = theArray[i];
		var cIndex = tmpLogContent.indexOf("entered--");

		if ( cIndex == -1)
		{
			var cIndex2 = tmpLogContent.indexOf("exiting--");
			if ( cIndex2 == -1)
			{
				continue;
			}
			else
			{
				//与上个方法平级
				var resultStr = tmpLogContent.slice(0,cIndex2);
				return resultStr;
			}
		}
		else
		{
			if (tmpLogContent.indexOf(status)==-1)
			{
				//与上一条输出 平级
				var resultStr = tmpLogContent.slice(0,cIndex);//replace(/entered--/, "");
				// console.log("("+tmpLogContent+")前缀是:("+resultStr+")");
				return resultStr;
			}
			else
			{
				//在上个方法的内部
				var resultStr = singlePrefix + tmpLogContent.slice(0,cIndex);//replace(/entered--/, "");
				// console.log("("+tmpLogContent+")前缀是:("+resultStr+")");
				return resultStr;
			}

		}
	}


	return "";

}

// trace Module functions
function traceModule(impl, name)
{
	console.log("Tracing " + name);

	Interceptor.attach(impl, {


		onEnter: function(args) {


			// debug only the intended calls
			this.flag = false;
			// var filename = Memory.readCString(ptr(args[0]));
			// if (filename.indexOf("XYZ") === -1 && filename.indexOf("ZYX") === -1) // exclusion list
			// if (filename.indexOf("my.interesting.file") !== -1) // inclusion list
			this.flag = true;

			if (this.flag) {
				var prefixStr = gainLogPrefix_Module(logContentArray,"entered--");
				// console.warn("\n*** entered " + name);

				var logContent_1 = "entered--"+name;
				logContentArray.push(prefixStr + logContent_1);
				console.warn(prefixStr + logContent_1);

				// print backtrace, 打印调用堆栈
				// console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"));
			}
		},

		onLeave: function(retval) {


			if (this.flag) {

				var prefixStr = gainLogPrefix_Module(logContentArray,"non6soidjs3kejf6sle8ifsjie");

				// print retval
				// console.log("\nretval: " + retval);
				var logContent_1 = "retval:"+retval;
				logContentArray.push(prefixStr + logContent_1);
				console.warn(prefixStr + logContent_1);

				var logContent_2 = "exiting--"+name;
				logContentArray.push(prefixStr + logContent_2);
				console.warn(prefixStr + logContent_2);


				// console.warn("\n*** exiting " + name);
			}
		}

	});
}

// remove duplicates from array
function uniqBy(array, key)
{
        var seen = {};
        return array.filter(function(item) {
                var k = key(item);
                return seen.hasOwnProperty(k) ? false : (seen[k] = true);
        });
}

// usage examples
setTimeout(function() { // avoid java.lang.ClassNotFoundException

	Java.perform(function() {

		trace("com.test.xxxxx.MainActivity");

	});
}, 0);
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
frida小功能点备注(Android)
1.frida命令以启动app的方式注入frida脚本到app,并重定向输出日志到文件中
用户4682003
2025/06/16
1020
frida小功能点备注(Android)
[1098]frida主动调用方法
除了使用frida进行hook, 很多场景我们需要用frida主动调用app的java方法和so方法。
周小董
2025/06/13
1350
[1098]frida主动调用方法
记一次爱加密企业版脱壳与反调试绕过
https://github.com/hanbinglengyue/FART?tab=readme-ov-file
亿人安全
2025/04/29
6400
记一次爱加密企业版脱壳与反调试绕过
精品连载丨安卓 App 逆向课程之五 frida 注入 Okhttp 抓包下篇
接下来我们分析Yang大佬的Frida实现okhttp3.Interceptor[1]。
崔庆才
2020/07/28
9.1K0
【APP逆向百例】某蜂窝逆向分析
本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
K哥爬虫
2025/02/17
2120
【APP逆向百例】某蜂窝逆向分析
安卓Frida Hook基础
设置环境变量WORKON_HOME为下面自己建立好的路径,当然默认也可以不设置,默认在用户目录下
用户1423082
2024/12/31
1610
安卓Frida Hook基础
某车联网App 通讯协议加密分析(三) Trace Block
之前我们已经用unidbg跑通了libencrypt.so,那么如何判断跑出来的结果是对是错?再如何纠正unidbg跑错误的流程,是我们今天的目标。
奋飞安全
2022/09/13
9400
Trace大盘点
jnitrace -l libnative-lib.so com.example.myapplication
奋飞安全
2022/03/16
1.6K0
APP爬虫|逆向神器 frida 初试
frida 真的是 app 逆向的神器,当你遇上他的时候,就会爱上他。这篇文章主要是通过自己写个 app 的 demo,然后一步步的 hook 它。之后会有系列的文章介绍 frida 对其他 app 的应用。
Python编程与实战
2020/04/27
2K0
APP爬虫|逆向神器 frida 初试
Frida爬虫分析流程——以微信视频号下载为例
微信的通信协议没有使用传统的https,而是采用 mmtls 和 quic 协议结合的方案(可能),导致常用的抓包方案完全无效。因此我们考虑使用逆向 hook 的方式,对微信视频号的数据进行获取。
mythsman
2022/11/14
11.4K2
Frida爬虫分析流程——以微信视频号下载为例
某A系电商App doCommandNative浅析
李老板: 奋飞呀,x-sign你都水了好几篇了,一直在Apk里面打转,咱们啥时候分析分析它的so?
奋飞安全
2021/12/22
2.8K0
frida 初体验
UnCrackable App for Android Level 1 This app holds a secret inside. Can you find it? Objective: A se
wywwzjj
2023/05/09
2960
frida 初体验
frida- registernatives获取so层动态注册函数
谢谢大佬的无私奉献https://github.com/lasting-yang/frida_hook_libart
小小咸鱼YwY
2020/10/19
2.2K0
安卓Frida Hook进阶
frida关于nativefunction的文档:https://frida.re/docs/javascript-api/#nativefunction
用户1423082
2024/12/31
2120
安卓Frida Hook进阶
【APP 逆向百例】淘某热点 APP 逆向分析
本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
K哥爬虫
2025/03/24
1760
【APP 逆向百例】淘某热点 APP 逆向分析
Frida-trace常用命令
转载:https://blog.csdn.net/tslx1020/article/details/128250777
小小咸鱼YwY
2023/02/01
3.1K0
某A系电商App x-sign签名分析
前不久(我去,都大半年了)分析过 某二手电商App x-sign签名分析 类成员变量的分析 我们找到了几个伪装成so的jar包。
奋飞安全
2021/12/14
1.5K0
frida实战笔记
frida 是一个十分强大的工具,已经学习它有一段时间了,但也只是零零碎碎的练习与使用。最近在对一个 APP 进行分析的过程中,使用 frida 完成了脱壳、hook 破解、模拟抓包、协议分析的操作,可以说是一条龙服务了, 感觉十分有意义,学到了很多,对 frida 的理解和掌握程度也提高了不少,记录下来这次实战分享给各位正在学习 frida 的看雪用户。(在看雪上论坛水了这么久,也该反馈些东西了,逃
bosh123
2020/08/27
3.2K0
【APP 逆向百例】Frida 初体验,root 检测与加密字符串定位
本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
K哥爬虫
2023/01/12
1.7K0
【APP 逆向百例】Frida 初体验,root 检测与加密字符串定位
frida用法小汇总
根据cpu版本去下载相应frida-server 运行./frida-sever &
小小咸鱼YwY
2021/12/08
9090
相关推荐
frida小功能点备注(Android)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验