仕事やプライベートで調べたことのメモ書きなど(@札幌)

仕事やプライベートで調べたこと、興味ある事のメモ書きです。2016年4月から札幌で働いてます。※このブログは個人によるもので、団体を代表するものではありません。

C#でほかのプロセスのメモリを参照する

C#のプログラムでほかのプロセスのメモリ空間を覗いてみたサンプル

using System;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ConsoleApplication2
{
	class Class1
	{
		static void Main(string[] args) {
			System.Diagnostics.Process[] hProcesses = System.Diagnostics.Process.GetProcesses();

			string stPrompt = string.Empty;

			foreach (System.Diagnostics.Process hProcess in hProcesses) {
				if (hProcess.ProcessName.ToLower().Contains("xxxxx")) {
					Func(hProcess);
				}
		    }
		}
		
		static void Func(System.Diagnostics.Process hProcess) {
			Console.WriteLine(hProcess.Id);
			Console.WriteLine(hProcess.ProcessName);
			
			try {
				IntPtr processMemory = IntPtr.Zero;
				IntPtr aPtr = Win32Api.OpenProcess(Win32Api.PROCESS_VM_READ, false, hProcess.Id);
				if (aPtr == IntPtr.Zero) {
					Win32Api.WriteError(Marshal.GetLastWin32Error());
					Console.WriteLine("OpenProcess error!");
					return;
				}

				int TARGET_ADDRESS = 0x111111;
				int READ_MEMORY_SIZE = 512;

				int aGetByte;
				byte[] aResultArray = new byte[READ_MEMORY_SIZE];
				IntPtr aTarget = new IntPtr(TARGET_ADDRESS);
				/* Console.WriteLine("EntryPoint:0x" + Convert.ToString(hProcess.MainModule.EntryPointAddress.ToInt64(),16)); */
				if (!Win32Api.ReadProcessMemory(hProcess.Handle, aTarget, aResultArray, READ_MEMORY_SIZE, out aGetByte)) {
					Win32Api.WriteError(Marshal.GetLastWin32Error());
					Console.WriteLine("ReadProcessMemory error!");
					return;
				}
				/* Console.WriteLine(System.Text.Encoding.ASCII.GetString(aResultArray)); */
				Console.WriteLine(BitConverter.ToString(aResultArray));
			} finally {
			}
		}
	}

	static class Win32Api
	{
		private const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;

		public const int 
			PROCESS_VM_READ = 0x0010,
			PROCESS_VM_WRITE = 0x0020,
			PROCESS_DUP_HANDLE = 0x0040,
			PROCESS_QUERY_INFO = 0x0400,
			PROCESS_QUERY_LIMITED_INFO = 0x1000;

		public const int
			MEM_COMMIT = 0x1000,
			MEM_RESERVE = 0x2000;

		public const int
			MEM_DECOMMIT = 0x4000,
			MEM_RELEASE = 0x8000;

		public const int
			PAGE_NOACCESS = 0x01,
			PAGE_READONLY = 0x02,
			PAGE_READWRITE = 0x04,
			PAGE_WRITECOPY = 0x08;

		[DllImport("kernel32")]
		public static extern IntPtr VirtualAllocEx(
			IntPtr hProcess, IntPtr lpAddress, int dwSize, int flAllocationType, int flProtect);

        [DllImport("kernel32")]
        public static extern int VirtualFreeEx(
            IntPtr hProcess, IntPtr lpAddress, int dwSize, int dwFreeType);

		[DllImport("kernel32")]
		public static extern int WriteProcessMemory(
			IntPtr hProcess, IntPtr lpBaseAddress,
			IntPtr lpBuffer, int nSize, out int lpNumberOfBytesWritten);

		[DllImport("kernel32", SetLastError = true)]
		public static extern bool ReadProcessMemory(
			IntPtr hProcess, IntPtr lpBaseAddress,
			byte[] lpBuffer, int nSize, out int lpNumberOfBytesRead);

		[DllImport("kernel32", SetLastError = true)]
		public static extern IntPtr OpenProcess(
			int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

		[DllImport("kernel32")]
		public static extern int CloseHandle(IntPtr hObject);
        
		[DllImport("kernel32.dll")]
		public static extern uint FormatMessage(
		    uint dwFlags, IntPtr lpSource, 
		    uint dwMessageId, uint dwLanguageId, 
		    StringBuilder lpBuffer, int nSize, 
		    IntPtr Arguments);

		public static void WriteError(int errCode) {
			StringBuilder message = new StringBuilder(255);
			Win32Api.FormatMessage(
				FORMAT_MESSAGE_FROM_SYSTEM,
				IntPtr.Zero,
				(uint)errCode,
				0,
				message,
				message.Capacity,
				IntPtr.Zero);
			Console.WriteLine("Win32ApiError:" + message.ToString());
		}
	}
}

管理者で実行しないとエラーになる場合がありますので要注意。

以下のサイトを参考にしました。
[C#] バイト型配列 byte[] (バイナリ) からstring(文字列)に変換する
プロセスの保護
Win32エラー・コードからエラー・メッセージを取得するには?[C#、VB] − @IT
stackoverflow.com
http://www.geocities.jp/syagamisrash2000/csgengo.htm
C# - 実行中のすべてのプロセスを取得する
schima.hatenablog.com
VirtualAllocEx 関数