C#操作内存读写方法是什么呢?让我们来看看具体的实例实现:
C#操作内存读写方法是什么呢?让我们来看看具体的实例实现:
- using System.Runtime.InteropServices;
- using System.Text;
- public class Function
- {
- //C#操作内存读写方法
- public static byte PtrToByte( int Ptr )
- {
- byte b = Marshal.ReadByte( ( IntPtr ) Ptr );
- return b;
- }
- public static char PtrToChar( int Ptr )
- {
- byte b = Marshal.ReadByte( ( IntPtr ) Ptr );
- return ( char ) b;
- }
- public static short PtrToShort( int Ptr )
- {
- short b = Marshal.ReadInt16( ( IntPtr ) Ptr );
- return b;
- }
- //C#操作内存读写方法
- public static ushort PtrToUShort( int Ptr )
- {
- ushort b = ( ushort ) Marshal.ReadInt16( ( IntPtr ) Ptr );
- return b;
- }
- public static int PtrToInt( int Ptr )
- {
- int b = Marshal.ReadInt32( ( IntPtr ) Ptr );
- return b;
- }
- public static uint PtrToUInt( int Ptr )
- {
- uint b = ( uint ) Marshal.ReadInt32( ( IntPtr ) Ptr );
- return b;
- }
- public static long PtrToLong( int Ptr )
- {
- long b = Marshal.ReadInt64( ( IntPtr ) Ptr );
- return b;
- } //C#操作内存读写方法
- public static ulong PtrToULong( int Ptr )
- {
- ulong b = ( ulong ) Marshal.ReadInt64( ( IntPtr ) Ptr );
- return b;
- }
- // Convert an ip address stored an address to equivalent string value
- public static string GetPtrToIpAddr(int intPtr, int varlen)
- {
- int i = 0;
- StringBuilder sb = new StringBuilder(0,varlen*4);
- byte[] byx = new byte[varlen];
- // ip address cann't have zero value C#操作内存读写方法
- // ip address cann't have zero length C#操作内存读写方法
- if( ( intPtr == 0 ) || ( varlen == 0 ) ) return "";
- Marshal.Copy( ( IntPtr ) intPtr , byx , 0 , varlen );
- for( i = 0; i < varlen - 1; i ++ )
- {
- sb.Append(byx[i]);
- sb.Append('.');
- }
- sb.Append(byx[varlen - 1]);
- return sb.ToString();
- }
- }
BOOL ReadProcessMemory( HANDLE hProcess, PVOID pvAddressRemote, PVOID pvBufferLocal, DWORD dwSize, PDWORD pdwNumBytesRead);
参数 hProcess为远程进程的句柄 pvAddressRemote用于指明远程进程中的地址 pvBufferLocal是本地进程中的内存地址 dwSize是需要传送的字节数 pdwNumBytesRead和pdwNumBytesWritten用于指明实际传送的字节数.当函数返回时,可以查看这两个参数的值.
ReadProcessMemory读出数据,权限要大一些。下面这个打开进程的方式具备了查询 读和写的权限
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, ProcessId)
然后就要结合上面的程序来搜索了。只有当内存是处于被占用状态时才去读取其中的内容,而忽略空闲状态的内存。程序我就不在这儿写了,和上面那段差不多。只是把dwTotalCommit = dwTotalCommit + mi.RegionSize换成了读取内存以及搜索这一块内存的函数而已。
1.通过FindWindow读取窗体的句柄
2.通过GetWindowThreadProcessId
3.用OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, ProcessId)打开查到PID值的进程. 此打开具备 读取,写入,查询的权限
4.ReadProcessMemory读出指定的内存地址数据
1 //C#读取内存例子 2 3 using System; 4 using System.Collections.Generic; 5 using System.Text; 6 using System.Runtime.InteropServices; 7 using System.Diagnostics; 8 using System.Management; 9 10 public class key 11 { 12 const uint PROCESS_ALL_ACCESS = 0x001F0FFF; 13 const uint KEYEVENTF_EXTENDEDKEY = 0x1; 14 const uint KEYEVENTF_KEYUP = 0x2; 15 private readonly int MOUSEEVENTF_LEFTDOWN = 0x2; 16 private readonly int MOUSEEVENTF_LEFTUP = 0x4; 17 const uint KBC_KEY_CMD = 0x64; 18 const uint KBC_KEY_DATA = 0x60; 19 //得到窗体句柄的函数,FindWindow函数用来返回符合指定的类名( ClassName )和窗口名( WindowTitle )的窗口句柄 20 [DllImport("user32.dll", CharSet = CharSet.Auto)] 21 public static extern IntPtr FindWindow( 22 string lpClassName, // pointer to class name 23 string lpWindowName // pointer to window name 24 ); 25 [DllImport("user32.dll")] 26 private static extern int GetWindowThreadProcessId(IntPtr id, int pid); 27 28 [DllImport("kernel32.dll")] 29 private static extern void CloseHandle 30 ( 31 uint hObject //Handle to object 32 ); 33 //读取进程内存的函数 34 [DllImport("kernel32.dll")] 35 static extern bool ReadProcessMemory(uint hProcess, IntPtr lpBaseAddress, 36 IntPtr lpBuffer, uint nSize, ref uint lpNumberOfBytesRead); 37 //得到目标进程句柄的函数 38 [DllImport("kernel32.dll")] 39 public static extern uint OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId); 40 //鼠标事件声明 41 [DllImport("user32.dll")] 42 static extern bool setcursorpos(int x, int y); 43 [DllImport("user32.dll")] 44 static extern void mouse_event(mouseeventflag flags, int dx, int dy, uint data, UIntPtr extrainfo); 45 //键盘事件声明 46 [DllImport("user32.dll")] 47 static extern byte MapVirtualKey(byte wCode, int wMap); 48 [DllImport("user32.dll")] 49 static extern short GetKeyState(int nVirtKey); 50 [DllImport("user32.dll")] 51 static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo); 52 //键盘事件声明winio 53 [DllImport("winio.dll")] 54 public static extern bool InitializeWinIo(); 55 [DllImport("winio.dll")] 56 public static extern bool GetPortVal(IntPtr wPortAddr, out int pdwPortVal, byte bSize); 57 [DllImport("winio.dll")] 58 public static extern bool SetPortVal(uint wPortAddr, IntPtr dwPortVal, byte bSize); 59 [DllImport("winio.dll")] 60 public static extern byte MapPhysToLin(byte pbPhysAddr, uint dwPhysSize, IntPtr PhysicalMemoryHandle); 61 [DllImport("winio.dll")] 62 public static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, byte pbLinAddr); 63 [DllImport("winio.dll")] 64 public static extern bool GetPhysLong(IntPtr pbPhysAddr, byte pdwPhysVal); 65 [DllImport("winio.dll")] 66 public static extern bool SetPhysLong(IntPtr pbPhysAddr, byte dwPhysVal); 67 [DllImport("winio.dll")] 68 public static extern void ShutdownWinIo(); 69 70 71 72 73 /// <summary> 74 /// 获取进程pid 75 /// </summary> 76 /// <param name="name"></param> 77 /// <returns></returns> 78 private int pid(String name) 79 { 80 try 81 { 82 ObjectQuery oQuery = new ObjectQuery("select * from Win32_Process where Name='" + name + "'"); 83 ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oQuery); 84 ManagementObjectCollection oReturnCollection = oSearcher.Get(); 85 86 string pid = ""; 87 string cmdLine; 88 StringBuilder sb = new StringBuilder(); 89 foreach (ManagementObject oReturn in oReturnCollection) 90 { 91 pid = oReturn.GetPropertyValue("ProcessId").ToString(); 92 //cmdLine = (string)oReturn.GetPropertyvalue("CommandLine"); 93 94 //string pattern = "-ap \"(.*)\""; 95 //Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); 96 // Match match = regex.Match(cmdLine); 97 //string appPoolName = match.Groups[1].ToString(); 98 //sb.AppendFormat("W3WP.exe PID: {0} AppPoolId:{1}\r\n", pid, appPoolName); 99 } 100 return Convert.ToInt32(pid); 101 } 102 catch (Exception ss) 103 { return 0; } 104 105 } 106 private int pid(IntPtr id) 107 { 108 int pid = 0; 109 pid = GetWindowThreadProcessId(id, pid); 110 return 260; 111 } 112 /// <summary> 113 /// 读取内存值 114 /// </summary> 115 /// <param name="name">进程id</param> 116 /// <param name="dizhi">读取的内存地址</param> 117 /// <returns></returns> 118 //public String getread(String QEC,String EC, IntPtr dizhi, uint size) 119 //{ 120 // Byte bt = new Byte(); 121 // IntPtr id=FindWindow(QEC, EC); 122 // uint hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid(id)); 123 // IntPtr fanhui = new IntPtr(); 124 // String gg = null; 125 // if (hProcess == 0) 126 // { 127 // // gg = ReadProcessMemory(hProcess, dizhi, fanhui, size, 0); 128 // // CloseHandle(hProcess); 129 130 131 // } 132 // return gg; 133 //} 134 public String getread(String jincheng, String EC, IntPtr dizhi, uint size) 135 { 136 byte[] vBuffer = new byte[4]; 137 IntPtr vBytesAddress = Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0); // 得到缓冲区的地址 138 139 uint vNumberOfBytesRead = 0; 140 Byte bt = new Byte(); 141 //IntPtr id = FindWindow(QEC, EC); 142 uint hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid(jincheng)); 143 //pid(0); 144 IntPtr fanhui = new IntPtr(); 145 String gg = null; 146 //if (hProcess == 0) 147 //{ 148 if (ReadProcessMemory(hProcess, dizhi, vBytesAddress, (uint)vBuffer.Length, ref hProcess)) 149 { 150 CloseHandle(hProcess); 151 } 152 else 153 { 154 CloseHandle(hProcess); 155 } 156 157 // } 158 int vInt = Marshal.ReadInt32(vBytesAddress); 159 return vInt.ToString(); 160 } 161 /// <summary> 162 /// 获取键盘状态 163 /// </summary> 164 /// <param name="Key"></param> 165 /// <returns></returns> 166 public bool GetState(VirtualKeys Key) 167 { 168 return (GetKeyState((int)Key) == 1); 169 } 170 /// <summary> 171 /// 发送键盘事件 172 /// </summary> 173 /// <returns></returns> 174 public void Send(VirtualKeys Key, bool State) 175 { 176 if (State != GetState(Key)) 177 { 178 byte a = MapVirtualKey((byte)Key, 0); 179 keybd_event((byte)Key, MapVirtualKey((byte)Key, 0), 0, 0); 180 System.Threading.Thread.Sleep(1000); 181 keybd_event((byte)Key, MapVirtualKey((byte)Key, 0), KEYEVENTF_KEYUP, 0); 182 } 183 } 184 /// <summary> 185 /// 初始化winio 186 /// </summary> 187 public void sendwinio() 188 { 189 if (InitializeWinIo()) 190 { 191 KBCWait4IBE(); 192 } 193 } 194 private void KBCWait4IBE() //等待键盘缓冲区为空 195 { 196 //int[] dwVal = new int[] { 0 }; 197 int dwVal = 0; 198 do 199 { 200 //这句表示从&H64端口读取一个字节并把读出的数据放到变量dwVal中 201 //GetPortVal函数的用法是GetPortVal 端口号,存放读出数据的变量,读入的长度 202 bool flag = GetPortVal((IntPtr)0x64, out dwVal, 1); 203 } 204 while ((dwVal & 0x2) > 0); 205 } 206 /// <summary> 207 /// 模拟键盘标按下 208 /// </summary> 209 /// <param name="vKeyCoad"></param> 210 public void MykeyDown(int vKeyCoad) 211 { 212 int btScancode = 0; 213 214 btScancode = MapVirtualKey((byte)vKeyCoad, 0); 215 // btScancode = vKeyCoad; 216 217 KBCWait4IBE(); // '发送数据前应该先等待键盘缓冲区为空 218 SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);// '发送键盘写入命令 219 //SetPortVal函数用于向端口写入数据,它的用法是SetPortVal 端口号,欲写入的数据,写入数据的长度 220 KBCWait4IBE(); 221 SetPortVal(KBC_KEY_DATA, (IntPtr)0xe2, 1);// '写入按键信息,按下键 222 KBCWait4IBE(); // '发送数据前应该先等待键盘缓冲区为空 223 SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);// '发送键盘写入命令 224 //SetPortVal函数用于向端口写入数据,它的用法是SetPortVal 端口号,欲写入的数据,写入数据的长度 225 KBCWait4IBE(); 226 SetPortVal(KBC_KEY_DATA, (IntPtr)btScancode, 1);// '写入按键信息,按下键 227 228 } 229 /// <summary> 230 /// 模拟键盘弹出 231 /// </summary> 232 /// <param name="vKeyCoad"></param> 233 public void MykeyUp(int vKeyCoad) 234 { 235 int btScancode = 0; 236 btScancode = MapVirtualKey((byte)vKeyCoad, 0); 237 //btScancode = vKeyCoad; 238 239 KBCWait4IBE(); // '发送数据前应该先等待键盘缓冲区为空 240 SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1); //'发送键盘写入命令 241 KBCWait4IBE(); 242 SetPortVal(KBC_KEY_DATA, (IntPtr)0xe0, 1);// '写入按键信息,释放键 243 KBCWait4IBE(); // '发送数据前应该先等待键盘缓冲区为空 244 SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1); //'发送键盘写入命令 245 KBCWait4IBE(); 246 SetPortVal(KBC_KEY_DATA, (IntPtr)btScancode, 1);// '写入按键信息,释放键 247 } 248 /// <summary> 249 /// 模拟鼠标按下 250 /// </summary> 251 /// <param name="vKeyCoad"></param> 252 public void MyMouseDown(int vKeyCoad) 253 { 254 int btScancode = 0; 255 256 btScancode = MapVirtualKey((byte)vKeyCoad, 0); 257 //btScancode = vKeyCoad; 258 259 KBCWait4IBE(); // '发送数据前应该先等待键盘缓冲区为空 260 SetPortVal(KBC_KEY_CMD, (IntPtr)0xD3, 1);// '发送键盘写入命令 261 //SetPortVal函数用于向端口写入数据,它的用法是SetPortVal 端口号,欲写入的数据,写入数据的长度 262 KBCWait4IBE(); 263 SetPortVal(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1);// '写入按键信息,按下键 264 265 } 266 /// <summary> 267 /// 模拟鼠标弹出 268 /// </summary> 269 /// <param name="vKeyCoad"></param> 270 public void MyMouseUp(int vKeyCoad) 271 { 272 int btScancode = 0; 273 btScancode = MapVirtualKey((byte)vKeyCoad, 0); 274 // btScancode = vKeyCoad; 275 276 KBCWait4IBE(); // '发送数据前应该先等待键盘缓冲区为空 277 SetPortVal(KBC_KEY_CMD, (IntPtr)0xD3, 1); //'发送键盘写入命令 278 KBCWait4IBE(); 279 SetPortVal(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1);// '写入按键信息,释放键 280 } 281 /// <summary> 282 /// 发送鼠标事件 283 /// </summary> 284 /// <returns></returns> 285 public void SendMouse() 286 { 287 288 } 289 /// <summary> 290 /// 鼠标动作枚举 291 /// </summary> 292 public enum mouseeventflag : uint 293 { 294 move = 0x0001, 295 leftdown = 0x0002, 296 leftup = 0x0004, 297 rightdown = 0x0008, 298 rightup = 0x0010, 299 middledown = 0x0020, 300 middleup = 0x0040, 301 xdown = 0x0080, 302 xup = 0x0100, 303 wheel = 0x0800, 304 virtualdesk = 0x4000, 305 absolute = 0x8000 306 } 307 /// <summary> 308 /// 键盘动作枚举 309 /// </summary> 310 public enum VirtualKeys : byte 311 { 312 //VK_NUMLOCK = 0x90, //数字锁定键 313 //VK_SCROLL = 0x91, //滚动锁定 314 //VK_CAPITAL = 0x14, //大小写锁定 315 //VK_A = 62, //键盘A 316 VK_LBUTTON = 1, //鼠标左键 317 VK_RBUTTON = 2, //鼠标右键 318 VK_CANCEL = 3, //Ctrl+Break(通常不需要处理) 319 VK_MBUTTON = 4, //鼠标中键 320 VK_BACK = 8, //Backspace 321 VK_TAB = 9, //Tab 322 VK_CLEAR = 12, //Num Lock关闭时的数字键盘5 323 VK_RETURN = 13, //Enter(或者另一个) 324 VK_SHIFT = 16, //Shift(或者另一个) 325 VK_CONTROL = 17, //Ctrl(或者另一个) 326 VK_MENU = 18, //Alt(或者另一个) 327 VK_PAUSE = 19, //Pause 328 VK_CAPITAL = 20, //Caps Lock 329 VK_ESCAPE = 27, //Esc 330 VK_SPACE = 32, //Spacebar 331 VK_PRIOR = 33, //Page Up 332 VK_NEXT = 34, //Page Down 333 VK_END = 35, //End 334 VK_HOME = 36, //Home 335 VK_LEFT = 37, //左箭头 336 VK_UP = 38, //上箭头 337 VK_RIGHT = 39, //右箭头 338 VK_DOWN = 40, //下箭头 339 VK_SELECT = 41, //可选 340 VK_PRINT = 42, //可选 341 VK_EXECUTE = 43, //可选 342 VK_SNAPSHOT = 44, //Print Screen 343 VK_INSERT = 45, //Insert 344 VK_DELETE = 46, //Delete 345 VK_HELP = 47, //可选 346 VK_NUM0 = 48, //0 347 VK_NUM1 = 49, //1 348 VK_NUM2 = 50, //2 349 VK_NUM3 = 51, //3 350 VK_NUM4 = 52, //4 351 VK_NUM5 = 53, //5 352 VK_NUM6 = 54, //6 353 VK_NUM7 = 55, //7 354 VK_NUM8 = 56, //8 355 VK_NUM9 = 57, //9 356 VK_A = 65, //A 357 VK_B = 66, //B 358 VK_C = 67, //C 359 VK_D = 68, //D 360 VK_E = 69, //E 361 VK_F = 70, //F 362 VK_G = 71, //G 363 VK_H = 72, //H 364 VK_I = 73, //I 365 VK_J = 74, //J 366 VK_K = 75, //K 367 VK_L = 76, //L 368 VK_M = 77, //M 369 VK_N = 78, //N 370 VK_O = 79, //O 371 VK_P = 80, //P 372 VK_Q = 81, //Q 373 VK_R = 82, //R 374 VK_S = 83, //S 375 VK_T = 84, //T 376 VK_U = 85, //U 377 VK_V = 86, //V 378 VK_W = 87, //W 379 VK_X = 88, //X 380 VK_Y = 89, //Y 381 VK_Z = 90, //Z 382 VK_NUMPAD0 = 96, //0 383 VK_NUMPAD1 = 97, //1 384 VK_NUMPAD2 = 98, //2 385 VK_NUMPAD3 = 99, //3 386 VK_NUMPAD4 = 100, //4 387 VK_NUMPAD5 = 101, //5 388 VK_NUMPAD6 = 102, //6 389 VK_NUMPAD7 = 103, //7 390 VK_NUMPAD8 = 104, //8 391 VK_NUMPAD9 = 105, //9 392 VK_NULTIPLY = 106, //数字键盘上的* 393 VK_ADD = 107, //数字键盘上的+ 394 VK_SEPARATOR = 108, //可选 395 VK_SUBTRACT = 109, //数字键盘上的- 396 VK_DECIMAL = 110, //数字键盘上的. 397 VK_DIVIDE = 111, //数字键盘上的/ 398 VK_F1 = 112, 399 VK_F2 = 113, 400 VK_F3 = 114, 401 VK_F4 = 115, 402 VK_F5 = 116, 403 VK_F6 = 117, 404 VK_F7 = 118, 405 VK_F8 = 119, 406 VK_F9 = 120, 407 VK_F10 = 121, 408 VK_F11 = 122, 409 VK_F12 = 123, 410 VK_NUMLOCK = 144, //Num Lock 411 VK_SCROLL = 145 // Scroll Lock 412 } 413 } 414 415 注:using System.Management需要添加System.Management的引用,否则编译容易出错