Some C# memory reading stuff I had laying around. menu

User Tag List

Results 1 to 8 of 8
  1. #1
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Some C# memory reading stuff I had laying around.

    Was going through my project folders for VS 2k8, and I found an old memory lib. (Similar to BlackMagic, but aimed more-so at .NET developers who want the Win32 API abstracted away as far as possible.)

    Anyhow, here's a few snippets of code. Obviously, you'll need to tweak it to fit your needs, but it all works (on my side at least) without bugs.


    Generic Read/Write Methods & CreateCodeCaves

    The generic read/write can be used as follows:

    Normal read procedure: [[[0x005]+0x002]+0x004]

    uint myAddress = memoryManager.Read<uint>(0x005, 0x002, 0x004);

    It will perform the incremental reads for you.

    For instance, imagine the above read was for the playerbase, and another read at pbase + 0x0F54 was the local X address.

    float localX = memoryManager.Read<float>(0x005, 0x002, 0x004, 0x0F54);

    That would produce exactly what you are looking for.

    Note: If you pass anything other than a ValueType (int, uint, long, byte, etc) it defaults to ReadObject, which may not be what you intend!

    Code:
            #region Read
    
            /// <summary>
            /// Reads the specified offsets. TODO: Add proper comments...
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="offsets">The offsets.</param>
            /// <returns></returns>
            /// 12/22/2008 6:41 PM
            public T Read<T>(params uint[] offsets)
            {
                if (offsets.Length == 0)
                {
                    throw new Exception("Invalid number of offsets passed! Must be > 0");
                }
                // Store the type so we don't need to make a bunch of
                // typeof calls if there's a long list of offsets
                Type t = typeof (T);
                // If we only have 1 offset, there's no point in going
                // through the for loop and doing more work than needed.
                if (offsets.Length == 1)
                {
                    return (T) _Read(offsets[0], t);
                }
                // This holds the last offset read.
                // Once we reach offsets.Length -1, we'll return the
                // proper T type needed.
                uint last = 0;
                for (int i = 0; i < offsets.Length; i++)
                {
                    // If this is the last offset in the params list
                    // we need to return the T type requested.
                    if (i == (offsets.Length - 1))
                    {
                        return (T) _Read(offsets[i] + last, t);
                    }
                    // Keep reading from the last thing read + the next offset
                    // in the params list.
                    // This is the equivalent to: [[[0x404]+0x54]+0x2C]
                    last = (uint) _Read(last + offsets[i], typeof (uint));
                }
                // We should never hit this point
                // The compiler bitches if we don't add this...
                return default(T);
            }
    
            private object _Read(uint address, Type t)
            {
                switch (Type.GetTypeCode(t))
                {
                    case TypeCode.SByte:
                        return GetReader.ReadSByte(address);
                    case TypeCode.Byte:
                        return GetReader.ReadByte(address);
                    case TypeCode.Int16:
                        return GetReader.ReadShort(address);
                    case TypeCode.UInt16:
                        return GetReader.ReadUShort(address);
                    case TypeCode.Int32:
                        return GetReader.ReadInt(address);
                    case TypeCode.UInt32:
                        return GetReader.ReadUInt(address);
                    case TypeCode.Int64:
                        return GetReader.ReadInt64(address);
                    case TypeCode.UInt64:
                        return GetReader.ReadUInt64(address);
                    case TypeCode.Single:
                        return GetReader.ReadFloat(address);
                    case TypeCode.Double:
                        return GetReader.ReadDouble(address);
                    default:
                        return GetReader.ReadObject(address, t);
                }
            }
    
            /// <summary>
            /// Reads a string from memory. The default length is 255. (MAX_LEN in C++)
            /// </summary>
            /// <param name="address">The address to read the string from.</param>
            /// <param name="ascii">if set to <c>true</c> the string will be read as an ASCII string. Otherwise it will be read as Unicode.</param>
            /// <returns></returns>
            /// 12/22/2008 4:42 PM
            public string ReadString(uint address, bool ascii)
            {
                return ReadString(address, ascii, 255);
            }
    
            /// <summary>
            /// Reads a string from memory.
            /// </summary>
            /// <param name="address">The address to read the string from.</param>
            /// <param name="ascii">if set to <c>true</c> the string will be read as an ASCII string. Otherwise it will be read as Unicode.</param>
            /// <param name="length">The length of the string to read.</param>
            /// <returns></returns>
            /// 12/22/2008 4:43 PM
            public string ReadString(uint address, bool ascii, int length)
            {
                return ascii
                           ? GetReader.ReadASCIIString(address, length).Trim()
                           : GetReader.ReadUnicodeString(address, length).Trim();
            }
    
            public byte[] ReadBytes(uint address, int size)
            {
                return GetReader.ReadBytes(address, size);
            }
    
            #endregion
    
            #region Write
    
            public bool Write<T>(uint offset, T value)
            {
                return _Write(offset, value, typeof (T));
            }
    
            private bool _Write(uint address, object value, Type t)
            {
                switch (Type.GetTypeCode(t))
                {
                    case TypeCode.SByte:
                        return GetWriter.WriteSByte(address, (sbyte) value);
                    case TypeCode.Byte:
                        return GetWriter.WriteByte(address, (byte) value);
                    case TypeCode.Int16:
                        return GetWriter.WriteShort(address, (short) value);
                    case TypeCode.UInt16:
                        return GetWriter.WriteUShort(address, (ushort) value);
                    case TypeCode.Int32:
                        return GetWriter.WriteInt(address, (int) value);
                    case TypeCode.UInt32:
                        return GetWriter.WriteUInt(address, (uint) value);
                    case TypeCode.Int64:
                        return GetWriter.WriteInt64(address, (long) value);
                    case TypeCode.UInt64:
                        return GetWriter.WriteUInt64(address, (ulong) value);
                    case TypeCode.Single:
                        return GetWriter.WriteFloat(address, (float) value);
                    case TypeCode.Double:
                        return GetWriter.WriteDouble(address, (double) value);
                    default:
                        return GetWriter.WriteObject(address, value);
                }
            }
    
            /// <summary>
            /// Reads a string from memory. The default length is 255. (MAX_LEN in C++)
            /// </summary>
            /// <param name="address">The address to read the string from.</param>
            /// <param name="value"></param>
            /// <param name="ascii">if set to <c>true</c> the string will be read as an ASCII string. Otherwise it will be read as Unicode.</param>
            /// <returns></returns>
            /// 12/22/2008 4:42 PM
            public bool WriteString(uint address, string value, bool ascii)
            {
                return ascii
                           ? GetWriter.WriteASCIIString(address, value)
                           : GetWriter.WriteUnicodeString(address, value);
            }
    
            public bool WriteBytes(uint address, byte[] value)
            {
                return GetWriter.WriteBytes(address, value);
            }
    
            #endregion
    
            #region CreateCodeCave
    
            public CodeCave CreateCodeCave(int size)
            {
                return CreateCodeCave(size, MemoryAllocType.MEM_COMMIT, MemoryProtectType.PAGE_EXECUTE_READWRITE);
            }
    
            public CodeCave CreateCodeCave()
            {
                return CreateCodeCave(Constants.DEFAULT_MEMORY_SIZE, MemoryAllocType.MEM_COMMIT,
                                      MemoryProtectType.PAGE_EXECUTE_READWRITE);
            }
    
            public CodeCave CreateCodeCave(int size, MemoryAllocType memoryAllocType)
            {
                return CreateCodeCave(size, memoryAllocType, MemoryProtectType.PAGE_EXECUTE_READWRITE);
            }
    
            public CodeCave CreateCodeCave(int size, MemoryAllocType memoryAllocType, MemoryProtectType memoryProtectType)
            {
                return new CodeCave(this, size, memoryAllocType, memoryProtectType);
            }
    
            #endregion
    CodeCave class. (See the comments for what it's used for. And yes, I purposely abstracted another layer on the FASM implementation. So when I use my Voodoo lib, I don't have to require the FASM reference on the main project. Again, see the comments.)

    Code:
    using System;
    using System.Collections.Generic;
    using Fasm;
    using Voodoo.Native;
    
    namespace Voodoo
    {
        /// <summary>
        /// This class holds a simple wrapper for the FASM DLL provided by Shynd, and Tomasz Grysztar, with a small twist.
        /// This class allows you to dynamically create a code cave, and release the allocated memory once the class loses
        /// scope. So it is very valid for the following to happen: 
        /// using (CodeCave cc = myMemoryManager.CreateCodeCave()) { /* Code Here */ }
        /// The required memory size is allocated in the constructor, and freed once the object is disposed.
        /// There is no need to remember to allocate/free memory!
        /// 
        /// This class exposes the main pieces of the FASM DLL so that you will not need to add a reference
        /// to it in your actual project. This is also to keep in compliance with .NET standards so if this library
        /// is ever updated, we can simply pop in a different DLL, and not worry about having everyone update their
        /// applications with the new API and references.
        /// </summary>
        /// 12/22/2008 10:50 PM
        public class CodeCave : IDisposable
        {
            private readonly uint allocatedMemory;
            private readonly int allocSize;
            private readonly ManagedFasm fasm;
            private readonly IntPtr memoryHandle = IntPtr.Zero;
            private readonly MemoryManager mgr;
    
            /// <summary>
            /// Gets the address where this <see cref="CodeCave"/> starts.
            /// </summary>
            /// <value>The allocation address.</value>
            /// 12/24/2008 2:47 PM
            public uint AllocationAddress { get { return allocatedMemory; } }
    
            #region Ctors
    
            internal CodeCave(MemoryManager memoryManager, int size, MemoryAllocType allocationType,
                              MemoryProtectType protectType)
                : this(memoryManager.ProcessHandle, size, allocationType, protectType)
            {
                mgr = memoryManager;
            }
    
            internal CodeCave(IntPtr processMemoryHandle, int size, MemoryAllocType memoryAllocType,
                              MemoryProtectType protectType)
            {
                memoryHandle = processMemoryHandle;
                allocSize = size;
                allocatedMemory = Win32.VirtualAllocEx(memoryHandle, 0, size, (uint) memoryAllocType, (uint) protectType);
                fasm = new ManagedFasm(memoryHandle);
                fasm.SetMemorySize(size);
            }
    
            internal CodeCave(IntPtr processMemoryHandle, int size, MemoryAllocType memoryAllocType)
                : this(processMemoryHandle, size, memoryAllocType, MemoryProtectType.PAGE_EXECUTE_READWRITE) {}
    
            internal CodeCave(IntPtr processMemoryHandle, int size, MemoryProtectType memoryProtectType)
                : this(processMemoryHandle, size, MemoryAllocType.MEM_COMMIT, memoryProtectType) {}
    
            internal CodeCave(IntPtr processMemoryHandle, int size)
                : this(processMemoryHandle, size, MemoryAllocType.MEM_COMMIT, MemoryProtectType.PAGE_EXECUTE_READWRITE) {}
    
            internal CodeCave(IntPtr processMemoryHandle)
                : this(
                    processMemoryHandle, Constants.DEFAULT_MEMORY_SIZE, MemoryAllocType.MEM_COMMIT,
                    MemoryProtectType.PAGE_EXECUTE_READWRITE) {}
    
            internal CodeCave(IntPtr processMemoryHandle, MemoryAllocType allocType, MemoryProtectType protectType)
                : this(processMemoryHandle, Constants.DEFAULT_MEMORY_SIZE, allocType, protectType) {}
    
            internal CodeCave(IntPtr processMemoryHandle, MemoryAllocType allocType)
                : this(
                    processMemoryHandle, Constants.DEFAULT_MEMORY_SIZE, allocType, MemoryProtectType.PAGE_EXECUTE_READWRITE) {}
    
            internal CodeCave(IntPtr processMemoryHandle, MemoryProtectType protectType)
                : this(processMemoryHandle, Constants.DEFAULT_MEMORY_SIZE, MemoryAllocType.MEM_COMMIT, protectType) {}
    
            ~CodeCave()
            {
                Dispose();
            }
    
            #endregion
    
            #region Implementation of IDisposable
    
            /// <summary>
            /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
            /// </summary>
            /// <filterpriority>2</filterpriority>
            public void Dispose()
            {
                Win32.VirtualFreeEx(memoryHandle, allocatedMemory, allocSize, (uint) MemoryFreeType.MEM_RELEASE);
                GC.SuppressFinalize(this);
            }
    
            #endregion
    
            #region FASM Wrapper
    
            /// <summary>
            /// Gets the underlying ManagedFasm object. Use this only if you plan on adding a 
            /// reference to the Managed FASM DLL in your main project!
            /// </summary>
            /// <value>The get asm.</value>
            /// 12/22/2008 11:04 PM
            public ManagedFasm GetAsm { get { return fasm; } }
    
            /// <summary>
            /// Gets or sets the size of the memory allocated for the FASM object.
            /// </summary>
            /// <value>The size of the get asm memory.</value>
            /// 12/22/2008 11:05 PM
            public int GetAsmMemorySize { get { return fasm.GetMemorySize(); } set { fasm.SetMemorySize(value); } }
    
            /// <summary>
            /// Gets or sets the process handle the FASM object is set to use.
            /// </summary>
            /// <value>The get asm process handle.</value>
            /// 12/22/2008 11:05 PM
            public IntPtr GetAsmProcessHandle { get { return fasm.GetProcessHandle(); } set { fasm.SetProcessHandle(value); } }
    
            /// <summary>
            /// Gets or sets the get asm pass limit.
            /// </summary>
            /// <value>The get asm pass limit.</value>
            /// 12/22/2008 11:06 PM
            public int GetAsmPassLimit { get { return fasm.GetPassLimit(); } set { fasm.SetPassLimit(value); } }
    
            #region AddLine
    
            /// <summary>
            /// Adds a line of ASM to the current FASM buffer.
            /// </summary>
            /// <param name="line">The line.</param>
            /// <param name="args">The args.</param>
            /// 12/22/2008 11:06 PM
            public void AsmAddLine(string line, params object[] args)
            {
                fasm.AddLine(string.Format(line, args));
            }
    
            public void AsmAddLine(params string[] lines)
            {
                foreach (string line in lines)
                {
                    fasm.AddLine(line);
                }
            }
    
            public void AsmAddLine(IList<string> lines)
            {
                foreach (string line in lines)
                {
                    fasm.AddLine(line);
                }
            }
    
            public void AsmAddLine(IEnumerable<string> lines)
            {
                foreach (string line in lines)
                {
                    fasm.AddLine(line);
                }
            }
    
            #endregion
    
            #region Add
    
            public void AsmAdd(string asm, params object[] args)
            {
                fasm.Add(asm, args);
            }
    
            #endregion
    
            #region Assemble
    
            public byte[] AsmAssemble()
            {
                return fasm.Assemble();
            }
    
            #endregion
    
            #region Clear
    
            public void AsmClear()
            {
                fasm.Clear();
            }
    
            #endregion
    
            #region Inject
    
            public bool AsmInject()
            {
                return AsmInject(allocatedMemory);
            }
    
            public bool AsmInject(uint address)
            {
                // FASM EXECUTOR
                return fasm.Inject(address);
            }
    
            #endregion
    
            #region Inesert InsertLine
    
            public void AsmInsertLine(int index, string line, params object[] args)
            {
                fasm.InsertLine(string.Format(line, args), index);
            }
    
            public void AsmInsert(int index, string asm, params object[] args)
            {
                fasm.Insert(string.Format(asm, args), index);
            }
    
            #endregion
    
            #region AsmInjectAndExecute
    
            #region No address/param
    
            public uint AsmInjectAndExecute()
            {
                return AsmInjectAndExecute(allocatedMemory, 0);
            }
    
            public uint AsmInjectAndExecute(params string[] lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute();
            }
    
            public uint AsmInjectAndExecute(IList<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute();
            }
    
            public uint AsmInjectAndExecute(IEnumerable<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute();
            }
    
            #endregion
    
            #region Address
    
            public uint AsmInjectAndExecute(uint address)
            {
                return AsmInjectAndExecute(address, 0);
            }
    
            public uint AsmInjectAndExecute(uint address, params string[] lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute(address);
            }
    
            public uint AsmInjectAndExecute(uint address, IList<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute(address);
            }
    
            public uint AsmInjectAndExecute(uint address, IEnumerable<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute(address);
            }
    
            #endregion
    
            #region Address and Parameter
    
            public uint AsmInjectAndExecute(uint address, uint parameter)
            {
                // FASM EXECUTOR
                return fasm.InjectAndExecute(memoryHandle, address, parameter);
            }
    
            public uint AsmInjectAndExecute(uint address, uint parameter, params string[] lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute(address, parameter);
            }
    
            public uint AsmInjectAndExecute(uint address, uint parameter, IList<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute(address, parameter);
            }
    
            public uint AsmInjectAndExecute(uint address, uint parameter, IEnumerable<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecute(address, parameter);
            }
    
            #endregion
    
            #endregion
    
            #region AsmInjectAndExecuteEx
    
            #region No Params
    
            public IntPtr AsmInjectAndExecuteEx()
            {
                return AsmInjectAndExecuteEx(allocatedMemory, 0);
            }
    
            public IntPtr AsmInjectAndExecuteEx(params string[] lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx();
            }
    
            public IntPtr AsmInjectAndExecuteEx(IList<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx();
            }
    
            public IntPtr AsmInjectAndExecuteEx(IEnumerable<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx();
            }
    
            #endregion
    
            #region Address
    
            public IntPtr AsmInjectAndExecuteEx(uint address)
            {
                return AsmInjectAndExecuteEx(address, 0);
            }
    
            public IntPtr AsmInjectAndExecuteEx(uint address, params string[] lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx(address);
            }
    
            public IntPtr AsmInjectAndExecuteEx(uint address, IList<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx(address);
            }
    
            public IntPtr AsmInjectAndExecuteEx(uint address, IEnumerable<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx(address);
            }
    
            #endregion
    
            #region Address and Param
    
            public IntPtr AsmInjectAndExecuteEx(uint address, uint parameter)
            {
                // FASM EXECUTOR
                return fasm.InjectAndExecuteEx(memoryHandle, address, parameter);
            }
    
            public IntPtr AsmInjectAndExecuteEx(uint address, uint parameter, params string[] lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx(address, parameter);
            }
    
            public IntPtr AsmInjectAndExecuteEx(uint address, uint parameter, IList<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx(address, parameter);
            }
    
            public IntPtr AsmInjectAndExecuteEx(uint address, uint parameter, IEnumerable<string> lines)
            {
                AsmAddLine(lines);
                return AsmInjectAndExecuteEx(address, parameter);
            }
    
            #endregion
    
            #endregion
    
            #endregion
    
            #region Read/Write Stuff
    
            #region Read
    
            /// <summary>
            /// Reads the specified offsets. TODO: Add proper comments...
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="offsets">The offsets.</param>
            /// <returns></returns>
            /// 12/22/2008 6:41 PM
            public T Read<T>(params uint[] offsets)
            {
                return mgr.Read<T>(offsets);
            }
    
            /// <summary>
            /// Reads a string from memory. The default length is 255. (MAX_LEN in C++)
            /// </summary>
            /// <param name="address">The address to read the string from.</param>
            /// <param name="ascii">if set to <c>true</c> the string will be read as an ASCII string. Otherwise it will be read as Unicode.</param>
            /// <returns></returns>
            /// 12/22/2008 4:42 PM
            public string ReadString(uint address, bool ascii)
            {
                return mgr.ReadString(address, ascii);
            }
    
            /// <summary>
            /// Reads a string from memory.
            /// </summary>
            /// <param name="address">The address to read the string from.</param>
            /// <param name="ascii">if set to <c>true</c> the string will be read as an ASCII string. Otherwise it will be read as Unicode.</param>
            /// <param name="length">The length of the string to read.</param>
            /// <returns></returns>
            /// 12/22/2008 4:43 PM
            public string ReadString(uint address, bool ascii, int length)
            {
                return mgr.ReadString(address, ascii, length);
            }
    
            public byte[] ReadBytes(uint address, int size)
            {
                return mgr.ReadBytes(address, size);
            }
    
            #endregion
    
            #region Write
    
            public bool Write<T>(uint offset, T value)
            {
                return mgr.Write(offset, value);
            }
    
            /// <summary>
            /// Writes a string to memory.
            /// </summary>
            /// <param name="address">The address to read the string from.</param>
            /// <param name="value"></param>
            /// <param name="ascii">if set to <c>true</c> the string will be written as an ASCII string. Otherwise it will be written as Unicode.</param>
            /// <returns></returns>
            /// 12/22/2008 4:42 PM
            public bool WriteString(uint address, string value, bool ascii)
            {
                return mgr.WriteString(address, value, ascii);
            }
    
            /// <summary>
            /// Writes a string to memory. This writes to the <see cref="AllocationAddress"/> of this <see cref="CodeCave"/>.
            /// </summary>
            /// <param name="value"></param>
            /// <param name="ascii">if set to <c>true</c> the string will be written as an ASCII string. Otherwise it will be written as Unicode.</param>
            /// <returns></returns>
            /// 12/22/2008 4:42 PM
            public bool WriteString(string value, bool ascii)
            {
                return mgr.WriteString(allocatedMemory, value, ascii);
            }
    
            public bool WriteBytes(uint address, byte[] value)
            {
                return mgr.WriteBytes(address, value);
            }
    
            #endregion
    
            #endregion
        }
    }
    Properly laid out Win32 enums/structs.

    Code:
    using System;
    using System.Runtime.InteropServices;
    
    namespace Voodoo.Native
    {
        /// <summary>
        /// Values to gain required access to process or thread.
        /// </summary>
        [Flags]
        public enum AccessRights : uint
        {
            /// <summary>
            /// Standard rights required to mess with an object's security descriptor, change, or delete the object.
            /// </summary>
            STANDARD_RIGHTS_REQUIRED = 0x000F0000,
            /// <summary>
            /// The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state. Some object types do not support this access right.
            /// </summary>
            SYNCHRONIZE = 0x00100000,
            /// <summary>
            /// Required to terminate a process using TerminateProcess.
            /// </summary>
            PROCESS_TERMINATE = 0x0001,
            /// <summary>
            /// Required to create a thread.
            /// </summary>
            PROCESS_CREATE_THREAD = 0x0002,
            //public const uint PROCESS_SET_SESSIONID = 0x0004,
            /// <summary>
            /// Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
            /// </summary>
            PROCESS_VM_OPERATION = 0x0008,
            /// <summary>
            /// Required to read memory in a process using ReadProcessMemory.
            /// </summary>
            PROCESS_VM_READ = 0x0010,
            /// <summary>
            /// Required to write memory in a process using WriteProcessMemory.
            /// </summary>
            PROCESS_VM_WRITE = 0x0020,
            /// <summary>
            /// Required to duplicate a handle using DuplicateHandle.
            /// </summary>
            PROCESS_DUP_HANDLE = 0x0040,
            /// <summary>
            /// Required to create a process.
            /// </summary>
            PROCESS_CREATE_PROCESS = 0x0080,
            /// <summary>
            /// Required to set memory limits using SetProcessWorkingSetSize.
            /// </summary>
            PROCESS_SET_QUOTA = 0x0100,
            /// <summary>
            /// Required to set certain information about a process, such as its priority class (see SetPriorityClass).
            /// </summary>
            PROCESS_SET_INFORMATION = 0x0200,
            /// <summary>
            /// Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob).
            /// </summary>
            PROCESS_QUERY_INFORMATION = 0x0400,
            /// <summary>
            /// Required to suspend or resume a process.
            /// </summary>
            PROCESS_SUSPEND_RESUME = 0x0800,
            /// <summary>
            /// Required to retrieve certain information about a process (see QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.
            /// </summary>
            PROCESS_QUERY_LIMITED_INFORMATION = 0x1000,
            /// <summary>
            /// All possible access rights for a process object. (Windows Vista/Server 2k8 Specific)
            /// </summary>
            PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF,
            /// <summary>
            /// All possible access rights for a process object. (Windows XP specific)
            /// </summary>
            PROCESS_ALL_ACCESS_WINXP = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x001F0FFF,
            /// <summary>
            /// Required to terminate a thread using TerminateThread.
            /// </summary>
            THREAD_TERMINATE = 0x0001,
            /// <summary>
            /// Required to suspend or resume a thread.
            /// </summary>
            THREAD_SUSPEND_RESUME = 0x0002,
            /// <summary>
            /// Required to read the context of a thread using GetThreadContext
            /// </summary>
            THREAD_GET_CONTEXT = 0x0008,
            /// <summary>
            /// Required to set the context of a thread using SetThreadContext
            /// </summary>
            THREAD_SET_CONTEXT = 0x0010,
            /// <summary>
            /// Required to read certain information from the thread object, such as the exit code (see GetExitCodeThread).
            /// </summary>
            THREAD_QUERY_INFORMATION = 0x0040,
            /// <summary>
            /// Required to set certain information in the thread object.
            /// </summary>
            THREAD_SET_INFORMATION = 0x0020,
            /// <summary>
            /// Required to set the impersonation token for a thread using SetThreadToken.
            /// </summary>
            THREAD_SET_THREAD_TOKEN = 0x0080,
            /// <summary>
            /// Required to use a thread's security information directly without calling it by using a communication mechanism that provides impersonation services.
            /// </summary>
            THREAD_IMPERSONATE = 0x0100,
            /// <summary>
            /// Required for a server thread that impersonates a client.
            /// </summary>
            THREAD_DIRECT_IMPERSONATION = 0x0200,
            /// <summary>
            /// All possible access rights for a thread object.
            /// </summary>
            THREAD_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3FF
        }
    
        /// <summary>
        /// Values that determine how memory is allocated.
        /// </summary>
        [Flags]
        public enum MemoryAllocType
        {
            /// <summary>
            /// Allocates physical storage in memory or in the paging file on disk for the specified reserved memory pages. The function initializes the memory to zero. 
            ///
            ///To reserve and commit pages in one step, call VirtualAllocEx with MEM_COMMIT | MEM_RESERVE.
            ///
            ///The function fails if you attempt to commit a page that has not been reserved. The resulting error code is ERROR_INVALID_ADDRESS.
            ///
            ///An attempt to commit a page that is already committed does not cause the function to fail. This means that you can commit pages without first determining the current commitment state of each page.
            /// </summary>
            MEM_COMMIT = 0x00001000,
            /// <summary>
            /// Reserves a range of the process's virtual address space without allocating any actual physical storage in memory or in the paging file on disk.
            ///
            ///You commit reserved pages by calling VirtualAllocEx again with MEM_COMMIT.
            /// </summary>
            MEM_RESERVE = 0x00002000,
            /// <summary>
            /// Indicates that data in the memory range specified by lpAddress and dwSize is no longer of interest. The pages should not be read from or written to the paging file. However, the memory block will be used again later, so it should not be decommitted. This value cannot be used with any other value.
            ///
            ///Using this value does not guarantee that the range operated on with MEM_RESET will contain zeroes. If you want the range to contain zeroes, decommit the memory and then recommit it.
            /// </summary>
            MEM_RESET = 0x00080000,
            /// <summary>
            /// Reserves an address range that can be used to map Address Windowing Extensions (AWE) pages.
            ///
            ///This value must be used with MEM_RESERVE and no other values.
            /// </summary>
            MEM_PHYSICAL = 0x00400000,
            /// <summary>
            /// Allocates memory at the highest possible address. 
            /// </summary>
            MEM_TOP_DOWN = 0x00100000
        }
    
        /// <summary>
        /// Values that determine how a block of memory is protected.
        /// </summary>
        [Flags]
        public enum MemoryProtectType
        {
            /// <summary>
            /// Enables execute access to the committed region of pages. An attempt to read or write to the committed region results in an access violation. 
            /// </summary>
            PAGE_EXECUTE = 0x10,
            /// <summary>
            /// Enables execute and read access to the committed region of pages. An attempt to write to the committed region results in an access violation. 
            /// </summary>
            PAGE_EXECUTE_READ = 0x20,
            /// <summary>
            /// Enables execute, read, and write access to the committed region of pages. 
            /// </summary>
            PAGE_EXECUTE_READWRITE = 0x40,
            /// <summary>
            /// Enables execute, read, and write access to the committed region of image file code pages. The pages are shared read-on-write and copy-on-write. 
            /// </summary>
            PAGE_EXECUTE_WRITECOPY = 0x80,
            /// <summary>
            /// Disables all access to the committed region of pages. An attempt to read from, write to, or execute the committed region results in an access violation exception, called a general protection (GP) fault. 
            /// </summary>
            PAGE_NOACCESS = 0x01,
            /// <summary>
            /// Enables read access to the committed region of pages. An attempt to write to the committed region results in an access violation. If the system differentiates between read-only access and execute access, an attempt to execute code in the committed region results in an access violation.
            /// </summary>
            PAGE_READONLY = 0x02,
            /// <summary>
            /// Enables both read and write access to the committed region of pages.
            /// </summary>
            PAGE_READWRITE = 0x04,
            /// <summary>
            /// Gives copy-on-write protection to the committed region of pages. 
            /// </summary>
            PAGE_WRITECOPY = 0x08,
            /// <summary>
            ///Pages in the region become guard pages. Any attempt to access a guard page causes the system to raise a STATUS_GUARD_PAGE_VIOLATION exception and turn off the guard page status. Guard pages thus act as a one-time access alarm. For more information, see Creating Guard Pages.
            ///
            ///When an access attempt leads the system to turn off guard page status, the underlying page protection takes over.
            ///
            ///If a guard page exception occurs during a system service, the service typically returns a failure status indicator.
            ///
            ///This value cannot be used with PAGE_NOACCESS.
            /// </summary>
            PAGE_GUARD = 0x100,
            /// <summary>
            /// Does not allow caching of the committed regions of pages in the CPU cache. The hardware attributes for the physical memory should be specified as "no cache." This is not recommended for general usage. It is useful for device drivers, for example, mapping a video frame buffer with no caching.
            ///
            ///This value cannot be used with PAGE_NOACCESS.
            /// </summary>
            PAGE_NOCACHE = 0x200,
            /// <summary>
            /// Enables write-combined memory accesses. When enabled, the processor caches memory write requests to optimize performance. Thus, if two requests are made to write to the same memory address, only the more recent write may occur.
            ///
            ///Note that the PAGE_GUARD and PAGE_NOCACHE flags cannot be specified with PAGE_WRITECOMBINE. If an attempt is made to do so, the SYSTEM_INVALID_PAGE_PROTECTION NT error code is returned by the function.
            /// </summary>
            PAGE_WRITECOMBINE = 0x400,
        }
    
        /// <summary>
        /// Values that determine how a block of memory is freed.
        /// </summary>
        [Flags]
        public enum MemoryFreeType
        {
            /// <summary>
            /// Decommits the specified region of committed pages. After the operation, the pages are in the reserved state.
            ///
            ///The function does not fail if you attempt to decommit an uncommitted page. This means that you can decommit a range of pages without first determining their current commitment state.
            ///
            ///Do not use this value with MEM_RELEASE.
            /// </summary>
            MEM_DECOMMIT = 0x4000,
            /// <summary>
            /// Releases the specified region of pages. After the operation, the pages are in the free state.
            ///
            /// If you specify this value, dwSize must be 0 (zero), and lpAddress must point to the base address returned by the VirtualAllocEx function when the region is reserved. The function fails if either of these conditions is not met.
            ///
            /// If any pages in the region are committed currently, the function first decommits, and then releases them.
            ///
            /// The function does not fail if you attempt to release pages that are in different states, some reserved and some committed. This means that you can release a range of pages without first determining the current commitment state.
            ///
            /// Do not use this value with MEM_DECOMMIT.
            /// </summary>
            MEM_RELEASE = 0x8000
        }
    
        /// <summary>
        /// Values which determine the state or creation-state of a thread.
        /// </summary>
        [Flags]
        public enum ThreadFlags
        {
            /// <summary>
            /// The thread will execute immediately.
            /// </summary>
            THREAD_EXECUTE_IMMEDIATELY = 0,
            /// <summary>
            /// The thread will be created in a suspended state.  Use ResumeThread to resume the thread.
            /// </summary>
            CREATE_SUSPENDED = 0x04,
            /// <summary>
            /// The dwStackSize parameter specifies the initial reserve size of the stack. If this flag is not specified, dwStackSize specifies the commit size.
            /// </summary>
            STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000,
            /// <summary>
            /// The thread is still active.
            /// </summary>
            STILL_ACTIVE = 259,
        }
    
        /// <summary>
        /// Values that determine the wait status of an object (thread, mutex, event, etc.).
        /// </summary>
        public enum WaitValues : uint
        {
            /// <summary>
            /// The object is in a signaled state.
            /// </summary>
            WAIT_OBJECT_0 = 0x00000000,
            /// <summary>
            /// The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled.
            /// </summary>
            WAIT_ABANDONED = 0x00000080,
            /// <summary>
            /// The time-out interval elapsed, and the object's state is nonsignaled.
            /// </summary>
            WAIT_TIMEOUT = 0x00000102,
            /// <summary>
            /// The wait has failed.
            /// </summary>
            WAIT_FAILED = 0xFFFFFFFF,
            /// <summary>
            /// Wait an infinite amount of time for the object to become signaled.
            /// </summary>
            INFINITE = 0xFFFFFFFF,
        }
    
        /// <summary>
        /// Determines which registers are returned or set when using GetThreadContext or SetThreadContext.
        /// </summary>
        public enum CONTEXT_FLAGS
        {
            /// <summary>
            /// DO NOT USE! For internal context settings!
            /// </summary>
            CONTEXT_i386 = 0x00010000,
            /// <summary>
            /// SS:SP, CS:IP, FLAGS, BP
            /// </summary>
            CONTEXT_CONTROL = (CONTEXT_i386 | 0x01),
            /// <summary>
            /// AX, BX, CX, DX, SI, DI
            /// </summary>
            CONTEXT_INTEGER = (CONTEXT_i386 | 0x02),
            /// <summary>
            /// DS, ES, FS, GS
            /// </summary>
            CONTEXT_SEGMENTS = (CONTEXT_i386 | 0x04),
            /// <summary>
            /// 387 state
            /// </summary>
            CONTEXT_FLOATING_POINT = (CONTEXT_i386 | 0x08),
            /// <summary>
            /// DB 0-3,6,7
            /// </summary>
            CONTEXT_DEBUG_REGISTERS = (CONTEXT_i386 | 0x10),
            /// <summary>
            /// cpu specific extensions
            /// </summary>
            CONTEXT_EXTENDED_REGISTERS = (CONTEXT_i386 | 0x20),
            /// <summary>
            /// Everything but extended information and debug registers.
            /// </summary>
            CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS),
            /// <summary>
            /// Everything.
            /// </summary>
            CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS |
                           CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS |
                           CONTEXT_EXTENDED_REGISTERS),
        }
    }
    And a quickie property for getting/setting the current working process' MainWindowTitle. (Note, you'll need the SendMessage stuff. That's what Sender is. Just a wrapper around SendMessage)

    Code:
            /// <summary>
            /// Gets or sets the main window title of the process. 
            /// (Note: if the process' MainWindowHandle == IntPtr.Zero, setting this property does nothing!)
            /// </summary>
            /// <value>The main window title.</value>
            /// 12/22/2008 4:46 PM
            public string MainWindowTitle
            {
                get { return WorkingProcess.MainWindowTitle; }
                set
                {
                    if (WorkingProcess.MainWindowTitle != value && WorkingProcess.MainWindowHandle != IntPtr.Zero)
                    {
                        StringBuilder sb = new StringBuilder(value);
                        Sender.SendMessage(WorkingProcess.MainWindowHandle, (int) SendMessageParam.WM_SETTEXT, IntPtr.Zero, sb);
                    }
                }
            }
    Quick SendMessage class and whatnot.

    Code:
    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Text;
    
    namespace Voodoo.Native.SendMessageAPI
    {
        [StructLayout(LayoutKind.Sequential)]
        internal struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
    
        internal class Sender
        {
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, StringBuilder lParam);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, String lParam);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
            internal static extern void SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref RECT lParam);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
            internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref Point lParam);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
        }
    }
    Enjoy folks.

    Some C# memory reading stuff I had laying around.
  2. #2
    luciferc's Avatar Contributor
    Reputation
    90
    Join Date
    Jul 2008
    Posts
    373
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    very nice apoc +Rep

    I like it that you have the all in one method for reading the Pointers the most :P.

  3. #3
    SKU's Avatar Contributor
    Reputation
    306
    Join Date
    May 2007
    Posts
    565
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Lovely, thanks for the share.

  4. #4
    sebdoingbot's Avatar Member
    Reputation
    1
    Join Date
    Aug 2008
    Posts
    20
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nices and Clean classes.
    the Template Reading classe is elegant

  5. #5
    JuJuBoSc's Avatar Banned for scamming CoreCoins Purchaser
    Reputation
    1019
    Join Date
    May 2007
    Posts
    922
    Thanks G/R
    1/3
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice stuff to dev a bot, we see ob.net is here

  6. #6
    bhpushnslide's Avatar Member
    Reputation
    5
    Join Date
    Feb 2009
    Posts
    28
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What is GetReader referring to? Does this still use blackmagic? I tried using MemoryLib but ReadSByte etc takes more than one argument. ..

    sorry for a stupid question.

  7. #7
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by bhpushnslide View Post
    What is GetReader referring to? Does this still use blackmagic? I tried using MemoryLib but ReadSByte etc takes more than one argument. ..

    sorry for a stupid question.
    GetReader is just a wrapper around memory reading routines.

    If you can't figure out how to change the code to match what you're working with, you probably shouldn't even be in this section.

  8. #8
    bhpushnslide's Avatar Member
    Reputation
    5
    Join Date
    Feb 2009
    Posts
    28
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Apoc View Post
    GetReader is just a wrapper around memory reading routines.

    If you can't figure out how to change the code to match what you're working with, you probably shouldn't even be in this section.
    I got it working.. I just used to to wrap around blackmagic so i can use your incremental read functions.

    +REP for the code

Similar Threads

  1. Some "simple" questions regarding memory reading!
    By sYpro in forum WoW Memory Editing
    Replies: 4
    Last Post: 08-07-2014, 12:20 PM
  2. Replies: 2
    Last Post: 04-08-2012, 12:03 AM
  3. [C#]Need help with some memory reading
    By jazerix in forum Programming
    Replies: 1
    Last Post: 10-29-2010, 09:49 AM
  4. [AutoIT3] WoW Cordinator (X,Y,MapID and rotation memory reading)
    By Vladinator in forum World of Warcraft Bots and Programs
    Replies: 22
    Last Post: 05-15-2007, 03:26 AM
All times are GMT -5. The time now is 03:42 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search