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

反编译.NET 4.6 DLL遇__fieldref等未知函数编译错误求解

解决.NET反编译中__fieldref和__untypedstackalloc的编译问题

我正在反编译一个基于.NET 4.6的DLL,用de4dot完成反编译与反混淆后得到大量类文件,但遇到两个未知函数__fieldref和__untypedstackalloc导致编译失败,相关代码及场景如下:

相关代码片段

__untypedstackalloc的调用与使用场景

void* voidPtr = (void*)__untypedstackalloc(12);

完整使用场景:

internal static unsafe string smethod_1(byte[] byte_0)
{
    // ISSUE: untyped stack allocation
    void* voidPtr = (void*)__untypedstackalloc(12);
    *(int*)voidPtr = 0;
    *(int*)((IntPtr)voidPtr + 4) = 0;
    while (*(int*)((IntPtr)voidPtr + 4) < byte_0.Length && (byte_0[*(int*)((IntPtr)voidPtr + 4)] != (byte)0 || byte_0[*(int*)((IntPtr)voidPtr + 4) + 1] != (byte)0))
    {
        *(int*)voidPtr = *(int*)voidPtr + 1;
        *(int*)((IntPtr)voidPtr + 4) = *(int*)((IntPtr)voidPtr + 4) + 2;
    }
    byte[] bytes = new byte[*(int*)voidPtr * 2];
    *(int*)((IntPtr)voidPtr + 8) = 0;
    while (*(int*)((IntPtr)voidPtr + 8) < *(int*)voidPtr * 2)
    {
        bytes[*(int*)((IntPtr)voidPtr + 8)] = byte_0[*(int*)((IntPtr)voidPtr + 8)];
        *(int*)((IntPtr)voidPtr + 8) = *(int*)((IntPtr)voidPtr + 8) + 1;
    }
    return Encoding.Unicode.GetString(bytes);
}

__fieldref的调用与关联类定义

RuntimeHelpers.InitializeArray((Array)numArray, __fieldref(Class73.class76_0));

Class73的定义:

[CompilerGenerated]
internal sealed class Class73
{
    internal static readonly Class73.Class78 class78_0;
    internal static readonly Class73.Class76 class76_0;
    internal static readonly Class73.Class74 class74_0;
    internal static readonly Class73.Class75 class75_0;
    internal static readonly Class73.Class77 class77_0;
    internal static readonly Class73.Class74 class74_1;
    internal static readonly Class73.Class77 class77_1;
    internal static readonly Class73.Class74 class74_2;

    [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 1)]
    private struct Class74
    {
    }

    [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)]
    private struct Class75
    {
    }

    [StructLayout(LayoutKind.Explicit, Size = 128, Pack = 1)]
    private struct Class76
    {
    }

    [StructLayout(LayoutKind.Explicit, Size = 256, Pack = 1)]
    private struct Class77
    {
    }

    [StructLayout(LayoutKind.Explicit, Size = 1024, Pack = 1)]
    private struct Class78
    {
    }
}

函数分析与解决方案

一、__untypedstackalloc

作用

本质是在栈上分配指定字节数的未类型化内存块,返回指向该内存的void*指针,用于临时存储少量数据(比如示例中用12字节存3个int变量,每个int占4字节)。栈内存会在方法返回时自动释放,适合短期临时存储。

为什么封装静态方法会出问题

C#中stackalloc分配的内存属于当前方法的栈帧,如果把它封装成独立静态方法返回指针,调用该方法后原栈帧销毁,返回的指针会指向已被释放的内存,后续访问会触发非法内存操作。

解决方法

直接在调用处用stackalloc替换原函数调用,无需封装:

// 替换原void* voidPtr = (void*)__untypedstackalloc(12);
byte* tempPtr = stackalloc byte[12]; // 分配12字节栈内存
void* voidPtr = tempPtr;

或者用int*分配(3个int正好12字节),效果完全一致:

int* tempPtr = stackalloc int[3];
void* voidPtr = tempPtr;

二、__fieldref

作用

用于获取静态字段的RuntimeFieldHandle,供RuntimeHelpers.InitializeArray使用——该方法需要通过字段句柄读取元数据中存储的数组初始值,完成目标数组的初始化。

反编译异常原因

de4dot反混淆时未正确解析IL中的ldtoken指令(该指令用于加载字段的元数据令牌),错误生成了__fieldref(Class73.class76_0)的调用(实际应获取字段本身的元数据句柄,而非字段的实例对象)。

解决方法

有两种可行方案:

方案1:直接替换调用处代码(推荐,性能更高)

用反射直接获取目标字段的FieldHandle,替换原函数调用:

// 替换原RuntimeHelpers.InitializeArray((Array)numArray, __fieldref(Class73.class76_0));
RuntimeHelpers.InitializeArray(
    (Array)numArray,
    typeof(Class73).GetField("class76_0", BindingFlags.Static | BindingFlags.NonPublic).FieldHandle
);
方案2:实现通用__fieldref方法(适合多处调用场景)

如果代码中有多处__fieldref调用,可以实现一个通用方法通过反射匹配字段:

using System;
using System.Reflection;

public static class DecompileHelpers
{
    public static RuntimeFieldHandle __fieldref(object staticFieldInstance)
    {
        Type declaringType = staticFieldInstance.GetType().DeclaringType;
        // 遍历类型的所有静态非公开字段(包含internal)
        foreach (FieldInfo field in declaringType.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Internal))
        {
            if (field.GetValue(null).Equals(staticFieldInstance))
            {
                return field.FieldHandle;
            }
        }
        throw new ArgumentException("无法找到对应的静态字段");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 02:10:51