ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/Win32/Sojaner.MemoryScanner/MemoryScanner.cs
Revision: 203
Committed: Thu May 31 09:03:53 2012 UTC (11 years, 6 months ago) by william
File size: 19255 byte(s)
Log Message:
+ add support to automatically goto the first address that has a non-zero byte

File Contents

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