ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/Win32/Sojaner.MemoryScanner/MemoryScanner.cs
(Generate patch)

Comparing trunk/Win32/Sojaner.MemoryScanner/MemoryScanner.cs (file contents):
Revision 403 by william, Wed Jun 20 13:24:49 2012 UTC vs.
Revision 404 by william, Thu Jun 21 12:51:57 2012 UTC

--- trunk/Win32/Sojaner.MemoryScanner/MemoryScanner.cs	2012/06/21 07:13:04	403
+++ trunk/Win32/Sojaner.MemoryScanner/MemoryScanner.cs	2012/06/21 12:51:57	404
@@ -10,6 +10,7 @@ using Sojaner.MemoryScanner.MemoryProvie
 using Microsoft.Win32.SafeHandles;
 using Microsoft.Win32.Interop;
 using System.ComponentModel;
+using ManagedWinapi;
 
 namespace Sojaner.MemoryScanner
 {
@@ -19,6 +20,50 @@ namespace Sojaner.MemoryScanner
     //For more information refer to "Minesweeper, Behind the scenes" article by Arik Poznanski at Codeproject.com
     internal class ProcessMemoryReader : IMemoryReader, IMemoryWriter, IFileWriter, IPatchMemory,IReadMemory
     {
+        // constants information can be found in <winnt.h>
+        [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)
+        }
+        [Flags]
+        public enum AllocationProtect : uint
+        {
+            // http://msdn.microsoft.com/en-us/library/windows/desktop/aa366786(v=vs.85).aspx
+            NONE = 0,
+            PAGE_NOACCESS = 0x00000001,
+            PAGE_READONLY = 0x00000002,
+            PAGE_READWRITE = 0x00000004,
+            PAGE_WRITECOPY = 0x00000008,
+            PAGE_EXECUTE = 0x00000010,
+            PAGE_EXECUTE_READ = 0x00000020,
+            PAGE_EXECUTE_READWRITE = 0x00000040,
+            PAGE_EXECUTE_WRITECOPY = 0x00000080,     
+            PAGE_GUARD = 0x00000100,
+            PAGE_NOCACHE = 0x00000200,
+            PAGE_WRITECOMBINE = 0x00000400
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct MEMORY_BASIC_INFORMATION
+        {
+            public IntPtr BaseAddress;
+            public IntPtr AllocationBase;
+            public AllocationProtect AllocationProtect;
+            public IntPtr RegionSize;
+            public uint State;
+            public uint Protect;
+            public uint Type;
+        }
 
         public ProcessMemoryReader()
         {
@@ -49,11 +94,16 @@ namespace Sojaner.MemoryScanner
             try
             {
                 //			m_hProcess = ProcessMemoryReaderApi.OpenProcess(ProcessMemoryReaderApi.PROCESS_VM_READ, 1, (uint)m_ReadProcess.Id);
-                ProcessMemoryReaderApi.ProcessAccessType access;
-                access = ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_READ
-                    | ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_WRITE
-                    | ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_OPERATION;
-                m_hProcess = ProcessMemoryReaderApi.OpenProcess((uint)access, 1, (uint)m_ReadProcess.Id);
+                //if (!TokenAdjuster.AdjustProcessTokenPrivileges("SeDebugPrivilege"))
+                //{
+                //    logger.Warn.WriteLine("Failed to set SeDebugPrivilege on current process");
+                //}
+                ProcessAccessType access;
+                access = ProcessAccessType.PROCESS_VM_READ
+                    | ProcessAccessType.PROCESS_VM_WRITE
+                    | ProcessAccessType.PROCESS_VM_OPERATION;
+                //m_hProcess = ProcessMemoryReaderApi.OpenProcess((uint)access, 1, (uint)m_ReadProcess.Id);
+               m_hProcess = ProcessMemoryReaderApi.OpenProcess((uint)access, 1, (uint)m_ReadProcess.Id);
             }
             catch (SEHException ex)
             {
@@ -72,12 +122,12 @@ namespace Sojaner.MemoryScanner
         {
             try
             {
-                SafeWaitHandle handle = new SafeWaitHandle(m_hProcess, false);
+                SafeWaitHandle handle = new SafeWaitHandle(m_ReadProcess.Handle, false);
                 if (handle.IsInvalid) { return; }
                 if (handle.IsClosed) { return; }
                 handle.Close();
                 handle = null;
-                m_hProcess = IntPtr.Zero;
+                //m_hProcess = IntPtr.Zero;
                 //string stack_trace = System.Environment.StackTrace;
                 //int iRetValue;
                 //iRetValue = ProcessMemoryReaderApi.CloseHandle(m_hProcess);
@@ -103,22 +153,10 @@ namespace Sojaner.MemoryScanner
         /// </summary>
         private class ProcessMemoryReaderApi
         {
-            // constants information can be found in <winnt.h>
-            [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)
-            }
+           
+        
+            [DllImport("kernel32.dll")]
+            public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);
 
             // function declarations are found in the MSDN and in <winbase.h> 
 
@@ -254,59 +292,71 @@ namespace Sojaner.MemoryScanner
             return false;
         }
         #endregion
-        #region public void ReadProcessMemory(int MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
-        public void ReadProcessMemoryAtOnce(int MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
+
+        public void ReadProcessMemoryAtOnce(uint MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
         {
-            ReadProcessMemoryAtOnce((uint)MemoryAddress, bytesToRead, out bytesRead, out data);
+            Stopwatch st = new Stopwatch();
+            st.Start();
+            uint size = 1024 * 64;
+            List<byte> buffer_list = new List<byte>();
+            for (uint j = MemoryAddress; j < bytesToRead; j += size)
+            {
+                ProcessMemoryChunk mem = new ProcessMemoryChunk(m_ReadProcess, (IntPtr)j, (int)size);
+                byte[] bigMem = mem.Read();
+                foreach (byte b in bigMem) { buffer_list.Add(b); }
+                bigMem = null;
+            }
+            bytesRead = buffer_list.Count;
+            data = new byte[bytesToRead];
+            data.Initialize();
+            Buffer.BlockCopy(buffer_list.ToArray(), 0, data, 0, (int)bytesToRead);
+            st.Stop();
+            logger.Profiler.WriteLine("ReadProcessMemoryAtOnce(): start=0x{0:x8} end=0x{1:x8} took {2:0.0000} seconds", MemoryAddress, MemoryAddress + bytesToRead, st.Elapsed.TotalSeconds);
         }
+
+        #region public void ReadProcessMemory(int MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
         public void ReadProcessMemory(int MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
         {
             ReadProcessMemory((uint)MemoryAddress, bytesToRead, out bytesRead, out data);
         }
-        public void ReadProcessMemoryAtOnce(uint MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
-        {
-            try
-            {
-                data = new byte[bytesToRead];
-                //bytesRead = 0;
-                //int _bytesRead = 0;
-                //const uint alignment = 20480;
-                //uint _MemoryAddress = MemoryAddress;
-                //for (uint i = 0; i < bytesToRead;i+=alignment)
-                //{
-                //    byte[] _tmp_data = new byte[alignment];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)MemoryAddress, data, bytesToRead, out bytesRead);
-                //    _MemoryAddress = MemoryAddress + i;
-                //    Buffer.BlockCopy(_tmp_data, 0, data, (int)i, _bytesRead);
-                //    bytesRead += _bytesRead;
-                //}
-            }
-            catch (SEHException ex)
-            {
-                logger.Error.WriteLine("ReadProcessMemory() SEHException was thrown: (0x{0:x8}) - {1}", ex.ErrorCode, ex.Message);
-                logger.Error.WriteLine(ex.ToString());
-                throw ex;
-            }
-            catch (Exception ex)
-            {
-                logger.Error.WriteLine("ReadProcessMemory(): Exception");
-                logger.Error.WriteLine(ex.ToString());
-                throw ex;
-            }
-        }
         public void ReadProcessMemory(uint MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
         {
             try
             {
                 bytesRead = 0;
-
+                data = new byte[bytesToRead];
+                const int alignment = 1;
                 List<byte> buffer_list = new List<byte>();
                 uint _MemoryAddress = MemoryAddress;
                 for (int i = 0; i < bytesToRead; i++)
                 {
-                    byte[] buffer = new byte[1];
+                    byte[] buffer = new byte[alignment];
                     int _bytesRead = 0;
-                    ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)_MemoryAddress, buffer, 1, out _bytesRead);
+                    MEMORY_BASIC_INFORMATION m;
+                    ProcessMemoryReaderApi.VirtualQueryEx(m_ReadProcess.Handle, (IntPtr)_MemoryAddress, out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)));
+
+                    if (m.AllocationProtect.HasFlag(AllocationProtect.PAGE_NOACCESS) ||
+                        m.AllocationProtect == 0)
+                    {
+                        uint OrignalAddress = _MemoryAddress;
+                        while (m.AllocationProtect.HasFlag(AllocationProtect.PAGE_NOACCESS) || m.AllocationProtect == 0)
+                        {
+                            ProcessMemoryReaderApi.VirtualQueryEx(m_ReadProcess.Handle, (IntPtr)_MemoryAddress, out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)));
+                            _MemoryAddress++;
+                            buffer_list.Add(0);
+                        }
+                        _MemoryAddress--;
+                        uint diff = _MemoryAddress - OrignalAddress;
+                        i += (int)diff;
+                        buffer_list.RemoveAt(buffer_list.Count-1);
+                    }
+
+                    ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)_MemoryAddress, buffer, alignment, out _bytesRead);
+                    int LastError = Marshal.GetLastWin32Error();
+                    if (LastError != ResultWin32.ERROR_SUCCESS)
+                    {
+                        string ErrorName = ResultWin32.GetErrorName(LastError);
+                    }
                     if (_bytesRead > 0)
                     {
                         foreach (byte b in buffer)
@@ -315,16 +365,9 @@ namespace Sojaner.MemoryScanner
                         }
                         _MemoryAddress += (uint)buffer.Length;
                     }
-                    else
-                    {
-                        //buffer_list.Add((byte)'?');
-                        buffer_list.Add(0);
-                        _MemoryAddress++;
-                    }
-                    
                 }
                 bytesRead = buffer_list.Count;
-                data = buffer_list.ToArray();
+                Buffer.BlockCopy(buffer_list.ToArray(), 0, data, 0, (int)bytesToRead);
             }
             catch (SEHException ex)
             {
@@ -360,7 +403,7 @@ namespace Sojaner.MemoryScanner
                 {
                     UIntPtr _ptrBytesWritten = UIntPtr.Zero;
                     byte[] buffer = new byte[] { bytesToWrite[i] };
-                    ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)_MemoryAddress, buffer, (uint)buffer.Length, out _ptrBytesWritten);
+                    ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)_MemoryAddress, buffer, (uint)buffer.Length, out _ptrBytesWritten);
                     _MemoryAddress++;
                     _bytesWritten++;
                 }
