I've seen many posts on MPGH and others sites/forums of people requesting help with C# WriteProcessMemory and ReadProcessMemory. Further digging on google and Found a lot of Classes made by others for this purpose. I tested a bunch of them and found them not functional or buggy. Most of them did not automatically add offsets. Granted i found a couple classes out there that actually worked, but there were pretty messy and was converting alot of variables from bytes to hex back hex to decs blah blah blah. So I gave up on the lazy route and made this one that more then suits what purposes i need it for. And since Ive never really tributed anything to MPGH here is a Memory Read/Write Class.
After looking over so many different examples I got alot of the ideas from them, but mostly take full credit of this.

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace PointerChecker
{
    public class MemoryHandler
    {
        #region Properties
        private string m_ProcessName;
        private Process[] m_Processes;
        private Process m_TargetProcess;
        private int m_TProcessId;
        private IntPtr m_TProcessAddress;
        private IntPtr m_TProcessHandle;

        public string ProcessName { get { return m_ProcessName; } set { m_ProcessName = value; } }
        public Process[] Processes { get { return m_Processes; } set { m_Processes = value; } }
        public Process TargetProcess { get { return m_TargetProcess; } set { m_TargetProcess = value; } }
        public IntPtr TProcessAddress { get { return m_TProcessAddress; } set { m_TProcessAddress = value; } }
        public IntPtr TProcessHandle { get { return m_TProcessHandle; } set { m_TProcessHandle = value; } }
        public int TProcessId { get { return m_TProcessId; } set { m_TProcessId = value; } }
        #endregion




        public bool LoadMemory(String TProcessName)
        {
            Process[] tmpList;
            tmpList = Process.GetProcessesByName(TProcessName);
            if (tmpList.Length != 0)
            {
                m_ProcessName = TProcessName;
                m_Processes = Process.GetProcesses();
                m_TargetProcess = tmpList.FirstOrDefault();
                m_TProcessAddress = m_TargetProcess.MainModule.BaseAddress;
                m_TProcessId = m_TargetProces*****;


                return true;
            }
            else
                return false;
        }


        public byte[] ReadMemory(int[] offs)
        {
            byte[] OutSource = new byte[20];
            byte[] addBuffer = new byte[4];
            int readOut = 0;
            int Count = offs.Length - 1;
            IntPtr tmpAdd = IntPtr.Zero;

            Open();

            if (Count == 0)//If Only One Offset
            {

                ReadProcessMemory(m_TProcessHandle, IntPtr.Add(m_TProcessAddress, offs[0]), OutSource, 20, out readOut);
                return OutSource;
            }

            for (int i = 0; i <= Count; i++)
            {
                if (i == Count)
                {
                    ReadProcessMemory(m_TProcessHandle, IntPtr.Add(tmpAdd, offs[offs.Length - 1]), OutSource, 1064, out readOut);
                    tmpAdd = IntPtr.Add(tmpAdd, offs[i]);
                    Close();
                    return OutSource;
                }

                else if (i == 0)
                {
                    ReadProcessMemory(m_TProcessHandle, IntPtr.Add(m_TProcessAddress, offs[i]), addBuffer, 4, out readOut);
                    tmpAdd = (IntPtr)BitConverter.ToInt32(addBuffer, 0);
                }

                else
                {
                    ReadProcessMemory(m_TProcessHandle, IntPtr.Add(tmpAdd, offs[i]), addBuffer, 4, out readOut);
                    tmpAdd = (IntPtr)BitConverter.ToInt32(addBuffer, 0);
                }

            }

            Close();

            return OutSource;
        }


        public void WriteMemory(int[] offs, byte[] WriteBuffer)
        {

            int bytesWritten = 0;
            int bytesRead = 0;
            int Counter = offs.Length - 1;
            IntPtr tmpAdd = IntPtr.Zero;
            byte[] addBuffer = new byte[4];
            byte[] ReadBuffer = new byte[30];

            Open();

            if (Counter == 0)
            {
                ReadProcessMemory(m_TProcessHandle, IntPtr.Add(m_TProcessAddress, offs[0]), addBuffer, 4, out bytesRead);
            }

            for (int i = 0; i <= Counter; i++)
            {
                if (i == Counter)
                {
                    WriteProcessMemory(m_TProcessHandle, IntPtr.Add(tmpAdd, offs[i]), WriteBuffer, (uint)WriteBuffer.Length, out bytesWritten);
                }

                else if (i == 0)
                {
                    ReadProcessMemory(m_TProcessHandle, IntPtr.Add(m_TProcessAddress, offs[i]), addBuffer, 4, out bytesRead);
                    tmpAdd = (IntPtr)BitConverter.ToInt32(addBuffer, 0);
                }

                else
                {
                    ReadProcessMemory(m_TProcessHandle, IntPtr.Add(tmpAdd, offs[i]), addBuffer, 4, out bytesRead);
                    tmpAdd = (IntPtr)BitConverter.ToInt32(addBuffer, 0);
                }
            }

            Close();
        }


        public void Open()
        {
            m_TProcessHandle = OpenProcess((uint)ProcessAccessType.PROCESS_ALL_ACCESS, 0, (uint)m_TProcessId);
        }


        public void Close()
        {
            CloseHandle(TProcessHandle);
        }



        [Flags]
        public enum ProcessAccessType
        {
            PROCESS_TERMINATE = (0x0001),
            PROCESS_CREATE_THREAD = (0x0002),
            PROCESS_SET_SESSIONID = (0x0004),
            PROCESS_VM_OPERATION = (0x0008),
            PROCESS_VM_READ = (0x0010),
            PROCESS_VM_WRITE = (0x0020),
            PROCESS_DUP_HANDLE = (0x0040),
            PROCESS_CREATE_PROCESS = (0x0080),
            PROCESS_SET_QUOTA = (0x0100),
            PROCESS_SET_INFORMATION = (0x0200),
            PROCESS_QUERY_INFORMATION = (0x0400),
            PROCESS_ALL_ACCESS = PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION
        }


        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);

        [DllImport("kernel32.dll")]
        public static extern Int32 CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll")]
        public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out int lpNumberOfBytesRead);

        [DllImport("kernel32.dll")]
        public static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out int lpNumberOfBytesWritten);
    }
}
I will be adding more to this class as I need, and will try my best to update it on here aswell.
HOPE YOU ENJOY THIS.