You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用Frida读取Cgo编译DLL中DoRequest参数结构体的属性?

读取Go编译C DLL中DoRequest参数结构体的Frida实现

核心思路

  1. 基于C#结构体定义,在Frida中映射对应的64位内存布局,考虑指针大小(8字节)和字段对齐规则
  2. 区分字符串类型:默认C# string对应UTF-16(LPWSTR),标注[MarshalAs(UnmanagedType.LPUTF8Str)]的字段对应UTF-8(char*)
  3. 可通过Frida的NativeStruct自动处理布局,或手动计算字段偏移读取数据

完整Frida Hook代码

方法1:使用NativeStruct自动处理布局

这种方式无需手动计算偏移,Frida会根据目标平台自动处理结构体对齐:

var doRequest = Module.getExportByName("client64.dll", "DoRequest");

// 映射C#的Struct0结构体
const RequestStruct = new NativeStruct({
    string_0: 'pointer',
    string_1: 'pointer',
    string_2: 'pointer',
    string_3: 'pointer',
    weirdString: 'pointer', // 对应特殊命名字段}{__>_
    string_4: 'pointer',
    string_5: 'pointer',
    string_6: 'pointer',
    string_7: 'pointer',
    string_8: 'pointer',
    string_9: 'pointer',
    int_0: 'int',
    int_1: 'int',
    string_10: 'pointer',
    bool_0: 'uint8', // UnmanagedType.I1对应1字节无符号整数
    bool_1: 'uint8',
    string_11: 'pointer',
    int_2: 'int',
    uint_0: 'uint'
});

// 读取UTF-16格式字符串(C#默认string类型)
function readUnicodeString(ptr) {
    return ptr.isNull() ? 'null' : ptr.readUtf16String();
}

// 读取UTF-8格式字符串(对应LPUTF8Str标注的字段)
function readUtf8String(ptr) {
    return ptr.isNull() ? 'null' : ptr.readUtf8String();
}

Interceptor.attach(doRequest, {
    onEnter: function(args) {
        console.log("[+] Hooked DoRequest");
        var structPtr = args[0];
        console.log("[+] Struct pointer: " + structPtr);

        // 解析结构体实例
        var requestStruct = new RequestStruct(structPtr);

        // 打印所有字段内容
        console.log("\n[+] Struct fields:");
        console.log(`string_0: ${readUnicodeString(requestStruct.string_0)}`);
        console.log(`string_1: ${readUnicodeString(requestStruct.string_1)}`);
        console.log(`string_2: ${readUnicodeString(requestStruct.string_2)}`);
        console.log(`string_3: ${readUnicodeString(requestStruct.string_3)}`);
        console.log(`}{__>_: ${readUnicodeString(requestStruct.weirdString)}`);
        console.log(`string_4 (UTF8): ${readUtf8String(requestStruct.string_4)}`);
        console.log(`string_5 (UTF8): ${readUtf8String(requestStruct.string_5)}`);
        console.log(`string_6: ${readUnicodeString(requestStruct.string_6)}`);
        console.log(`string_7: ${readUnicodeString(requestStruct.string_7)}`);
        console.log(`string_8: ${readUnicodeString(requestStruct.string_8)}`);
        console.log(`string_9: ${readUnicodeString(requestStruct.string_9)}`);
        console.log(`int_0: ${requestStruct.int_0}`);
        console.log(`int_1: ${requestStruct.int_1}`);
        console.log(`string_10: ${readUnicodeString(requestStruct.string_10)}`);
        console.log(`bool_0: ${requestStruct.bool_0 !== 0}`);
        console.log(`bool_1: ${requestStruct.bool_1 !== 0}`);
        console.log(`string_11: ${readUnicodeString(requestStruct.string_11)}`);
        console.log(`int_2: ${requestStruct.int_2}`);
        console.log(`uint_0: ${requestStruct.uint_0}`);
    }
});

方法2:手动计算偏移读取(适用于自动布局异常场景)

如果NativeStruct自动处理的布局不符合实际内存结构,可手动计算64位下的字段偏移:

var doRequest = Module.getExportByName("client64.dll", "DoRequest");

// 64位系统下的字段偏移(按C# Sequential布局规则计算)
const offsets = {
    string_0: 0x00,
    string_1: 0x08,
    string_2: 0x10,
    string_3: 0x18,
    weirdString: 0x20,
    string_4: 0x28,
    string_5: 0x30,
    string_6: 0x38,
    string_7: 0x40,
    string_8: 0x48,
    string_9: 0x50,
    int_0: 0x58,
    int_1: 0x5C,
    string_10: 0x60,
    bool_0: 0x68,
    bool_1: 0x69,
    string_11: 0x70,
    int_2: 0x78,
    uint_0: 0x7C
};

function readUnicodeString(ptr) {
    return ptr.isNull() ? 'null' : ptr.readUtf16String();
}

function readUtf8String(ptr) {
    return ptr.isNull() ? 'null' : ptr.readUtf8String();
}

Interceptor.attach(doRequest, {
    onEnter: function(args) {
        console.log("[+] Hooked DoRequest");
        var structPtr = args[0];
        console.log("[+] Struct pointer: " + structPtr);

        console.log("\n[+] Struct fields:");
        console.log(`string_0: ${readUnicodeString(structPtr.add(offsets.string_0).readPointer())}`);
        console.log(`string_1: ${readUnicodeString(structPtr.add(offsets.string_1).readPointer())}`);
        console.log(`string_2: ${readUnicodeString(structPtr.add(offsets.string_2).readPointer())}`);
        console.log(`string_3: ${readUnicodeString(structPtr.add(offsets.string_3).readPointer())}`);
        console.log(`}{__>_: ${readUnicodeString(structPtr.add(offsets.weirdString).readPointer())}`);
        console.log(`string_4 (UTF8): ${readUtf8String(structPtr.add(offsets.string_4).readPointer())}`);
        console.log(`string_5 (UTF8): ${readUtf8String(structPtr.add(offsets.string_5).readPointer())}`);
        console.log(`string_6: ${readUnicodeString(structPtr.add(offsets.string_6).readPointer())}`);
        console.log(`string_7: ${readUnicodeString(structPtr.add(offsets.string_7).readPointer())}`);
        console.log(`string_8: ${readUnicodeString(structPtr.add(offsets.string_8).readPointer())}`);
        console.log(`string_9: ${readUnicodeString(structPtr.add(offsets.string_9).readPointer())}`);
        console.log(`int_0: ${structPtr.add(offsets.int_0).readInt()}`);
        console.log(`int_1: ${structPtr.add(offsets.int_1).readInt()}`);
        console.log(`string_10: ${readUnicodeString(structPtr.add(offsets.string_10).readPointer())}`);
        console.log(`bool_0: ${structPtr.add(offsets.bool_0).readU8() !== 0}`);
        console.log(`bool_1: ${structPtr.add(offsets.bool_1).readU8() !== 0}`);
        console.log(`string_11: ${readUnicodeString(structPtr.add(offsets.string_11).readPointer())}`);
        console.log(`int_2: ${structPtr.add(offsets.int_2).readInt()}`);
        console.log(`uint_0: ${structPtr.add(offsets.uint_0).readUInt()}`);
    }
});

注意事项

  • 若读取到乱码,检查字符串类型是否匹配:默认C# string用readUtf16String,标注LPUTF8Str的字段用readUtf8String
  • 若字段值异常,可通过C#的Marshal.SizeOf(typeof(Struct0))计算结构体总大小,验证Frida读取的内存范围是否一致
  • Go编译的C DLL使用C调用约定,Frida默认兼容,无需额外配置

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:50:28