当前位置: 首页 > news >正文

Frida:配置自动补全 in VSCode

1. 前言

编写 frida JavaScript 脚本是一件 very 普遍的事情在 Android Reverse 中。为了方便编写,配置相关的环境使其能够自动补全是很关键的,即通过类名就能够获取该类的所有对外接口信息,这是面向对象编程的核心优势,可惜我没有对象。

首先我们还是要有一个信仰,相信这是能够配置好的,这个原因很简单,因为 frida 的控制台中就给出了相应的补全操作,只是因为操作不方便我才要去 VSCode 中配置。
在这里插入图片描述

2. 配置

In C/C++ 中我们只需要 #include 相应的头文件就能够达到在编写源码时的自动补全了,后续的补全操作都是由 MicrosoftIntelliSense 组件完成的。

同样的在 JavaScript 中包含相应的 .ts (TypeScript)文件就能够达到这样的效果。当然 .ts 绝对不是用来干这个的,只是我找到的 frida-gum 的相关文件是 .ts 的。相应的下载地址在这 @types/frida-gum。我下载的是 19.0.0 版本的,对应的 frida-17.2.* 这个版本的 APIfrida-16.1.0 是不同的,配置的时候需要找到对应版本的 index.d.ts 文件。

安装 node.js 后可以直接使用其附带的 npm 进行下载。After 下载,@types/frida-gum 目录下的 index.d.ts 复制到 Frida JavaScript 目录下即可。在文件开头添加下面的代码进行包含即可。

/// <reference path="./frida.d.ts" />

当然如果不 want 下载 node.js 可以直接从网页端产看代码,然后全选,复制到文件中保存,这里我要吐槽一下 npm 管理了,代码都展示出来了却不提供下载的接口。

完成包含后就可以在 VSCode 使用 Frida 的自动补全了。
在这里插入图片描述

3. API 变化

frida-17.2.5frida-16.1.0API 是不一样的,这里我只能说我亲身体会到的一个例子,这个 Bug 我找了好久,修完之后 I just wanna say sun your mum frida

下面的代码是 frida-16.1.0 以及很多网上教程中常用的用来 Hook Android 加载库时的操作。但在 frida-17.2.5 中这样的操作是不行的。

Module.findExportByName(null, "dlopen");

当输入上述 JavaScript 之后会在得到这样的报错信息,出现这样错误的原因是 frida-17.2.5 中没有相应的 API 实现。
在这里插入图片描述
When 我去查看相应的 API 描述 in @type/frida-gum-19.0.0 时,发现在 Module 中只有一个 findExportByName 的实现,而其参数列表只接受一个参数,并且函数没有 static 关键字修饰,必须要实例化之后才能使用。
在这里插入图片描述

While in @type/frida-gum-15.2.0 中则是另一种情况,在其 Module 中有两个 findExportByName 的实现,并且其中一个使用 static 关键字修饰,即不需要实例化也能使用。这就是代码 Module.findExportByName(null, "dlopen") 为什么在 frida-16.1.0 中能够正常使用的原因。
在这里插入图片描述

4. Some Code

这部分是我用来记录自己写的 JavaScript 代码的位置,主要是给自己以后查阅。使用的是 frida-17.2.5。包括:查找 API 函数输出调用栈颜色字

