Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access structure in other program's memory?

I know how to import and use read/writeprocessmomory in C#. I'm working on game trainer. I need to have "direct" access to other process memory casted to struct. I can use readprocessmemory or writeprocessmemory but that would take much time to inplement for many structures.

There is this structure in 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)

How to represent that structure in C#? What is the easiest way to achive sth like this:

//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

In C# I want to be able to use it like this:

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

How to use other process memory as struct in my C# application?

like image 661
Hooch Avatar asked Feb 13 '11 18:02

Hooch


People also ask

Can a program access another program's memory?

Unless the program is specifically built to be able to inject itself in another processes memory space (i.e. using specific Windows programming calls that need administrative access), a program cannot see another programs memory.

Can a process read another process memory?

Processes cannot access other processes' memory in principle. In practice the underlying operating system usually offers this mechanism to privileged processes.

What section of memory will you allocate the struct instances in?

Structs are allocated on the stack, if a local function variable, or on the heap as part of a class if a class member.

Does a struct take up memory?

Yes except for padding. The struct occupies one "area" in memory. I say "area" because this is poorly defined in C due to manual memory management. Each item in the struct comes after the previous one, but there may be padding between them.


2 Answers

If you need a structure to be binary compatible with a non-managed program, you can use the [StructLayout] attribute and its friends. E.g. in your case it would be something like:

[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);
}

I am not sure if you would be able to access the data of the other module in such a direct way, but you can replace the method with ReadProcessMemory/WriteProcessMemory, the basic principle would still hold (only this time, you would need to manage the memory for the structure).

like image 159
Mormegil Avatar answered Oct 05 '22 18:10

Mormegil


If you want to read or write memory that is owned by a different process you need to use ReadProcessMemory and WriteProcessMemory. That's the only way to do it.

For what you are trying to do, it won't be enough to write the memory values into the other process. You'd likely need to invoke some methods as well. If these variables that you are modifying are properties, then the property access method would need to be called. If the variable holds something dynamic (e.g. a list, a string), then WriteProcessMemory is not going to get the job done.

This sort of thing is usually done with a well-defined interface (and API), some sort of plug-in architecture etc.

like image 45
David Heffernan Avatar answered Oct 05 '22 19:10

David Heffernan