NativeAPIHelper.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using static WechatBakTool.Helpers.NativeAPI;
  9. namespace WechatBakTool.Helpers
  10. {
  11. public class NativeAPIHelper
  12. {
  13. // Managed native buffer
  14. internal static IntPtr AllocManagedMemory(uint iSize)
  15. {
  16. IntPtr pAlloc = Marshal.AllocHGlobal((int)iSize);
  17. RtlZeroMemory(pAlloc, iSize);
  18. return pAlloc;
  19. }
  20. // Free managed buffer
  21. internal static bool FreeManagedMemory(IntPtr pAlloc)
  22. {
  23. Marshal.FreeHGlobal(pAlloc);
  24. return true;
  25. }
  26. // Get an array of OBJECT_ALL_TYPES_INFORMATION, describing all object types
  27. // Win8+ only
  28. internal static string FindHandleName(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX systemHandleInformation, Process process)
  29. {
  30. IntPtr ipHandle = IntPtr.Zero;
  31. IntPtr openProcessHandle = IntPtr.Zero;
  32. IntPtr hObjectName = IntPtr.Zero;
  33. try
  34. {
  35. PROCESS_ACCESS_FLAGS flags = PROCESS_ACCESS_FLAGS.DupHandle | PROCESS_ACCESS_FLAGS.VMRead;
  36. openProcessHandle = OpenProcess(flags, false, process.Id);
  37. // 通过 DuplicateHandle 访问句柄
  38. if (!DuplicateHandle(openProcessHandle, systemHandleInformation.HandleValue, GetCurrentProcess(), out ipHandle, 0, false, DUPLICATE_SAME_ACCESS))
  39. {
  40. return "";
  41. }
  42. uint nLength = 0;
  43. hObjectName = AllocManagedMemory(256 * 1024);
  44. Task.Run(() =>
  45. {
  46. // 查询句柄名称
  47. while (NtQueryObject(ipHandle, OBJECT_INFORMATION_CLASS.ObjectNameInformation, hObjectName, nLength, ref nLength) == NTSTATUS_STATUS_INFO_LENGTH_MISMATCH)
  48. {
  49. FreeManagedMemory(hObjectName);
  50. if (nLength == 0)
  51. {
  52. Console.WriteLine("Length returned at zero!");
  53. }
  54. hObjectName = AllocManagedMemory(nLength);
  55. }
  56. }).Wait(100);
  57. OBJECT_NAME_INFORMATION? objObjectName = new OBJECT_NAME_INFORMATION();
  58. objObjectName = Marshal.PtrToStructure(hObjectName, objObjectName.GetType()) as OBJECT_NAME_INFORMATION?;
  59. if (objObjectName == null)
  60. return "";
  61. if (objObjectName.Value.Name.Buffer != IntPtr.Zero)
  62. {
  63. string? strObjectName = Marshal.PtrToStringUni(objObjectName.Value.Name.Buffer);
  64. if (strObjectName != null)
  65. return strObjectName;
  66. }
  67. }
  68. catch (Exception ex)
  69. {
  70. Console.WriteLine(ex.Message);
  71. }
  72. finally
  73. {
  74. FreeManagedMemory(hObjectName);
  75. CloseHandle(ipHandle);
  76. CloseHandle(openProcessHandle);
  77. }
  78. return "";
  79. }
  80. internal static List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> GetHandleInfoForPID(uint ProcId)
  81. {
  82. // Create return object
  83. List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> ltei = new List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX>();
  84. // Create Buffer variable
  85. IntPtr BuffPtr = IntPtr.Zero;
  86. // Loop till success
  87. uint LoopSize = 0;
  88. while (true)
  89. {
  90. BuffPtr = AllocManagedMemory(LoopSize);
  91. uint SystemInformationLength = 0;
  92. uint CallRes = NtQuerySystemInformation(SystemExtendedHandleInformation, BuffPtr, LoopSize, ref SystemInformationLength);
  93. if (CallRes == NTSTATUS_STATUS_INFO_LENGTH_MISMATCH)
  94. {
  95. FreeManagedMemory(BuffPtr);
  96. LoopSize = Math.Max(LoopSize, SystemInformationLength);
  97. }
  98. else if (CallRes == NTSTATUS_STATUS_SUCCESS)
  99. {
  100. break;
  101. }
  102. else if (CallRes == NTSTATUS_STATUS_ACCESS_DENIED)
  103. {
  104. FreeManagedMemory(BuffPtr);
  105. throw new AccessViolationException("[!] Failed to query SystemExtendedHandleInformation: Access Denied");
  106. }
  107. else
  108. {
  109. FreeManagedMemory(BuffPtr);
  110. throw new InvalidOperationException("[!] Failed to query SystemExtendedHandleInformation.");
  111. }
  112. }
  113. // Read handle count
  114. Int32 HandleCount = Marshal.ReadInt32(BuffPtr);
  115. // Move Buff ptr
  116. BuffPtr = (IntPtr)(BuffPtr.ToInt64() + (IntPtr.Size * 2));
  117. // Loop handles
  118. for (int i = 0; i < HandleCount; i++)
  119. {
  120. ulong iCurrProcId = (ulong)Marshal.ReadIntPtr((IntPtr)(BuffPtr.ToInt64() + IntPtr.Size));
  121. if (ProcId == iCurrProcId)
  122. {
  123. // Ptr -> SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
  124. SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX? tei = (SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX?)Marshal.PtrToStructure(BuffPtr, typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX));
  125. if (tei == null)
  126. continue;
  127. else
  128. ltei.Add(tei.Value);
  129. }
  130. // Move Buffptr
  131. BuffPtr = (IntPtr)(BuffPtr.ToInt64() + Marshal.SizeOf(typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)));
  132. }
  133. // Return list
  134. return ltei;
  135. }
  136. public static List<long> SearchProcessAllMemory(Process process, string searchString)
  137. {
  138. IntPtr minAddress = IntPtr.Zero;
  139. IntPtr maxAddress = IntPtr.MaxValue;
  140. List<long> addrList = new List<long>();
  141. while (minAddress.ToInt64() < maxAddress.ToInt64())
  142. {
  143. MEMORY_BASIC_INFORMATION64 memInfo;
  144. int result = VirtualQueryEx(process.Handle, minAddress, out memInfo, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64)));
  145. if (result == 0)
  146. {
  147. break;
  148. }
  149. if (memInfo.State == MEM_COMMIT && (memInfo.Protect == PAGE_EXECUTE || memInfo.Protect == PAGE_EXECUTE_READ || memInfo.Protect == PAGE_EXECUTE_READ || memInfo.Protect == PAGE_READWRITE || memInfo.Protect == PAGE_READONLY))
  150. {
  151. byte[] buffer = new byte[(long)memInfo.RegionSize];
  152. bool success = ReadProcessMemory(process.Handle, memInfo.BaseAddress, buffer, buffer.Length, out _);
  153. if (success)
  154. {
  155. byte[] search = Encoding.ASCII.GetBytes(searchString);
  156. for (int i = 0; i < buffer.Length - 8; i++)
  157. {
  158. if (buffer[i] == search[0])
  159. {
  160. for (int s = 1; s < search.Length; s++)
  161. {
  162. if (buffer[i + s] != search[s])
  163. break;
  164. if (s == search.Length - 1)
  165. {
  166. addrList.Add((long)memInfo.BaseAddress + i);
  167. }
  168. }
  169. }
  170. }
  171. }
  172. }
  173. minAddress = new IntPtr(memInfo.BaseAddress.ToInt64() + (long)memInfo.RegionSize);
  174. }
  175. return addrList;
  176. }
  177. }
  178. }