Frida官方文档-Gadget

Frida的Gadget是一个共享库,可以在不适合Injected操作模式的情况下由要检测的程序加载。

这可以通过多种方式完成, 例如:

  • 修改程序的源代码
  • 修补它或其一个库,例如 通过使用诸如insert_dylib之类的工具
  • 使用动态链接器功能,例如LD_PRELOAD或DYLD_INSERT_LIBRARIES

动态链接程序执行其构造函数后,就会立即启动Gadget。根据您的用例,它支持三种不同的交互,其中“Listen”交互是默认的. 您可以通过添加配置文件来覆盖它。 该文件的名称应与Gadget二进制文件完全相同,但文件扩展名为.config。 因此,例如,如果您命名二进制文件FridaGadget.dylib,则将命名配置文件FridaGadget.config。

请注意,您可以随意命名Gadget二进制文件,这对于回避寻找名称为“ Frida”的已加载库的反Frida检测方案很有用。

还值得注意的是,当使用Xcode向iOS应用添加.config时,您可能会发现将FridaGadget.dylib放在名为“ Frameworks”的子目录中,并将“ .config”放在其上方的目录中–接下来 到应用程序的可执行文件和任何资源文件。 因此,在这种情况下,小工具还将在父目录中查找.config。 但只有将其放在名为“ Frameworks”的目录中。

在Android上,程序包管理器仅在其名称符合以下条件时才从不可调试应用程序的/ lib文件夹复制文件:

  • 以前缀lib开头
  • 以后缀.so结尾
  • gdbserver

Frida非常了解此限制,并将接受具有这些更改的配置文件。 例:
lib
└── arm64-v8a
├── libgadget.config.so
├── libgadget.so
获取更多信息,请阅读这篇文章。

配置文件应为以JSON对象为根的UTF-8编码文本文件。 它在根级别支持四个不同的键:

  • interaction: object describing which interaction to use. It defaults to the Listen interaction.
  • teardown: string specifying either minimal or full, stating how much cleanup to perform when the library gets unloaded. The default is minimal, which means we don’t shut down internal threads and free allocated memory and OS resources. This is fine if Gadget’s lifetime is linked to the program itself. Specify full if you intend to unload it at some point.
  • runtime: string specifying either interpreter or jit, essentially letting you choose between Duktape and V8, respectively. The default is interpreter, i.e. Duktape, which uses less memory at the expense of speed and JavaScript language features.
  • code_signing: string specifying either optional or required, making it possible to run on a jailed iOS device without a debugger attached by setting this to required. The default is optional, which means Frida will assume that it is possible to modify existing code in memory and run unsigned code, both without getting killed by the kernel. Setting this to required also means the Interceptor API is unavailable. So on a jailed iOS device the only way to use the Interceptor API is if a debugger is attached prior to Gadget being loaded. Note that it is sufficient to just launch the app with a debugger, it does not have to remain attached as the relaxed code-signing state is sticky once set.

Supported interaction types

  • Listen
  • Script
  • ScriptDirectory

这是默认的互动,其中Gadget公开与frida-server相同的接口,默认情况下监听localhost:27042。 唯一的区别是,正在运行的进程和已安装的应用程序列表仅包含一个条目,该条目用于程序本身。 进程名称始终仅为Gadget,安装的应用程序标识符始终为re.frida.Gadget。

为了实现早期检测,我们让Gadget的构造函数停止运行,直到您通过常规的spawn()-> attach()->…apply instrumentation …步骤将attach()附加到进程,或调用resume()。 这意味着现有的CLI工具(例如frida-trace)的工作方式与您已经在使用它们的方式相同。

如果您不希望这种阻止行为,并且希望程序立即启动,或者您希望它在其他接口或端口上监听,则可以通过配置文件对此进行自定义。

默认配置为:

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

支持的配置键值:

  • address: string specifying the interface to listen on. Supports both IPv4 and IPv6. Defaults to 127.0.0.1. Specify 0.0.0.0 to listen on all IPv4 interfaces.
  • port: number specifying the TCP port to listen on. Defaults to 27042.
  • On_load: string specifying either resume or wait, stating what to do when Gadget is loaded. The default is wait, which means it will wait for you to connect to it and tell it to resume. Specify resume if you would like the program to be allowed to start immediately, which is useful if you just want to be able to attach at a later time.

脚本

有时,通过在执行程序的入口点之前从文件系统中加载脚本,以完全自主的方式应用某些检测很有用。
这是所需的最低配置:

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

其中explorer.js包含以下框架:

rpc.exports = {
  init: function (stage, parameters) {
    console.log('[init]', stage, JSON.stringify(parameters));

    Interceptor.attach(Module.getExportByName(null, 'open'), {
      onEnter: function (args) {
        var path = args[0].readUtf8String();
        console.log('open("' + path + '")');
      }
    });
  },
  dispose: function () {
    console.log('[dispose]');
  }
};

