墨锋
Published on 2025-03-22 / 8 Visits
0
0

[翻译]FRIDA官方文档-入门-Gadget

Gadget

Frida的Gadget是一个共享库,旨在加载需要进行动态插桩的程序,特别是在Injected模式不适用时。

可以通过以下方式实现:

  • 修改程序的源代码

  • 修补程序或其库(例如使用insert_dylib工具)

  • 使用动态链接器特性,如LD_PRELOADDYLD_INSERT_LIBRARIES

Gadget在动态链接器执行其构造函数时启动。

它支持四种交互方式,默认使用Listen交互。你可以通过添加配置文件来覆盖默认设置。配置文件名称应与Gadget二进制文件相同,只需将扩展名改为.config。例如,如果二进制文件名为FridaGadget.dylib,则配置文件应命名为FridaGadget.config

你可以随意命名Gadget的二进制文件,这有助于避免一些反Frida检测方法。

在iOS上使用Xcode时,可能会发现它会将FridaGadget.dylib放入名为“Frameworks”的子目录,并将“.config”文件放置在上级目录(与应用程序可执行文件和资源文件相邻)。因此,Gadget也会在上级目录中查找该.config文件,前提是它位于“Frameworks”目录中。

在Android上,包管理器仅会复制名称符合特定条件的文件,例如:

  • lib开头

  • .so结尾

  • 名称为gdbserver

Frida对此限制已经有所了解,并会接受这些修改后的配置文件。例如:

 lib
 └── arm64-v8a
     ├── libgadget.config.so
     ├── libgadget.so

配置文件应为UTF-8编码的文本文件,根为JSON对象,支持以下四个键:

  • interaction:描述使用的交互方式,默认为Listen

  • teardown:字符串,指定minimalfull,表示卸载库时执行的清理程度。默认值为minimal

  • runtime:字符串,指定使用的JavaScript运行时,支持defaultqjsv8

  • code_signing:字符串,指定optionalrequired,用于指示是否可以在监禁的iOS设备上运行无需调试器的代码。默认值为optional

支持的交互类型

  1. Listen

  2. Connect

  3. Script

  4. ScriptDirectory

Listen

默认交互方式,Gadget会以frida-server兼容的接口监听本地端口(默认是localhost:27042)。运行的进程列表和已安装的应用程序仅包含一个条目,即程序本身。进程名始终是Gadget,安装的应用程序标识符为re.frida.Gadget

若要进行早期插桩,Gadget的构造函数会阻塞,直到你通过attach()*附加到进程,或在执行完*spawn() -> attach() -> 插桩后调用resume()。现有的CLI工具(如frida-trace)的使用方式不变。

如果不想要阻塞行为,或者希望使用不同的接口或端口进行监听,可以通过配置文件进行定制。

默认配置如下:

 {
   "interaction": {
     "type": "listen",
     "address": "127.0.0.1",
     "port": 27042,
     "on_port_conflict": "fail",
     "on_load": "wait"
   }
 }

支持的配置键有:

  • address:指定监听的接口,支持IPv4和IPv6,默认是127.0.0.1

  • port:指定监听的端口,默认是27042

  • certificate:启用TLS时,指定PEM编码的公钥和私钥。

  • token:启用认证时,指定需要的密钥。

  • on_port_conflict:指定冲突时的行为,fail表示失败,pick-next表示尝试下一个端口。

  • on_load:指定Gadget加载后的行为,wait表示等待连接后再启动,resume表示直接启动程序。

  • origin:保护防止未授权的跨域使用。

  • asset_root:指定HTTP/HTTPS服务静态文件的根目录。

Connect

与“Listen”相反,Gadget连接到一个正在运行的frida-portal并成为其进程集群中的一员。

默认配置如下:

 {
   "interaction": {
     "type": "connect",
     "address": "127.0.0.1",
     "port": 27052
   }
 }

支持的配置键有:

  • address:指定连接的主机,默认为127.0.0.1

  • port:指定连接的端口,默认为27052

  • certificate:指定TLS时的公钥。

  • token:指定Portal的认证密钥。

  • acl:指定访问控制列表,限制哪些控制器可以与进程交互。

