从受保护的进程内存中读取

时间:2016-04-26 08:03:44

标签: c# winapi

我试图读取进程的内存。

实际代码循环过程'记忆和搜索值,但这是一般的想法。

我正在为x64编译并尝试读取x64进程。

此代码在调用VirtualProtectEx后失败,错误代码为5(ERROR_ACCESS_DENIED)或错误代码为487(ERROR_INVALID_ADDRESS),具体取决于所选的进程。

  • 我在读这个过程'记忆是否正确?
  • VirtualProtectEx如何通过拒绝访问失败?
  • 我还没考虑其他保护方法吗?
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace ReadProcessMemoryTest {
    public class Program {
        public static void Main(string[] args) {
            string processName = "ProcessName";
            IntPtr startAddress = new IntPtr(0x00000000);
            IntPtr endAddress = new IntPtr(0x7FFFFFFF);
            uint bytesToRead = 8;
            int errorCode = 0;

            // Ensure running as admin
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
            WindowsPrincipal principal = new WindowsPrincipal(identity);
            if(!principal.IsInRole(WindowsBuiltInRole.Administrator)){
                throw new Exception("Not running as administrator");
            }

            // Turn on SeDebugPrivilege
            Process.EnterDebugMode();

            // Select the process
            Process process = Process.GetProcessesByName(processName)[0];

            // Get a handle to the process with all access rights
            IntPtr processHandle = OpenProcess(0x001F0FFF, 1, (uint)process.Id);

            // Check for errors
            errorCode = Marshal.GetLastWin32Error();
            if(errorCode != 0) {
                throw new Exception("OpenProcess error: " + errorCode);
            }

            // Set the protection level of these 8 bytes to execute, read and write
            uint prevProtection = 0;
            VirtualProtectEx(processHandle, startAddress, new UIntPtr(bytesToRead), 0x40, out prevProtection);

            // Check for errors
            errorCode = Marshal.GetLastWin32Error();
            if(errorCode != 0) {
                throw new Exception("VirtualProtectEx error: " + errorCode);
            }

            // Read some bytes into an array
            byte[] buffer = new byte[bytesToRead];
            IntPtr bytesRead;
            ReadProcessMemory(processHandle, startAddress, buffer, bytesToRead, out bytesRead);

            // Check for errors
            errorCode = Marshal.GetLastWin32Error();
            if(errorCode != 0) {
                throw new Exception("ReadProcessMemory error: " + errorCode);
            }

            // Close the process handle
            CloseHandle(processHandle);
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);

        [DllImport("kernel32.dll")]
        public static extern Int32 CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern Int32 VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
    }
}

1 个答案:

答案 0 :(得分:1)

EnterDebugMode()不够,您需要显式调整AdjustTokenPrivileges

using System;
using System.Runtime.InteropServices;

public class TokenManipulator
{
 [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
 internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
 ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
 [DllImport("kernel32.dll", ExactSpelling = true)]
 internal static extern IntPtr GetCurrentProcess();
 [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
 internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
 [DllImport("advapi32.dll", SetLastError = true)]
 internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
 [StructLayout(LayoutKind.Sequential, Pack = 1)]
 internal struct TokPriv1Luid
 {
  public int Count;
  public long Luid;
  public int Attr;
 }
 internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
 internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
 internal const int TOKEN_QUERY = 0x00000008;
 internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
 public static bool AddPrivilege(string privilege)
 {
  try
  {
   bool retVal;
   TokPriv1Luid tp;
   IntPtr hproc = GetCurrentProcess();
   IntPtr htok = IntPtr.Zero;
   retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
   tp.Count = 1;
   tp.Luid = 0;
   tp.Attr = SE_PRIVILEGE_ENABLED;
   retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
   retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
   return retVal;
  }
  catch (Exception ex)
  {
   throw ex;
  }
 }