@@ -416,7 +459,7 @@ namespace Sojaner.MemoryScanner
                             _bytesToRead = byte_alignment;
                             buffer = new byte[byte_alignment];
                         }
-                        ReadProcessMemoryAtOnce(address, _bytesToRead, out bytesRead, out buffer);
+                        ReadProcessMemory(address, _bytesToRead, out bytesRead, out buffer);
                         bw.Write(buffer);
                         bw.Flush();
 
@@ -466,7 +509,7 @@ namespace Sojaner.MemoryScanner
         {
             byte[] bitData = BitConverter.GetBytes(value);
             UIntPtr ptrBytesWritten;
-            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
+            ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
             if (ptrBytesWritten.ToUInt32() == 0)
                 return false;
             byte check = 0;
@@ -480,7 +523,7 @@ namespace Sojaner.MemoryScanner
         {
             byte[] bitData = BitConverter.GetBytes(value);
             UIntPtr ptrBytesWritten;
-            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
+            ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
             if (ptrBytesWritten.ToUInt32() == 0)
                 return false;
             sbyte check = 0;
@@ -494,7 +537,7 @@ namespace Sojaner.MemoryScanner
         {
             byte[] bitData = BitConverter.GetBytes(value);
             UIntPtr ptrBytesWritten;
-            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
+            ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
             if (ptrBytesWritten.ToUInt32() == 0)
                 return false;
             ushort check = 0;
@@ -508,7 +551,7 @@ namespace Sojaner.MemoryScanner
         {           
             byte[] bitData = BitConverter.GetBytes(value);
             UIntPtr ptrBytesWritten;
-            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
+            ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
             if (ptrBytesWritten.ToUInt32() == 0)
                 return false;
             short check = 0;
@@ -522,7 +565,7 @@ namespace Sojaner.MemoryScanner
         {
             byte[] bitData = BitConverter.GetBytes(value);
             UIntPtr ptrBytesWritten;
-            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
+            ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
             if (ptrBytesWritten.ToUInt32() == 0)
                 return false;
             uint check = 0;
@@ -536,7 +579,7 @@ namespace Sojaner.MemoryScanner
         {
             byte[] bitData = BitConverter.GetBytes(value);
             UIntPtr ptrBytesWritten;
-            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
+            ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
             if (ptrBytesWritten.ToUInt32() == 0)
                 return false;
             int check = 0;
@@ -550,7 +593,7 @@ namespace Sojaner.MemoryScanner
         {
             byte[] bitData = BitConverter.GetBytes(value);
             UIntPtr ptrBytesWritten;
-            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
+            ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
             if (ptrBytesWritten.ToUInt32() == 0)
                 return false;
             ulong check = 0;
@@ -564,7 +607,7 @@ namespace Sojaner.MemoryScanner
         {
             byte[] bitData = BitConverter.GetBytes(value);
             UIntPtr ptrBytesWritten;
-            ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
+            ProcessMemoryReaderApi.WriteProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, (uint)bitData.Length, out ptrBytesWritten);
             if (ptrBytesWritten.ToUInt32() == 0)
                 return false;
             long check = 0;
@@ -585,7 +628,7 @@ namespace Sojaner.MemoryScanner
                 int bytesRead;
                 uint size = sizeof(byte);
                 byte[] bitData = new byte[size];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)address, bitData, size, out bytesRead);
+                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, size, out bytesRead);
                 if (bytesRead == 0)
                     return false;
                 value = bitData[0];
@@ -607,7 +650,7 @@ namespace Sojaner.MemoryScanner
                 int bytesRead;
                 uint size = sizeof(sbyte);
                 byte[] bitData = new byte[size];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)address, bitData, size, out bytesRead);
+                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, size, out bytesRead);
                 if (bytesRead == 0)
                     return false;
                 value = Convert.ToSByte(bitData[0]);
@@ -629,7 +672,7 @@ namespace Sojaner.MemoryScanner
                 int bytesRead;
                 uint size = sizeof(ushort);
                 byte[] bitData = new byte[size];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)address, bitData, size, out bytesRead);
