Friday, March 11, 2011

0 [C#] Reading struct from game

Hello.
This is my first tutorial. I hope you like it.
Consider this. You have reversed struct in game using ReClass.
ReClass generated code for this struct but in C++.
This is for WinMine.exe:



Code:
class CGame
{
public:
  char unknown0[280]; //0x0000
 __int32 xPressed; //0x0118  
 __int32 yPressed; //0x011C  
  char unknown288[32]; //0x0120
 __int32 MouseDown; //0x0140  
  char unknown324[28]; //0x0144
 __int32 GameStatus; //0x0160 3-win, 2-boom,  
 __int32 IsInGame; //0x0164  
  char unknown360[44]; //0x0168
 __int32 MinesLeft; //0x0194  
  char unknown408[408]; //0x0198
 __int32 LevelMines; //0x0330  
 __int32 Colls; //0x0334  
 __int32 Rows; //0x0338  
  char unknown828[868]; //0x033C
 __int32 GameType; //0x06A0 0-easy, ..., 3-custom 
  char unknown1700[40]; //0x06A4
 __int32 EasyBestScore; //0x06CC  
 __int32 MediumBestScore; //0x06D0  
 __int32 HardBestScore; //0x06D4  
 char PlayerEasyName[64]; //0x06D8  
 char PlayerMediumName[64]; //0x0718  
 char PlayerHardName[64]; //0x0758  
 __int32 NumLastHitsDiscovered; //0x0798  
 __int32 TimePlayed; //0x079C  
  char unknown1952[4]; //0x07A0
 __int32 DiscoveredFields; //0x07A4  
}//Size=0x07A8(1960)
Now this is the same struct in C#:
Code:
[StructLayout(LayoutKind.Explicit)]
    public struct WinMineGameStruct
    {
        [FieldOffset(0x118)]
        public Int32 xPressed;
        [FieldOffset(0x118)]
        public Int32 yPressed;
        [FieldOffset(0x140)]
        public Int32 MouseDown;
        [FieldOffset(0x160)]
        public Int32 GameStatus;
        [FieldOffset(0x164)]
        public Int32 IsInGame;
        [FieldOffset(0x194)]
        public Int32 MinesLeft;
        [FieldOffset(0x330)]
        public Int32 LevelMines;
        [FieldOffset(0x334)]
        public Int32 Colls;
        [FieldOffset(0x338)]
        public Int32 Rows;
        [FieldOffset(0x6a0)]
        public Int32 GameType;
        [FieldOffset(0x6cc)]
        public Int32 EasyBestScore;
        [FieldOffset(0x6d0)]
        public Int32 MediumBestScore;
        [FieldOffset(0x6d4)]
        public Int32 HardBestScore;
        [FieldOffset(0x6d8)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public Char[] PlayerEasyName;
        [FieldOffset(0x718)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public Char[] PlayerMediumName;
        [FieldOffset(0x758)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public Char[] PlayerHardName;
        [FieldOffset(0x798)]
        public Int32 NumLastHitDiscovered;
        [FieldOffset(0x79c)]
        public Int32 TimePlayed;
        [FieldOffset(0x7a4)]
        public Int32 DiscoveredFields;
    }
You can read more about Struct Layout and Field Offset attributes there:


Now.
I will not tell you how to read byte array from memory.
If you are reading this you should already know this.
In my example ProcessReaderWriter is wrppper for ReadProcessMemory winsows's function.

So there it is.

Code:
using System;
using System****ntime.InteropServices;
using ProcessMemoryReader;

namespace Tester
{
    [StructLayout(LayoutKind.Explicit)]
    public struct WinMineGameStruct
    {
        [FieldOffset(0x118)]
        public Int32 xPressed;
        [FieldOffset(0x118)]
        public Int32 yPressed;
        [FieldOffset(0x140)]
        public Int32 MouseDown;
        [FieldOffset(0x160)]
        public Int32 GameStatus;
        [FieldOffset(0x164)]
        public Int32 IsInGame;
        [FieldOffset(0x194)]
        public Int32 MinesLeft;
        [FieldOffset(0x330)]
        public Int32 LevelMines;
        [FieldOffset(0x334)]
        public Int32 Colls;
        [FieldOffset(0x338)]
        public Int32 Rows;
        [FieldOffset(0x6a0)]
        public Int32 GameType;
        [FieldOffset(0x6cc)]
        public Int32 EasyBestScore;
        [FieldOffset(0x6d0)]
        public Int32 MediumBestScore;
        [FieldOffset(0x6d4)]
        public Int32 HardBestScore;
        [FieldOffset(0x6d8)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public Char[] PlayerEasyName;
        [FieldOffset(0x718)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public Char[] PlayerMediumName;
        [FieldOffset(0x758)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public Char[] PlayerHardName;
        [FieldOffset(0x798)]
        public Int32 NumLastHitDiscovered;
        [FieldOffset(0x79c)]
        public Int32 TimePlayed;
        [FieldOffset(0x7a4)]
        public Int32 DiscoveredFields;
    }

    class Winmine
    {
        WinMineGameStruct WinMineStruct;
        ProcessReaderWriter Reader;

        public Winmine(ProcessReaderWriter reader)
        {
            Reader = reader;
            WinMineStruct = new WinMineGameStruct();
        }

        public void ReadGame()
        {
            Byte[] rawStruct = Reader.GetByteArray((IntPtr)0x1005000, 0x7A8);
            WinMineStruct = ByteArrayToStructure<WinMineGameStruct>(rawStruct);
        }

        public T ByteArrayToStructure<T>(byte[] bytes) where T : struct
        {
            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
            T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                typeof(T));
            handle.Free();
            return stuff;
        }
    }
}
If you have any question ask there. I'll not answer any questions sent on PM.

0 komentar:

Post a Comment