public unsafe IEnumerable <NamedOffset> FindOffsets(NamedPattern[] patterns, IntPtrEx @base, int size) { var buff = new byte[size]; fixed(byte *ptr = buff) if (!this.TryReadRawMemory(@base, ptr, size, out var read) || read != size) { return(null); } var baseval = @base.Pointer.ToInt32(); var offsets = new NamedOffset[patterns.Length]; for (var i = 0; i < patterns.Length; i++) { var pattern = patterns[i]; var off = this.FindPattern(pattern.Pattern, buff); var ptr = 0; if (!this.TryReadRawMemory(@base + off + pattern.PointerStart, &ptr, sizeof(int), out var read) || read != sizeof(int)) { throw new InvalidProcessException(); } offsets[i] = new NamedOffset(ptr - baseval, pattern.Name); } return(offsets); }
/// <summary> /// Reads and follows a pointer chain. /// </summary> /// <param name="addr">Address to start at.</param> /// <param name="offsets">Offsets to follow.</param> /// <returns>Final pointer.</returns> public unsafe IntPtrEx ReadPointerChain(IntPtrEx addr, params int[] offsets) { foreach (var offset in offsets) { addr = this.ReadPointer(addr + offset); } return(addr); }
private GameProcess(Process p, IntPtrEx gameModule, int moduleSize) { this._proc = p; this._module = gameModule; this._moduleSize = moduleSize; this._cts = new CancellationTokenSource(); this._ct = this._cts.Token; this._proc.Exited += this._proc_Exited; }
/// <summary> /// Reads a pointer from the process' memory. /// </summary> /// <param name="addr">Address to read from.</param> /// <returns>Read pointer.</returns> public unsafe IntPtrEx ReadPointer(IntPtrEx addr) { var ptrval = 0; if (!this.TryReadRawMemory(addr, &ptrval, sizeof(int), out var read) || read != sizeof(int)) { throw new MemoryReadException(); } return(new IntPtr(ptrval)); }
private unsafe bool TryReadRawMemory(IntPtrEx addr, void *buff, int size, out int read) { read = -1; if (!PInvoke.ReadProcessMemory(this._proc.Handle, addr.Pointer, buff, new IntPtr(size), out var pread)) { return(false); } read = pread.ToInt32(); return(true); }
/// <summary> /// Reads data of a blittable data structure. /// </summary> /// <typeparam name="T">Type of data to read.</typeparam> /// <param name="addr">Address to read from.</param> /// <returns>Read data.</returns> public unsafe T Read <T>(IntPtrEx addr) where T : unmanaged { var val = default(T); var size = sizeof(T); if (!this.TryReadRawMemory(addr, &val, size, out var read) || read != size) { throw new MemoryReadException(); } return(val); }
/// <summary> /// Reads a string from the process' memory. /// </summary> /// <param name="addr">Address to read from.</param> /// <param name="maxLength">Maximum string length to read.</param> /// <returns>Read string.</returns> public unsafe string ReadString(IntPtrEx addr, int maxLength = 256) { var buff = stackalloc char[maxLength]; if (!this.TryReadRawMemory(addr, buff, maxLength * sizeof(char), out var read)) { throw new MemoryReadException(); } var spbuff = new Span <char>(buff, read / sizeof(char)); var len = spbuff.IndexOf('\0'); if (len < 0) { return(new string(spbuff)); } return(new string(spbuff.Slice(0, len))); }
/// <summary> /// Reads an ANSI string from the process' memory. /// </summary> /// <param name="addr">Address to read from.</param> /// <param name="maxLength">Maximum string length to read.</param> /// <returns>Read string.</returns> public unsafe string ReadAnsiString(IntPtrEx addr, int maxLength = 256) { var buff = stackalloc byte[maxLength]; if (!this.TryReadRawMemory(addr, buff, maxLength, out var read)) { throw new MemoryReadException(); } var spbuff = new Span <byte>(buff, read); var len = spbuff.IndexOf((byte)0x00); if (len >= 0) { spbuff = spbuff.Slice(0, len); } return(Encoding.ASCII.GetString(spbuff)); }
private void ValidateKlass(IntPtrEx klassPtr, params string[] refNames) { // For whatever bloody reason, the pointers are off by one sometimes. // Always case with LSB var ptrv = klassPtr.Pointer.ToInt32(); if ((ptrv & 0x1) == 0x1) { ptrv &= ~0x1; } var klass = this._mem.Read <RawClassInfo>(new IntPtr(ptrv)); var name = this._mem.ReadAnsiString(klass.Name); if (!refNames.Any(x => name == x)) { throw new InvalidProcessException(); } }
public GameReader(ProcessMemory pmem, IntPtrEx module, int moduleSize) { this._mem = pmem; this._module = module; this._moduleSize = moduleSize; this._state = new GameStateInfo(); var offsets = this._mem.FindOffsets(new NamedPattern[] { new NamedPattern(Offsets.ClientName, Offsets.ClientPattern, Offsets.ClientPatternPtrLocation), new NamedPattern(Offsets.MeetingHudName, Offsets.MeetingHudPattern, Offsets.MeetingHudPatternPtrLocation), new NamedPattern(Offsets.GameDataName, Offsets.GameDataPattern, Offsets.GameDataPatternPtrLocation), new NamedPattern(Offsets.ShipStatusName, Offsets.ShipStatusPattern, Offsets.ShipStatusPatternPtrLocation) }, this._module, this._moduleSize); foreach (var offset in offsets) { switch (offset.Name) { case Offsets.ClientName: Offsets.ClientBase = offset.Offset; break; case Offsets.MeetingHudName: Offsets.MeetingHudBase = offset.Offset; break; case Offsets.GameDataName: Offsets.GameDataBase = offset.Offset; break; case Offsets.ShipStatusName: Offsets.ShipStatusBase = offset.Offset; break; } } if (Offsets.ClientBase == 0 || Offsets.MeetingHudBase == 0 || Offsets.GameDataBase == 0 || Offsets.ShipStatusBase == 0) { throw new InvalidProcessException(); } }