Gadget
Frida的Gadget是一个共享库,旨在加载需要进行动态插桩的程序,特别是在Injected模式不适用时。
可以通过以下方式实现:
修改程序的源代码
修补程序或其库(例如使用insert_dylib工具)
使用动态链接器特性,如LD_PRELOAD或DYLD_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
:字符串,指定minimal
或full
,表示卸载库时执行的清理程度。默认值为minimal
。runtime
:字符串,指定使用的JavaScript运行时,支持default
、qjs
和v8
。code_signing
:字符串,指定optional
或required
,用于指示是否可以在监禁的iOS设备上运行无需调试器的代码。默认值为optional
。
支持的交互类型
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