rpc.exports部分实际上是可选的,在脚本需要了解其生命周期时很有用。

Gatget会调用您的init()方法并等待其返回,然后再让程序执行其入口点。 这意味着如果您需要执行异步操作,例如,您可以返回Promise。 Socket.connect(),并确保您不会错过任何早期通话。 第一个参数stage是一个字符串,它指定了早期或晚期,对于了解Gadget是刚刚加载还是脚本正在重新加载非常有用。 以下是关于后一个主题的更多信息。 第二个参数parameter是配置文件中可选指定的对象,否则为空对象。 这对于参数化脚本很有用。
如果在卸载脚本时需要执行一些显式清理,则还可以公开dispose()方法。 这通常是由于进程退出,Gadget已卸载或脚本从磁盘加载新版本之前已卸载而发生的。

对于调试,您可以使用console.log(),console.warn()和console.error(),它们将打印到stdout / stderr。
支持的配置键为:

  • path: string specifying the filesystem path to the script to load. May also be a path relative to where the Gadget binary resides. Specifying a relative path on iOS will first look for the script relative to the app’s Documents directory. This means you can use iTunes file sharing to upload an updated version of the script, or update it by vending the whole container through AFC, which is allowed for debuggable apps. This is especially useful together with “on_change”: “reload”. This key does not have a default value and must be provided.
  • parameters: object containing arbitrary configuration data that you would like to pass to the init() RPC method. Defaults to an empty object.
  • on_change: string specifying either ignore or reload, where ignore means the script will be loaded exactly once, and reload means Gadget will monitor the file and reload the script anytime it changes. The default is ignore, but reload is highly recommended during development.

脚本目录

在某些情况下,您可能希望篡改系统范围内的程序和库,但您可能不想做一些事情来最小化过滤并根据Gadget在其中运行的程序加载不同的脚本,而不是从脚本的逻辑中识别程序。 您甚至可能不需要任何过滤,但是发现将每个脚本视为单独的插件很方便。 在GNU / Linux系统上,此类脚本甚至可以由程序包提供,从而可以轻松地为现有应用程序安装调整。
这是所需的最低配置:

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

支持的配置键是:

  • path: string specifying the filesystem path to the directory containing scripts to load. May also be a path relative to where the Gadget binary resides. This key does not have a default value and must be provided. Scripts should use .js as their file extension, and each script may also have configuration data in a .config file next to it. This means that twitter.js may specify its configuration in a file named twitter.config.
  • on_change: string specifying either ignore or rescan, where ignore means the directory will be scanned exactly once, and rescan means Gadget will monitor the directory and rescan it anytime it changes. The default is ignore, but rescan is highly recommended during development.

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

  • filter: object containing criteria for this script to be loaded. Only one of them has to match, so complex filtering should be implemented in the script itself if needed. Supports the following keys specifying what to match:
  • executables: array of strings specifying executable names
  • bundles: array of strings specifying bundle identifiers
  • objc_classes: array of strings specifying Objective-C class names
  • parameters: object containing arbitrary configuration data that you would like to pass to the init() RPC method. Defaults to an empty object.
  • on_change: string specifying either ignore or reload, where ignore means the script will be loaded exactly once, and reload means Gadget will monitor the file and reload the script anytime it changes. The default is ignore, but reload is highly recommended during development.

假设您要为Twitter的macOS应用编写一个调整,可以在/ usr / local / frida / scripts中创建一个名为twitter.js的文件,其中包含:

 var TMTheme = ObjC.classes.TMTheme;

rpc.exports = {
  init: function (stage, parameters) {
    console.log('[init]', stage, JSON.stringify(parameters));

    ObjC.schedule(ObjC.mainQueue, function () {
      TMTheme.switchToTheme_(TMTheme.darkTheme());
    });
  },
  dispose: function () {
    console.log('[dispose]');

    ObjC.schedule(ObjC.mainQueue, function () {
      TMTheme.switchToTheme_(TMTheme.lightTheme());
    });
  }
};

然后,为确保仅将此脚本加载到该特定应用中,您将创建另一个名为twitter.config的文件,其中包含:

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

这个例子说,我们希望在以下情况之一时加载脚本:

  • The executable name is Twitter, or
  • its bundle identifier is com.twitter.twitter-mac, or
  • it’s got an Objective-C class loaded whose name is Twitter.

对于这个特定的示例,您可能只对bundle ID进行过滤,因为这是最稳定的标识符,并且如果需要,请在代码中进行兼容性检查。在过滤键旁边,您还可以指定参数和on_change,就像在Script配置中 以上。

你可能感兴趣的:(Windows开发,Android平台,网络与安全)