ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/Win32/Sojaner.MemoryScanner/MemoryScanner.cs
Revision: 351
Committed: Sat Jun 9 20:52:19 2012 UTC (10 years, 5 months ago) by william
File size: 18930 byte(s)
Log Message:

File Contents

# User Rev Content
1 william 88 using System;
2     using System.Collections.Generic;
3     using System.Text;
4     using System.Diagnostics;
5     using System.Threading;
6     using System.Runtime.InteropServices;
7 william 156 using RomCheater.Logging;
8 william 162 using System.IO;
9 william 231 using Sojaner.MemoryScanner.MemoryProviers;
10 william 284 using Microsoft.Win32.SafeHandles;
11 william 351 using Microsoft.Win32.Interop;
12     using System.ComponentModel;
13 william 88
14     namespace Sojaner.MemoryScanner
15     {
16     // code borrowed from: http://www.codeproject.com/KB/cs/sojaner_memory_scanner.aspx
17     #region ProcessMemoryReader class
18     //Thanks goes to Arik Poznanski for P/Invokes and methods needed to read and write the Memory
19     //For more information refer to "Minesweeper, Behind the scenes" article by Arik Poznanski at Codeproject.com
20 william 257 internal class ProcessMemoryReader : IMemoryReader, IMemoryWriter, IFileWriter
21 william 88 {
22    
23     public ProcessMemoryReader()
24     {
25     }
26    
27     /// <summary>
28     /// Process from which to read
29     /// </summary>
30     public Process ReadProcess
31     {
32     get
33     {
34     return m_ReadProcess;
35     }
36     set
37     {
38     m_ReadProcess = value;
39     }
40     }
41    
42     private Process m_ReadProcess = null;
43 william 286
44     //SafeWaitHandle handle;
45 william 198 private static IntPtr m_hProcess = IntPtr.Zero;
46 william 88
47     public void OpenProcess()
48     {
49 william 247 try
50     {
51     // m_hProcess = ProcessMemoryReaderApi.OpenProcess(ProcessMemoryReaderApi.PROCESS_VM_READ, 1, (uint)m_ReadProcess.Id);
52     ProcessMemoryReaderApi.ProcessAccessType access;
53     access = ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_READ
54     | ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_WRITE
55     | ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_OPERATION;
56     m_hProcess = ProcessMemoryReaderApi.OpenProcess((uint)access, 1, (uint)m_ReadProcess.Id);
57     }
58     catch (SEHException ex)
59     {
60     logger.Error.WriteLine("WriteProcessMemoryToFile() SEHException was thrown: (0x{0:x8}) - {1}", ex.ErrorCode, ex.Message);
61     logger.Error.WriteLine(ex.ToString());
62     throw ex;
63     }
64     catch (Exception ex)
65     {
66     logger.Error.WriteLine(ex.ToString());
67     throw ex;
68     }
69 william 88 }
70    
71     public void CloseHandle()
72     {
73     try
74     {
75 william 286 SafeWaitHandle handle = new SafeWaitHandle(m_hProcess, false);
76     if (handle.IsInvalid) { return; }
77 william 284 if (handle.IsClosed) { return; }
78     handle.Close();
79     //string stack_trace = System.Environment.StackTrace;
80     //int iRetValue;
81     //iRetValue = ProcessMemoryReaderApi.CloseHandle(m_hProcess);
82     //if (iRetValue == 0)
83     //{
84     // throw new Exception("CloseHandle failed");
85     //}
86 william 88 }
87 william 245 catch (SEHException ex)
88     {
89 william 247 logger.Error.WriteLine("WriteProcessMemoryToFile() SEHException was thrown: (0x{0:x8}) - {1}", ex.ErrorCode, ex.Message);
90     logger.Error.WriteLine(ex.ToString());
91 william 245 throw ex;
92     }
93 william 88 catch (Exception ex)
94     {
95 william 247 logger.Error.WriteLine(ex.ToString());
96 william 88 throw ex;
97     }
98     }
99     /// <summary>
100     /// ProcessMemoryReader is a class that enables direct reading a process memory
101     /// </summary>
102 william 231 private class ProcessMemoryReaderApi
103 william 88 {
104     // constants information can be found in <winnt.h>
105     [Flags]
106     public enum ProcessAccessType
107     {
108     PROCESS_TERMINATE = (0x0001),
109     PROCESS_CREATE_THREAD = (0x0002),
110     PROCESS_SET_SESSIONID = (0x0004),
111     PROCESS_VM_OPERATION = (0x0008),
112     PROCESS_VM_READ = (0x0010),
113     PROCESS_VM_WRITE = (0x0020),
114     PROCESS_DUP_HANDLE = (0x0040),
115     PROCESS_CREATE_PROCESS = (0x0080),
116     PROCESS_SET_QUOTA = (0x0100),
117     PROCESS_SET_INFORMATION = (0x0200),
118     PROCESS_QUERY_INFORMATION = (0x0400)
119     }
120    
121     // function declarations are found in the MSDN and in <winbase.h>
122    
123     // HANDLE OpenProcess(
124     // DWORD dwDesiredAccess, // access flag
125     // BOOL bInheritHandle, // handle inheritance option
126     // DWORD dwProcessId // process identifier
127     // );
128     [DllImport("kernel32.dll")]
129     public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);
130    
131     // BOOL CloseHandle(
132     // HANDLE hObject // handle to object
133     // );
134     [DllImport("kernel32.dll")]
135     public static extern Int32 CloseHandle(IntPtr hObject);
136    
137     // BOOL ReadProcessMemory(
138     // HANDLE hProcess, // handle to the process
139     // LPCVOID lpBaseAddress, // base of memory area
140     // LPVOID lpBuffer, // data buffer
141     // SIZE_T nSize, // number of bytes to read
142     // SIZE_T * lpNumberOfBytesRead // number of bytes read
143     // );
144 william 350 [DllImport("kernel32.dll", SetLastError = true)]
145     public static extern bool ReadProcessMemory(
146     IntPtr hProcess,
147     IntPtr lpBaseAddress,
148     [Out] byte[] lpBuffer,
149     uint dwSize,
150     out int lpNumberOfBytesRead
151     );
152 william 88
153     // BOOL WriteProcessMemory(
154     // HANDLE hProcess, // handle to process
155     // LPVOID lpBaseAddress, // base of memory area
156     // LPCVOID lpBuffer, // data buffer
157     // SIZE_T nSize, // count of bytes to write
158     // SIZE_T * lpNumberOfBytesWritten // count of bytes written
159     // );
160 william 350 [DllImport("kernel32.dll", SetLastError = true)]
161     public static extern bool WriteProcessMemory(
162     IntPtr hProcess,
163     IntPtr lpBaseAddress,
164     byte[] lpBuffer,
165     uint nSize,
166     out UIntPtr lpNumberOfBytesWritten);
167 william 88
168    
169     }
170 william 231
171     #region IMemoryReader Members
172 william 249 #region public bool ReadFirstNonZeroByte(uint MemoryAddress, uint bytesToRead, out int address)
173     public bool ReadFirstNonZeroByte(int MemoryAddress, uint bytesToRead, out int address)
174 william 231 {
175     //logger.Info.WriteLine("Dumping memory (0x{0:x8}-0x{1:x8}) from pid=({2})", MemoryAddress, MemoryAddress + bytesToRead, string.Format("0x{0:x4} {1}.exe", ppid.Id, ppid.ProcessName));
176     address = 0;
177 william 235 uint byte_alignment = 1;
178 william 231 // get common init parameters
179     //InitMemoryDump(out byte_alignment);
180 william 249 int mem_address = MemoryAddress;
181 william 235 uint _bytesToRead = bytesToRead;
182 william 231 byte[] buffer = new byte[] { };
183     try
184     {
185     //using (MemoryStream ms = new MemoryStream())
186     //{
187     // //BinaryWriter bw = new BinaryWriter(ms);
188     // //foreach (byte b in data) { bw.Write(b); }
189 william 235 for (uint i = 0; i <= bytesToRead; )
190 william 231 {
191     if (_bytesToRead < byte_alignment)
192     {
193     _bytesToRead = bytesToRead;
194     buffer = new byte[_bytesToRead];
195     }
196     else
197     {
198     _bytesToRead = byte_alignment;
199     buffer = new byte[byte_alignment];
200     }
201     int bytesRead = 0;
202     ReadProcessMemory(mem_address, _bytesToRead, out bytesRead, out buffer);
203 william 245 if (buffer.Length == 0 && bytesRead == 0)
204     {
205     throw new Exception(string.Format("Failed to read memory from process: {0}", ReadProcess.ToString()));
206     }
207 william 231 //bw.Write(buffer);
208     //bw.Flush();
209     if (_bytesToRead < byte_alignment)
210     {
211     i += _bytesToRead;
212 william 249 mem_address += (int)_bytesToRead;
213 william 231 }
214     else
215     {
216     i += byte_alignment;
217 william 249 mem_address += (int)byte_alignment;
218 william 231 }
219     for (uint j = 0; j < buffer.Length; j++)
220     {
221     if (buffer[j] != 0)
222     {
223     address = mem_address;
224     break;
225     }
226     }
227     if (address != 0)
228     break;
229     }
230     // bw.Close();
231     //}
232     //logger.Info.WriteLine("Succefully dumped memory (0x{0:x8}-0x{1:x8}) from pid=({2})", MemoryAddress, MemoryAddress + bytesToRead, string.Format("0x{0:x4} {1}.exe", ppid.Id, ppid.ProcessName));
233     return true;
234     }
235 william 247 catch (SEHException ex)
236     {
237     logger.Error.WriteLine("ReadFirstNonZeroByte() SEHException was thrown: (0x{0:x8}) - {1}", ex.ErrorCode, ex.Message);
238     logger.Error.WriteLine(ex.ToString());
239     throw ex;
240     }
241 william 231 catch (OutOfMemoryException ex)
242     {
243 william 247 logger.Error.WriteLine("ReadFirstNonZeroByte(): OutOfMemoryException");
244 william 231 logger.Error.WriteLine(ex.ToString());
245     }
246     catch (Exception ex)
247     {
248 william 247 logger.Error.WriteLine("ReadFirstNonZeroByte(): Exception");
249 william 231 logger.Error.WriteLine(ex.ToString());
250 william 247 throw ex;
251 william 231 }
252     return false;
253     }
254 william 249 #endregion
255     #region public void ReadProcessMemory(int MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
256     public void ReadProcessMemory(int MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
257 william 231 {
258 william 350 ReadProcessMemory((uint)MemoryAddress, bytesToRead, out bytesRead, out data);
259     }
260     public void ReadProcessMemory(uint MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data)
261     {
262 william 247 try
263     {
264 william 351 bytesRead = 0;
265    
266     List<byte> buffer_list = new List<byte>();
267     uint _MemoryAddress = MemoryAddress;
268     for (int i = 0; i < bytesToRead; i++)
269     {
270     byte[] buffer = new byte[1];
271     int _bytesRead = 0;
272     ProcessMemoryReader.ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, (IntPtr)_MemoryAddress, buffer, 1, out _bytesRead);
273     if (_bytesRead > 0)
274     {
275     foreach (byte b in buffer)
276     {
277     buffer_list.Add(b);
278     }
279     _MemoryAddress += (uint)buffer.Length;
280     }
281     else
282     {
283     buffer_list.Add(0);
284     _MemoryAddress++;
285     }
286    
287     }
288     bytesRead = buffer_list.Count;
289     data = buffer_list.ToArray();
290 william 247 }
291     catch (SEHException ex)
292     {
293     logger.Error.WriteLine("ReadProcessMemory() SEHException was thrown: (0x{0:x8}) - {1}", ex.ErrorCode, ex.Message);
294     logger.Error.WriteLine(ex.ToString());
295     throw ex;
296     }
297     catch (Exception ex)
298     {
299     logger.Error.WriteLine("ReadProcessMemory(): Exception");
300     logger.Error.WriteLine(ex.ToString());
301     throw ex;
302     }
303 william 231 }
304     #endregion
305 william 249 #endregion
306 william 231
307     #region IMemoryWriter Members
308 william 249 #region public void WriteProcessMemory(uint MemoryAddress, byte byteToWrite, out int bytesWritten)
309     public void WriteProcessMemory(int MemoryAddress, byte byteToWrite, out int bytesWritten)
310 william 350 {
311     WriteProcessMemory(MemoryAddress, new byte[] { byteToWrite }, out bytesWritten);
312     }
313     public void WriteProcessMemory(uint MemoryAddress, byte byteToWrite, out uint bytesWritten)
314 william 231 {
315     WriteProcessMemory(MemoryAddress, new byte[] { byteToWrite }, out bytesWritten);
316     }
317 william 249 #endregion
318     #region public void WriteProcessMemory(uint MemoryAddress, byte[] bytesToWrite, out int bytesWritten)
319     public void WriteProcessMemory(int MemoryAddress, byte[] bytesToWrite, out int bytesWritten)
320 william 231 {
321 william 350 uint _bytesWritten = 0;
322     WriteProcessMemory((uint)MemoryAddress, bytesToWrite, out _bytesWritten);
323     bytesWritten = (int)_bytesWritten;
324     }
325     public void WriteProcessMemory(uint MemoryAddress, byte[] bytesToWrite, out uint bytesWritten)
326     {
327 william 247 try
328     {
329 william 350 UIntPtr ptrBytesWritten;
330 william 249 ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess, (IntPtr)MemoryAddress, bytesToWrite, (uint)bytesToWrite.Length, out ptrBytesWritten);
331 william 350 bytesWritten = ptrBytesWritten.ToUInt32();
332 william 351 int LastWin32Error = Marshal.GetLastWin32Error();
333     if (LastWin32Error != ResultWin32.ERROR_SUCCESS)
334     {
335     string error = ResultWin32.GetErrorName(LastWin32Error);
336     throw new Win32Exception(LastWin32Error, "Unable to read process memory");
337     }
338 william 247 }
339 william 351 catch (Win32Exception ex)
340     {
341     string error_name = ResultWin32.GetErrorName(ex.ErrorCode);
342     error_name = (error_name == string.Empty) ? "undefined" : error_name;
343     logger.Error.WriteLine("WriteProcessMemory() Win32Exception was thrown: ErrorCode:{0} - {1}", string.Format("0x{0:x8}", ex.ErrorCode, error_name), ex.Message);
344     logger.Error.WriteLine(ex.ToString());
345     throw ex;
346     }
347 william 247 catch (SEHException ex)
348     {
349     logger.Error.WriteLine("WriteProcessMemory() SEHException was thrown: (0x{0:x8}) - {1}", ex.ErrorCode, ex.Message);
350     logger.Error.WriteLine(ex.ToString());
351     throw ex;
352     }
353     catch (Exception ex)
354     {
355    
356     logger.Error.WriteLine("WriteProcessMemory() Exception");
357     logger.Error.WriteLine(ex.ToString());
358     bytesWritten = 0;
359     throw ex;
360     }
361 william 231 }
362 william 249 #endregion
363 william 231 #endregion
364    
365     #region IFileWriter Members
366 william 249 #region public bool WriteProcessMemoryToFile(string filename, uint MemoryAddress, uint bytesToRead, out int bytesRead)
367     public bool WriteProcessMemoryToFile(string filename, int MemoryAddress, uint bytesToRead, out int bytesRead)
368 william 231 {
369     //logger.Info.WriteLine("Dumping memory (0x{0:x8}-0x{1:x8}) from pid=({3}) to file {2}", MemoryAddress, MemoryAddress + bytesToRead, filename, string.Format("0x{0:x4} {1}.exe", ppid.Id, ppid.ProcessName));
370     bytesRead = 0;
371 william 235 uint byte_alignment = 102400;
372 william 249 int address = MemoryAddress;
373 william 235 uint _bytesToRead = bytesToRead;
374 william 231 byte[] buffer = new byte[] { };
375     try
376     {
377     FileInfo fi = new FileInfo(filename);
378     if (fi.Exists)
379     fi.Delete();
380     using (FileStream fs = new FileStream(filename, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite))
381     {
382     BinaryWriter bw = new BinaryWriter(fs);
383     //foreach (byte b in data) { bw.Write(b); }
384    
385 william 235 for (uint i = 0; i <= bytesToRead; )
386 william 231 {
387     if (_bytesToRead < byte_alignment)
388     {
389     _bytesToRead = bytesToRead;
390     buffer = new byte[_bytesToRead];
391     }
392     else
393     {
394     _bytesToRead = byte_alignment;
395     buffer = new byte[byte_alignment];
396     }
397     ReadProcessMemory(address, _bytesToRead, out bytesRead, out buffer);
398     bw.Write(buffer);
399     bw.Flush();
400    
401     if (_bytesToRead < byte_alignment)
402     {
403     i += _bytesToRead;
404 william 249 address += (int)_bytesToRead;
405 william 231 }
406     else
407     {
408     i += byte_alignment;
409 william 249 address += (int)byte_alignment;
410 william 231 }
411    
412    
413     }
414     bw.Close();
415     }
416     logger.Info.WriteLine("Succefully dumped memory (0x{0:x8}-0x{1:x8}) from pid=({3}) to file {2}", MemoryAddress, MemoryAddress + bytesToRead, filename, string.Format("0x{0:x4} {1}.exe", ReadProcess.Id, ReadProcess.ProcessName));
417     return true;
418     }
419 william 247 catch (SEHException ex)
420     {
421     logger.Error.WriteLine("WriteProcessMemoryToFile() SEHException was thrown: (0x{0:x8}) - {1}", ex.ErrorCode, ex.Message);
422     logger.Error.WriteLine(ex.ToString());
423     throw ex;
424     }
425 william 231 catch (OutOfMemoryException ex)
426     {
427 william 247 logger.Error.WriteLine("WriteProcessMemoryToFile(): Exception");
428 william 231 logger.Error.WriteLine(ex.ToString());
429     }
430     catch (Exception ex)
431     {
432 william 247 logger.Error.WriteLine("WriteProcessMemoryToFile(): Exception");
433 william 231 logger.Error.WriteLine(ex.ToString());
434 william 247 throw ex;
435 william 231 }
436     return false;
437     }
438     #endregion
439 william 249 #endregion
440 william 88 }
441     #endregion
442     }