从调试过程MainModule获取符号

Str*_*ece 37 c# debugging pinvoke debug-symbols

我开始用C#编写调试器,以调试我的操作系统上的任何进程.目前,它只能处理断点(HW,SW和内存),但现在我想显示进程的操作码.

我的第一次尝试是使用nidsasm(NASM),但这不合适,因为启动后a.Net应用程序汇编程序指令与ndisasm(使用CheatEngine测试)不同.

所以我搜索了一段时间,发现dbghelp.dll中的一些方法,可以调用它们列出所有加载的模块和符号(加上基地址).好吧,我的尝试是,用SharpDisasm分别拆解所有模块.

ProcessModuleCollection modules = ProcessData.Instance.MPMR.ReadProcess.Modules;用来获取进程的所有加载模块.这非常有效.

现在我尝试加载MainModule的符号,但此时,我坚持实现.我用p/Invoke和SymInitialize等其他必要的函数实现了SymEnumSymbols函数.

当我使用例如"User32.dll"的BaseAddress调用它时,所有符号都打印得很完美,但对于MainModule,我没有得到任何符号.

这是来自CheatEngine的截图: 从Cheat Engine获得的符号

正如你所看到的,有像"Form1_Load"这样的符号,我的实现并没有这些符号.

这是必要的代码示例:

if (!DebugApi.SymInitialize(ProcessData.Instance.MPMR.M_hProcess, null, false))
{
    var err = Marshal.GetLastWin32Error();

    //throw new Exception("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
    Console.WriteLine("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
    return;
}

if (!DebugApi.SymEnumSymbols(ProcessData.Instance.MPMR.M_hProcess, (ulong)ProcessData.Instance.MPMR.ReadProcess.MainModule.BaseAddress, "!", DebugApi.EnumSyms, IntPtr.Zero))
{
    var err = Marshal.GetLastWin32Error();

    //throw new Exception("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
    Console.WriteLine("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
    return;
}

DebugApi.SymCleanup(ProcessData.Instance.MPMR.M_hProcess);
Run Code Online (Sandbox Code Playgroud)

和我的DebugApi,具有所有必需的p/Invoke函数.

public class DebugApi
{

    [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, [MarshalAs(UnmanagedType.Bool)]bool fInvadeProcess);

    [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SymCleanup(IntPtr hProcess);

    [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern ulong SymLoadModuleEx(IntPtr hProcess, IntPtr hFile, string ImageName, string ModuleName, long BaseOfDll, int DllSize, IntPtr Data, int Flags);

    [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SymEnumSymbols(IntPtr hProcess, ulong BaseOfDll, string Mask, PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, IntPtr UserContext);

    public delegate bool PSYM_ENUMERATESYMBOLS_CALLBACK(ref SYMBOL_INFO pSymInfo, uint SymbolSize, IntPtr UserContext);

    public static bool EnumSyms(ref SYMBOL_INFO pSymInfo, uint SymbolSize, IntPtr UserContext)
    {
        Console.Out.WriteLine("Name: " + pSymInfo.Name);
        return true;
    }

    [Flags]
    public enum SymFlag : uint
    {
        VALUEPRESENT = 0x00000001,
        REGISTER = 0x00000008,
        REGREL = 0x00000010,
        FRAMEREL = 0x00000020,
        PARAMETER = 0x00000040,
        LOCAL = 0x00000080,
        CONSTANT = 0x00000100,
        EXPORT = 0x00000200,
        FORWARDER = 0x00000400,
        FUNCTION = 0x00000800,
        VIRTUAL = 0x00001000,
        THUNK = 0x00002000,
        TLSREL = 0x00004000,
    }

    [Flags]
    public enum SymTagEnum : uint
    {
        Null,
        Exe,
        Compiland,
        CompilandDetails,
        CompilandEnv,
        Function,
        Block,
        Data,
        Annotation,
        Label,
        PublicSymbol,
        UDT,
        Enum,
        FunctionType,
        PointerType,
        ArrayType,
        BaseType,
        Typedef,
        BaseClass,
        Friend,
        FunctionArgType,
        FuncDebugStart,
        FuncDebugEnd,
        UsingNamespace,
        VTableShape,
        VTable,
        Custom,
        Thunk,
        CustomType,
        ManagedType,
        Dimension
    };

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct SYMBOL_INFO
    {
        public uint SizeOfStruct;
        public uint TypeIndex;
        public ulong Reserved1;
        public ulong Reserved2;
        public uint Reserved3;
        public uint Size;
        public ulong ModBase;
        public SymFlag Flags;
        public ulong Value;
        public ulong Address;
        public uint Register;
        public uint Scope;
        public SymTagEnum Tag;
        public int NameLen;
        public int MaxNameLen;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
        public string Name;
    }

}
Run Code Online (Sandbox Code Playgroud)

我的函数应该没问题,因为它适用于其他模块(例如加载的dll).也许我不理解.Net可执行文件符号的概念或遗漏某些东西.

PPa*_*ann 2

难道您正在寻找 System.Diagnostics.SymbolStore.ISymbolScope。看一下SymbolAccess类,您可以使用它来访问返回 ISymbolVariable[] 的 ISymbolScope.GetLocals() 和 GetChildren() ,这次再次返回一个名为 ISymbolVariable[] 的数组

现在,另一组有趣的参考代码示例是调试器扩展,可让您“嗅探”值,如下所示