C++ 以编程方式附加调试器并获取变量地址Visual Studio

C++ 以编程方式附加调试器并获取变量地址Visual Studio,c++,c,visual-studio,debugging,gdb,C++,C,Visual Studio,Debugging,Gdb,在使用C/C++编程的微控制器中,在程序启动之前,所有地址都是已知的。我可以使用编译时生成的elf文件来查找带有gdb的文件,例如: gdb elfFile.elf-ex print&variableName-ex quit 这对于实时获取变量非常有用,方法是向微控制器请求外部工具的变量地址,该工具可用于记录和绘制数据。该工具从elf文件中获取变量地址,然后只要求微控制器读取地址处的数据&variableName,共n个字节 我已经将一些微控制器代码移植到Windows进行测试,并且它运行正常。

在使用C/C++编程的微控制器中,在程序启动之前,所有地址都是已知的。我可以使用编译时生成的elf文件来查找带有gdb的文件,例如:

gdb elfFile.elf-ex print&variableName-ex quit

这对于实时获取变量非常有用,方法是向微控制器请求外部工具的变量地址,该工具可用于记录和绘制数据。该工具从elf文件中获取变量地址,然后只要求微控制器读取地址处的数据&variableName,共n个字节

我已经将一些微控制器代码移植到Windows进行测试,并且它运行正常。我想添加日志功能,为此,我需要能够从运行的exe文件中以编程方式获取变量地址。在程序在Windows中启动之前,变量的地址是未知的,但偏移量可能是已知的。我正在使用Visual Studio Express 2017,我打算获取我自己编译的程序的地址,而不是来自外部的任何程序。从VisualStudio内部,我可以看到任何带有调试器的变量,所以我希望有一个调试器exe文件,我可以从外部调用并附加到我的程序中,以与gdb类似的方式读取变量地址


有什么帮助吗?谢谢

您可以使用CreateRemoteProcess插入dll,并在其中读取变量地址

但是你正在寻找一个叫做

此外,您还可以下载并安装MinGW&msys,然后可以从源代码处下载。但是你必须在Windows上使用MinGW来编译程序。Mingw创建本机Win32/Win64程序-无需Cygwin

我没有CreateRemoteThread的版本,但我可以提供C源代码:

// Inject(DLL_NAME, "Engine");
void Inject(string strDLLtoInject, string strEngine) 
{
    CheckIfDebugger();
    //String pszLibFileRemote = Application.StartupPath + "\\"+ strDLLtoInject;            
    //String pszLibFileRemote = Application.StartupPath + "\\"+ strDLLtoInject;            
    //String strPathOfSharedObjectToInject = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + System.IO.Path.DirectorySeparatorChar + strDLLtoInject;
    String strPathOfSharedObjectToInject = m_strTempPath + strDLLtoInject;

    //System.Windows.Forms.MessageBox.Show(strPathOfSharedObjectToInject);
    System.Diagnostics.Process[] TargetProcess = System.Diagnostics.Process.GetProcessesByName(strEngine);

    if (TargetProcess.Length > 0)
    {
        System.IntPtr pTargetProcess = WinAPI.OpenProcess(WinAPI.CREATE_THREAD_ACCESS, false, TargetProcess[0].Id);
        if (pTargetProcess != System.IntPtr.Zero)
        {
            CheckIfDebugger();
            int iLoadLibraryAaddress = WinAPI.GetProcAddress(WinAPI.GetModuleHandleA("Kernel32.dll"), "LoadLibraryA");
            if (iLoadLibraryAaddress != 0)
            {
                int iSharedObjectNameBufferSize = 1 + strPathOfSharedObjectToInject.Length;
                int iSharedObjectNameAddress = WinAPI.VirtualAllocEx(pTargetProcess, 0, iSharedObjectNameBufferSize, 4096, 4);

                if (iSharedObjectNameAddress != 0)
                {
                    CheckIfDebugger();
                    int iReturnValue = WinAPI.WriteProcessMemory(pTargetProcess, iSharedObjectNameAddress, strPathOfSharedObjectToInject, iSharedObjectNameBufferSize, 0);

                    if (iReturnValue != 0)
                        WinAPI.CreateRemoteThread(pTargetProcess, 0, 0, iLoadLibraryAaddress, iSharedObjectNameAddress, 0, 0);
                    else
                        MsgBox("WriteProcessMemory failed.", "Error");

                    CheckIfDebugger();
                } // End if (iSharedObjectNameAddress != null)
                else
                    MsgBox("VirtualAllocEx failed.", "Error");

            }// End if (iLoadLibraryAaddress != null)
            else
                MsgBox("GetProcAddress or GetModuleHandleA failed.", "Error");

            CheckIfDebugger();
            WinAPI.CloseHandle(pTargetProcess);
        } // End if (pTargetProcess != System.IntPtr.Zero)
        else
            MsgBox("OpenProcess failed.", "Error");

        CheckIfDebugger();
    } // End if (TargetProcess.Length > 0)
    else
        MsgBox("GetProcessesByName failed.", "Error");

    CheckIfDebugger();
} // End Sub Inject
以下是WinAPI调用:

class WinAPI
{
    public const int CREATE_THREAD_ACCESS = 0x1F0FFF;


    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

    [System.Runtime.InteropServices.DllImport("Kernel32", EntryPoint = "GetModuleHandleA", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern int GetModuleHandleA(string lpModuleName);

    [System.Runtime.InteropServices.DllImport("kernel32", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern int GetProcAddress(int hModule, string lpProcName);

    [System.Runtime.InteropServices.DllImport("kernel32", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern int VirtualAllocEx(System.IntPtr hProcess, int lpAddress, int dwSize, int flAllocationType, int flProtect);

    [System.Runtime.InteropServices.DllImport("kernel32", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern int WriteProcessMemory(System.IntPtr hProcess, int lpBaseAddress, string lpBuffer, int nSize, int lpNumberOfBytesWritten);

    [System.Runtime.InteropServices.DllImport("kernel32", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern int CreateRemoteThread(System.IntPtr hProcess, int lpThreadAttributes, int dwStackSize, int lpStartAddress, int lpParameter, int dwCreationFlags, int lpThreadId);

    [System.Runtime.InteropServices.DllImport("kernel32", EntryPoint = "CloseHandle")]
    public static extern int CloseHandle(System.IntPtr hObject);

    // http://www.pinvoke.net/default.aspx/kernel32/GetVersion.html
    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    public static extern uint GetVersion();

    [System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, ExactSpelling = true)]
    internal static extern bool IsDebuggerPresent();


} // End class WinAPI

Windows程序是否首先将所有相关地址转储到文本文件或类似文件中?不管你怎么说,在Windows中模拟微控制器基本上都是骗人的。特别是,Windows不存在实时行为。