/// <reference path="./frida.d.ts" />
const CMD_RED = "\x1b[31m";
const CMD_GREEN = "\x1b[32m";
const CMD_YELLOW = "\x1b[33m";
const CMD_BLUE = "\x1b[34m";
const CMD_MAGENTA = "\x1b[35m";
const CMD_CYAN = "\x1b[36m";
const CMD_WHITE = "\x1b[37m";
// Store original console.log
const originalLog = console.log;
// Override console.log
console.log = function(...args) {originalLog(args, CMD_WHITE);
};console.log(CMD_GREEN + "[+] Enter Hook");/*** get a export function by its name* @param {string} strName : the function you want to hook* @returns {fnPoint} : the address of the function*/
function FindExportByName(strName) {var fn = null;const Modules = Process.enumerateModules();for(let i = 0; i < Modules.length; i++) {fn = Modules[i].getExportByName(strName);if(fn) {console.log(`In Module : ${Modules[i].name}, Address is : ${fn}`);break;}};return fn;
}/*** print out a thread calling stack * @param {context} Context : the context of current Thread, can be obtained in Interceptor.attach() callback*/
function TraceStack(Context) {try {const backtrace = Thread.backtrace(Context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).map(sym => sym.name + CMD_YELLOW +'[' + sym.moduleName + ']');console.log(CMD_YELLOW + 'Backtrace:');backtrace.forEach((frame, i) => console.log(CMD_GREEN + "\t" + `${i}: ${frame}`));}catch(e) {console.log(CMD_RED + "\tStack trace unavailable");console.log(CMD_RED + `\t${e}`);}console.log(CMD_GREEN + "End Trace");
}// record which lib are loaded
var setLoged = new Set(["libstats_jni.so"]);
/*** if the module isn't record in setLoged, then print it.* @param {string} libPath : the module name that is loaded* @returns : if the first that load it return 1 else return 0.*/
function LogLib(libPath) {if(libPath && !setLoged.has(libPath)) {setLoged.add(libPath);console.log(CMD_CYAN + `Load Module : ${libPath}`);return 1;}return 0;//console.log(CMD_RED + `00: ${this}`);
}function TraceModuleLoad() {var fnOpen = FindExportByName("android_dlopen_ext");if(fnOpen) {var bThere = 0;var libPath;Interceptor.attach(fnOpen, {onEnter(args) {libPath = args[0].readCString();bThere = LogLib(libPath);//Thread.sleep(10);if(bThere) {TraceStack(this.context);}},onLeave(retval) {}})console.log("Complete dlopen hook install");}
}
// get all the load module when apk start
TraceModuleLoad();console.log(CMD_YELLOW + "[-] Hook Installed");
http://www.lryc.cn/news/579478.html

相关文章:

  • TCP 三次握手与四次挥手详解
  • MyBatis 之基础概念与框架原理详解
  • RabbitMQ 通过HTTP API删除队列命令
  • 【如何判断Linux系统是Ubuntu还是CentOS】
  • Centrifugo 深度解析:构建高性能实时应用的开源引擎
  • 记忆翻牌记忆力小游戏流量主微信小程序开源
  • 网创vip课程视频教程、付费网络课程以及网赚培训,学习引流、建站、赚钱。8个T的全套课程
  • 【2.3 漫画SpringSecurity - 守护应用安全的钢铁卫士】
  • ATE FT ChangeKit学习总结-20250630
  • Easy-excel监听器中对批量上传的工单做错误收集
  • Redisson使用示例
  • 请求未达服务端?iOS端HTTPS链路异常的多工具抓包排查记录
  • 【Bug Recod】更新中...
  • Day50
  • 一文详解Character AI:实用指南+ ChatGPT、Gemini对比分析
  • contenteditable网页富文本编辑无法选中图片
  • Swift 的基础设计哲学是 “通过模块化组合实现安全与效率的平衡“,就像用标准化工业零件建造摩天大楼
  • 一台香港原生ip站群服务器多少钱?
  • 如何在Ubuntu上检查MySQL是否启动并放开3306端口
  • C++笔记-位图和布隆过滤器
  • P1155 [NOIP 2008 提高组] 双栈排序
  • 李宏毅机器学习笔记——梯度下降法
  • 映射阿里云OSS(对象存储服务)
  • 百度文心智能体平台x小米应用商店:联手打造行业首个智能体与应用市场跨端分发模式
  • webrtc-streamer视频流播放(rstp协议h264笔记)
  • KDD 2025 | 地理定位中的群体智能:一个多智能体大型视觉语言模型协同框架
  • Go应用容器化完全指南:构建最小化安全镜像的终极实践
  • I/O 线程 7.3
  • VTK中自定义双组分输入最大值滤波
  • 基于spark的北京房价数据分析及价格预测