使用Ultimate-ASI-Loader实现DLL注入frida-gadget

概况

有时想执行exe文件直接执行frida的hook,需要通过DLL inject的方式实现。 程序在加载DLL时会优先加载当前目录的,所以可以伪造一个DLL加载我们自己准备好的DLL,然后执行原有DLL的方法。

使用

可以使用 Ultimate-ASI-Loader 实现注入。unity会加载version.dll,下载对应版本的 version.dll 放到游戏根目录,下载 frida-gadget.dll 改名为 frida-gadget.asi

增加配置文件frida-gadget.config

1
2
3
4
5
6
7
{
  "interaction": {
    "type": "script",
    "path": "frida.js",
    "on_change": "reload"
  }
}

然后就是 frida.js 文件,下面是一个AI生成的例子,这个例子是Hook CHECK_FILE_INTEGRITY 方法,直接返回true。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
"use strict";

// 仅适用于当前 GameAssembly.dll 构建:
// SHA-256 db1c25ebdc0d1a8c3718971039db718323caae04e94c5a93f17e208827f2036e
const CHECK_FILE_INTEGRITY_RVA = 0x3d4e50;
const POLL_INTERVAL_MS = 10;

let installed = false;

function readIl2CppString(value) {
    if (value.isNull()) return "<null>";
    try {
        const length = value.add(0x10).readS32();
        if (length < 0 || length > 0x10000) return `<invalid length=${length}>`;
        return value.add(0x14).readUtf16String(length) || "";
    } catch (error) {
        return `<read failed: ${error}>`;
    }
}

function installHook() {
    if (installed) return;

    const gameAssembly = Process.findModuleByName("GameAssembly.dll");
    if (gameAssembly === null) return;

    installed = true;
    Interceptor.attach(gameAssembly.base.add(CHECK_FILE_INTEGRITY_RVA), {
        onEnter(args) {
            this.rootPath = readIl2CppString(args[1]);
            this.targetPath = readIl2CppString(args[2]);
            this.expectedLength = args[3].toInt32();
        },
        onLeave(retval) {
            const originalResult = (retval.toInt32() & 0xff) !== 0;
            retval.replace(ptr(1));
            send(
                `[FILE-INTEGRITY BYPASS] originalResult=${originalResult} ` +
                `effectiveResult=true expectedLength=${this.expectedLength}\n` +
                `root=${this.rootPath}\n` +
                `target=${this.targetPath}`,
            );
        },
    });

    send(
        `[READY] CheckFileIntegrity hook installed at ` +
        `${gameAssembly.base.add(CHECK_FILE_INTEGRITY_RVA)}`,
    );
}

send("[BOOT] frida.js loaded; waiting for GameAssembly.dll");
const installTimer = setInterval(() => {
    installHook();
    if (installed) clearInterval(installTimer);
}, POLL_INTERVAL_MS);
installHook();

如何找到这个位置

这个游戏检查了dll的大小等,游戏中随机延迟使用协程弹窗报错,使用AI从错误码入手,使用IDA MCP静态分析,分析了很久才找到弹窗的相关代码。然后分析什么情况才会弹窗,最后看这个变量是哪里赋值的。

updatedupdated2026-08-082026-08-08