ProcessHelper.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Net.NetworkInformation;
  6. using System.Runtime.InteropServices;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows;
  10. namespace WechatPCMsgBakTool.Helpers
  11. {
  12. public class ProcessHelper
  13. {
  14. private const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
  15. private const int DUPLICATE_SAME_ACCESS = 0x2;
  16. private const int CNST_SYSTEM_HANDLE_INFORMATION = 0x10;
  17. public static Process GetProcess(string ProcessName)
  18. {
  19. Process[] processes = Process.GetProcessesByName(ProcessName);
  20. if (processes.Length == 0)
  21. return null;
  22. else if(processes.Length > 1) {
  23. SelectWechat selectWechat = new SelectWechat();
  24. MessageBox.Show("检测到有多个微信,请选择本工作区对应的微信");
  25. selectWechat.ShowDialog();
  26. if (selectWechat.SelectProcess == null)
  27. return null;
  28. Process? p = processes.ToList().Find(x => x.Id.ToString() == selectWechat.SelectProcess.ProcessId);
  29. if (p == null)
  30. return null;
  31. return p;
  32. }
  33. else
  34. return processes[0];
  35. }
  36. public static ProcessModule? FindProcessModule(int ProcessId, string ModuleName)
  37. {
  38. Process process = Process.GetProcessById(ProcessId);
  39. foreach (ProcessModule module in process.Modules)
  40. {
  41. if (module.ModuleName == ModuleName)
  42. return module;
  43. }
  44. return null;
  45. }
  46. public static List<int> FindProcessMemory(IntPtr processHandle, ProcessModule module, string content)
  47. {
  48. byte[] buffer = new byte[module.ModuleMemorySize];
  49. byte[] search = Encoding.ASCII.GetBytes(content);
  50. // 逐页读取数据
  51. List<int> offset = new List<int>();
  52. int readBytes;
  53. bool success = ReadProcessMemory(processHandle, module.BaseAddress, buffer, buffer.Length,out readBytes);
  54. if (!success || readBytes == 0)
  55. {
  56. int error = Marshal.GetLastWin32Error();
  57. Console.WriteLine($"ReadProcessMemory failed. GetLastError: {error}");
  58. }
  59. else
  60. {
  61. for (int i = 0; i < buffer.Length; i++)
  62. {
  63. if (buffer[i] == search[0])
  64. {
  65. for (int s = 1; s < search.Length; s++)
  66. {
  67. if (buffer[i + s] != search[s])
  68. break;
  69. if (s == search.Length - 1)
  70. offset.Add(i);
  71. }
  72. }
  73. }
  74. }
  75. return offset;
  76. }
  77. public static List<SYSTEM_HANDLE_INFORMATION> GetHandles(Process process)
  78. {
  79. List<SYSTEM_HANDLE_INFORMATION> aHandles = new List<SYSTEM_HANDLE_INFORMATION>();
  80. int handle_info_size = Marshal.SizeOf(new SYSTEM_HANDLE_INFORMATION()) * 20000;
  81. IntPtr ptrHandleData = IntPtr.Zero;
  82. try
  83. {
  84. ptrHandleData = Marshal.AllocHGlobal(handle_info_size);
  85. int nLength = 0;
  86. while (NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ptrHandleData, handle_info_size, ref nLength) == STATUS_INFO_LENGTH_MISMATCH)
  87. {
  88. handle_info_size = nLength;
  89. Marshal.FreeHGlobal(ptrHandleData);
  90. ptrHandleData = Marshal.AllocHGlobal(nLength);
  91. }
  92. long handle_count = Marshal.ReadIntPtr(ptrHandleData).ToInt64();
  93. IntPtr ptrHandleItem = ptrHandleData + Marshal.SizeOf(ptrHandleData);
  94. for (long lIndex = 0; lIndex < handle_count; lIndex++)
  95. {
  96. SYSTEM_HANDLE_INFORMATION? oSystemHandleInfo = new SYSTEM_HANDLE_INFORMATION();
  97. oSystemHandleInfo = Marshal.PtrToStructure(ptrHandleItem, oSystemHandleInfo.GetType()) as SYSTEM_HANDLE_INFORMATION?;
  98. if (oSystemHandleInfo == null)
  99. throw new Exception("获取SYSTEM_HANDLE_INFORMATION失败");
  100. ptrHandleItem += Marshal.SizeOf(new SYSTEM_HANDLE_INFORMATION());
  101. if (oSystemHandleInfo.Value.ProcessID != process.Id) { continue; }
  102. aHandles.Add(oSystemHandleInfo.Value);
  103. }
  104. }
  105. catch (Exception)
  106. {
  107. throw;
  108. }
  109. finally
  110. {
  111. Marshal.FreeHGlobal(ptrHandleData);
  112. }
  113. return aHandles;
  114. }
  115. public static string FindHandleName(SYSTEM_HANDLE_INFORMATION systemHandleInformation, Process process)
  116. {
  117. IntPtr ipHandle = IntPtr.Zero;
  118. IntPtr openProcessHandle = IntPtr.Zero;
  119. IntPtr hObjectName = IntPtr.Zero;
  120. try
  121. {
  122. PROCESS_ACCESS_FLAGS flags = PROCESS_ACCESS_FLAGS.DupHandle | PROCESS_ACCESS_FLAGS.VMRead;
  123. openProcessHandle = OpenProcess(flags, false, process.Id);
  124. // 通过 DuplicateHandle 访问句柄
  125. if (!DuplicateHandle(openProcessHandle, new IntPtr(systemHandleInformation.Handle), GetCurrentProcess(), out ipHandle, 0, false, DUPLICATE_SAME_ACCESS))
  126. {
  127. return "";
  128. }
  129. int nLength = 0;
  130. hObjectName = Marshal.AllocHGlobal(256 * 1024);
  131. // 查询句柄名称
  132. while ((uint)(NtQueryObject(ipHandle, (int)OBJECT_INFORMATION_CLASS.ObjectNameInformation, hObjectName, nLength, ref nLength)) == STATUS_INFO_LENGTH_MISMATCH)
  133. {
  134. Marshal.FreeHGlobal(hObjectName);
  135. if (nLength == 0)
  136. {
  137. Console.WriteLine("Length returned at zero!");
  138. return "";
  139. }
  140. hObjectName = Marshal.AllocHGlobal(nLength);
  141. }
  142. OBJECT_NAME_INFORMATION? objObjectName = new OBJECT_NAME_INFORMATION();
  143. objObjectName = Marshal.PtrToStructure(hObjectName, objObjectName.GetType()) as OBJECT_NAME_INFORMATION?;
  144. if (objObjectName == null)
  145. return "";
  146. if (objObjectName.Value.Name.Buffer != IntPtr.Zero)
  147. {
  148. string? strObjectName = Marshal.PtrToStringUni(objObjectName.Value.Name.Buffer);
  149. if (strObjectName != null)
  150. return strObjectName;
  151. }
  152. }
  153. catch (Exception ex)
  154. {
  155. Console.WriteLine(ex.Message);
  156. }
  157. finally
  158. {
  159. Marshal.FreeHGlobal(hObjectName);
  160. CloseHandle(ipHandle);
  161. CloseHandle(openProcessHandle);
  162. }
  163. return "";
  164. }
  165. // 这里开始下面是对Windows API引用声明
  166. public static byte[]? ReadMemoryDate(IntPtr hProcess, IntPtr lpBaseAddress, int nSize = 100)
  167. {
  168. byte[] array = new byte[nSize];
  169. int readByte;
  170. if (!ReadProcessMemory(hProcess, lpBaseAddress, array, nSize, out readByte))
  171. return null;
  172. else
  173. return array;
  174. }
  175. [DllImport("kernel32.dll", SetLastError = true)]
  176. public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int nSize, out int lpNumberOfBytesRead);
  177. [DllImport("ntdll.dll")]
  178. private static extern uint NtQuerySystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, ref int returnLength);
  179. [DllImport("kernel32.dll")]
  180. private static extern IntPtr OpenProcess(PROCESS_ACCESS_FLAGS dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
  181. [DllImport("kernel32.dll", SetLastError = true)]
  182. [return: MarshalAs(UnmanagedType.Bool)]
  183. private static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
  184. [DllImport("kernel32.dll")]
  185. private static extern IntPtr GetCurrentProcess();
  186. [DllImport("ntdll.dll")]
  187. private static extern int NtQueryObject(IntPtr ObjectHandle, int ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength, ref int returnLength);
  188. [DllImport("kernel32.dll")]
  189. private static extern bool CloseHandle(IntPtr hObject);
  190. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  191. public struct SYSTEM_HANDLE_INFORMATION
  192. { // Information Class 16
  193. public ushort ProcessID;
  194. public ushort CreatorBackTrackIndex;
  195. public byte ObjectType;
  196. public byte HandleAttribute;
  197. public ushort Handle;
  198. public IntPtr Object_Pointer;
  199. public IntPtr AccessMask;
  200. }
  201. private enum OBJECT_INFORMATION_CLASS : int
  202. {
  203. ObjectBasicInformation = 0,
  204. ObjectNameInformation = 1,
  205. ObjectTypeInformation = 2,
  206. ObjectAllTypesInformation = 3,
  207. ObjectHandleInformation = 4
  208. }
  209. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  210. private struct OBJECT_NAME_INFORMATION
  211. {
  212. public UNICODE_STRING Name;
  213. }
  214. [StructLayout(LayoutKind.Sequential)]
  215. private struct UNICODE_STRING
  216. {
  217. public ushort Length;
  218. public ushort MaximumLength;
  219. public IntPtr Buffer;
  220. }
  221. [Flags]
  222. private enum PROCESS_ACCESS_FLAGS : uint
  223. {
  224. All = 0x001F0FFF,
  225. Terminate = 0x00000001,
  226. CreateThread = 0x00000002,
  227. VMOperation = 0x00000008,
  228. VMRead = 0x00000010,
  229. VMWrite = 0x00000020,
  230. DupHandle = 0x00000040,
  231. SetInformation = 0x00000200,
  232. QueryInformation = 0x00000400,
  233. Synchronize = 0x00100000
  234. }
  235. }
  236. }