微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 如何访问其他程序内存中的结构?

我知道如何在C#中导入和使用read / writeprocessmomory.
我正在研究游戏培训师.我需要“直接”访问转换为struct的其他进程内存.我可以使用readprocessmemory或writeprocessmemory,但这需要很多时间来实现许多结构.

C中有这种结构:

class CRenderer
{
public:
    char unkNown0[1692]; //0x0000
    BYTE ID07D54FC8; //0x069C  
    BYTE drawObjects; //0x069D  
    BYTE drawDeferred; //0x069E  
    BYTE drawParticles; //0x069F  
    BYTE ID07E1CA70; //0x06A0  
    BYTE drawBundledMeshes; //0x06A1  
    BYTE drawStaticmeshes; //0x06A2  
    BYTE drawSkinnedMeshes; //0x06A3  
    BYTE drawRoads; //0x06A4  
    BYTE drawTerrain; //0x06A5  
    BYTE drawUnderGrowth; //0x06A6  
    BYTE drawOverGrowth; //0x06A7  
    BYTE drawNaMetags; //0x06A8  
    BYTE drawTrees; //0x06A9  
    BYTE ID07E1CE70; //0x06AA  
    BYTE ID07E1CDF0; //0x06AB  
    BYTE DrawFPS; //0x06AC  
    BYTE ID07E1CEF0; //0x06AD  
    BYTE ID07E1C8F0; //0x06AE  
    BYTE ID07E1C870; //0x06AF  
    BYTE drawGraphs; //0x06B0  
    BYTE ID07D55048; //0x06B1  
    BYTE drawSkyDome; //0x06B2  
    BYTE drawSunFlare; //0x06B3  
    BYTE drawPostProduction; //0x06B4  
    BYTE ID07D550C8; //0x06B5  
    char unkNown1718[6534]; //0x06B6
};//Size=0x203C(8252)

如何在C#中表示该结构?
这样做最简单的方法是什么:

//C++
DWORD RendererBase = (DWORD)GetModuleHandle( "RendDx9.dll" ); //Gets the base address of RenDX9.dll
DWORD RendererOffset = RendererBase + 0x23D098; //Static address
CRenderer *cRenderer = *(CRenderer**)RendererOffset; //Points to the class using the static offset

cRenderer->drawSkyDome = 0; //No Sky
cRenderer->DrawFPS = 1; //Show FPS

在C#中,我希望能够像这样使用它:

cRenderer.drawSkyDome = 0; //No Sky
cRenderer.DrawFPS = 1; //Show FPS

如何在我的C#应用​​程序中使用其他进程内存作为struct?

解决方法

如果您需要一个与非托管程序二进制兼容的结构,则可以使用[StructLayout]属性及其朋友.例如.在你的情况下,它将是这样的:
[DllImport("kernel32.dll",CharSet=CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

[StructLayout(LayoutKind.Sequential,Pack = 1)]
public struct RendererData
{
    [MarshalAs(UnmanagedType.ByValArray,SizeConst = 1692)]
    public byte[] UnkNown;
    public byte ID07D54FC8;
    public byte DrawObjects;
    public byte DrawDeferred;
    // ...
    public byte DrawFPS;
    // ...
    public byte DrawSkyDome;
    // ...
}

void Main()
{
    IntPtr rendererBase = GetModuleHandle("RendDx9.dll");
    if (rendererBase == IntPtr.Zero)
    {
        throw new InvalidOperationException("RendDx9.dll not found");
    }
    IntPtr rendererAddr = IntPtr.Add(rendererBase,0x23D098);

    var data = new RendererData();
    Marshal.PtrToStructure(rendererAddr,data);

    data.DrawSkyDome = 0;
    data.DrawFPS = 1;

    Marshal.StructuretoPtr(data,rendererAddr,false);
}

我不确定你是否能够以这种直接的方式访问其他模块的数据,但你可以用ReadProcessMemory / WriteProcessMemory替换该方法,基本原则仍然适用(只有这一次,你需要管理结构的记忆).

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