+                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, size, out bytesRead);
                 if (bytesRead == 0)
                     return false;
                 value = BitConverter.ToUInt16(bitData, 0);
@@ -651,7 +694,7 @@ namespace Sojaner.MemoryScanner
                 int bytesRead;
                 uint size = sizeof(short);
                 byte[] bitData = new byte[size];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)address, bitData, size, out bytesRead);
+                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, size, out bytesRead);
                 if (bytesRead == 0)
                     return false;
                 value = BitConverter.ToInt16(bitData, 0);
@@ -673,7 +716,7 @@ namespace Sojaner.MemoryScanner
                 int bytesRead;
                 uint size = sizeof(uint);
                 byte[] bitData = new byte[size];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)address, bitData, size, out bytesRead);
+                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, size, out bytesRead);
                 if (bytesRead == 0)
                     return false;
                 value = BitConverter.ToUInt32(bitData, 0);
@@ -695,7 +738,7 @@ namespace Sojaner.MemoryScanner
                 int bytesRead;
                 uint size = sizeof(int);
                 byte[] bitData = new byte[size];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)address, bitData, size, out bytesRead);
+                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, size, out bytesRead);
                 if (bytesRead == 0)
                     return false;
                 value = BitConverter.ToInt32(bitData, 0);
@@ -717,7 +760,7 @@ namespace Sojaner.MemoryScanner
                 int bytesRead;
                 uint size = sizeof(ulong);
                 byte[] bitData = new byte[size];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)address, bitData, size, out bytesRead);
+                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, size, out bytesRead);
                 if (bytesRead == 0)
                     return false;
                 value = BitConverter.ToUInt64(bitData, 0);
@@ -739,7 +782,7 @@ namespace Sojaner.MemoryScanner
                 int bytesRead;
                 uint size = sizeof(long);
                 byte[] bitData = new byte[size];
-                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)address, bitData, size, out bytesRead);
+                ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_ReadProcess.Handle, (IntPtr)address, bitData, size, out bytesRead);
                 if (bytesRead == 0)
                     return false;
                 value = BitConverter.ToInt64(bitData, 0);