Script

如果希望通过脚本进行完全自主的插桩,可以在程序的入口点执行前加载脚本。

最简配置:

 {
   "interaction": {
     "type": "script",
     "path": "/home/oleavr/explore.js"
   }
 }

explore.js文件示例:

 rpc.exports = {
   init(stage, parameters) {
     console.log('[init]', stage, JSON.stringify(parameters));
 ​
     Interceptor.attach(Module.getExportByName(null, 'open'), {
       onEnter(args) {
         const path = args[0].readUtf8String();
         console.log('open("' + path + '")');
       }
     });
   },
   dispose() {
     console.log('[dispose]');
   }
 };

在调试时,可以使用console.log()console.warn()console.error()

支持的配置键有:

  • path:指定脚本的路径。

  • parameters:传递给init()方法的配置数据。

  • on_change:指定是否监视脚本文件的变化,reload表示脚本变化时重新加载。

ScriptDirectory

在某些情况下,你可能想处理系统级的程序和库,而不依赖于脚本逻辑判断程序,可以通过加载不同的脚本来处理。这种方式适用于处理系统或应用程序级的插件。

最简配置:

 {
   "interaction": {
     "type": "script-directory",
     "path": "/usr/local/frida/scripts"
   }
 }

支持的配置键有:

  • path:指定脚本目录路径。

  • on_change:指定是否重新扫描目录,rescan表示当目录内容发生变化时重新扫描。

每个脚本的可选配置文件可以包含以下键:

  • filter:指定加载脚本的条件。

  • parameters:传递给init()方法的配置数据。

  • on_change:指定是否重新加载脚本。

每个脚本的配置文件中的 filter 部分可以包含以下内容,用来限制加载的脚本:

  • executables:指定要匹配的可执行文件名数组。

  • bundles:指定要匹配的应用包标识符数组。

  • objc_classes:指定要匹配的Objective-C类名数组。

例如,假设你想为Twitter的macOS应用编写一个修改主题的脚本。你可以在 /usr/local/frida/scripts/ 目录下创建一个名为 twitter.js 的文件,内容如下:

 const { TMTheme } = ObjC.classes;
 ​
 rpc.exports = {
   init(stage, parameters) {
     console.log('[init]', stage, JSON.stringify(parameters));
 ​
     ObjC.schedule(ObjC.mainQueue, () => {
       TMTheme.switchToTheme_(TMTheme.darkTheme());
     });
   },
   dispose() {
     console.log('[dispose]');
 ​
     ObjC.schedule(ObjC.mainQueue, () => {
       TMTheme.switchToTheme_(TMTheme.lightTheme());
     });
   }
 };

然后,在同一目录下创建一个名为 twitter.config 的配置文件,内容如下:

 {
   "filter": {
     "executables": ["Twitter"],
     "bundles": ["com.twitter.twitter-mac"],
     "objc_classes": ["Twitter"]
   }
 }

在这个配置文件中,filter 部分定义了条件:如果程序的可执行文件名是 Twitter,或者包标识符是 com.twitter.twitter-mac,或者加载了 Twitter 类,那么脚本就会被加载。

通过这种方式,你可以为特定的应用程序加载自定义的脚本,而无需在脚本中做复杂的判断。这样做也便于维护和扩展,特别是在处理多个系统或应用程序时。

配置文件的其他支持项

除了上面提到的基本键,还有一些额外的配置项可以帮助你更好地定制脚本行为:

  • parameters:你可以在配置文件中传递任意的配置数据到脚本的 init() 方法中,默认是一个空对象。

  • on_change:指定脚本文件发生变化时的处理方式。ignore 表示只加载一次,reload 表示每次脚本变化时都重新加载,适合开发过程中频繁修改脚本时使用。

通过 on_change: "reload" 配置,Gadget会在文件改变时自动重新加载脚本,避免了手动干预,特别适合开发调试时使用。


原文链接:Gadget | Frida • A world-class dynamic instrumentation toolkit

翻译来源:ChatGPT


Comment