WinAPI OpenProcess拒绝访问

时间:2018-08-13 19:15:09

标签: c# winapi pinvoke

因此,我决定出于教育目的将DLL注入记事本进程。

IntPtr hProcess = OpenProcess(ProcessAccessFlags.VirtualMemoryWrite | ProcessAccessFlags.VirtualMemoryWrite | ProcessAccessFlags.VirtualMemoryOperation, false, process.Id);           
_log.Info({0}, new Win32Exception(Marshal.GetLastWin32Error()).Message);

这似乎因“拒绝访问”而失败。奇怪的是hProcess不是IntPtr.Zero,它看起来像一个句柄。因此,我不确定它是否真的失败了。

我尝试过的事情如下。

  • 以管理员身份启动Visual Studio 2017
  • 使用Process.EnterDebugMode();
  • 其他访问标志,包括0x001F0FFF

整个课程都在下面(不再位于粘贴容器上)。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;

namespace Blade.Injector
{
class Injector
{
    private readonly NLog.Logger _log = NLog.LogManager.GetCurrentClassLogger();

    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);

    [Flags]
    public enum AllocationType
    {
        Commit = 0x1000,
        Reserve = 0x2000,
        Decommit = 0x4000,
        Release = 0x8000,
        Reset = 0x80000,
        Physical = 0x400000,
        TopDown = 0x100000,
        WriteWatch = 0x200000,
        LargePages = 0x20000000
    }

    [Flags]
    public enum MemoryProtection
    {
        Execute = 0x10,
        ExecuteRead = 0x20,
        ExecuteReadWrite = 0x40,
        ExecuteWriteCopy = 0x80,
        NoAccess = 0x01,
        ReadOnly = 0x02,
        ReadWrite = 0x04,
        WriteCopy = 0x08,
        GuardModifierflag = 0x100,
        NoCacheModifierflag = 0x200,
        WriteCombineModifierflag = 0x400
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    [SuppressUnmanagedCodeSecurity]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle(IntPtr hObject);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processId);

    [Flags]
    public enum ProcessAccessFlags : uint
    {
        All = 0x001F0FFF,
        Terminate = 0x00000001,
        CreateThread = 0x00000002,
        VirtualMemoryOperation = 0x00000008,
        VirtualMemoryRead = 0x00000010,
        VirtualMemoryWrite = 0x00000020,
        DuplicateHandle = 0x00000040,
        CreateProcess = 0x000000080,
        SetQuota = 0x00000100,
        SetInformation = 0x00000200,
        QueryInformation = 0x00000400,
        QueryLimitedInformation = 0x00001000,
        Synchronize = 0x00100000
    }        

    private const string DllFile = @"C:\Poison.dll";

    public void List()
    {
        var processes = Process.GetProcesses().Where(p => !string.IsNullOrEmpty(p.MainWindowTitle)).ToList();

        foreach (var process in processes)
        {
            _log.Info("{0} -> {1}", process.MainWindowTitle, process.Id);
        }
    }

    public bool Inject(int pid)
    {                                       
        Process.EnterDebugMode();

        Process process = Process.GetProcessById(pid);                        

        foreach (ProcessModule module in process.Modules)
        {
            if (module.FileName.Equals(DllFile))
            {
                _log.Info("{0} already inside process.", module.FileName);
                return false;
            }
        }

        _log.Info("Opening process. Last Win32 error is now '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
        IntPtr hProcess = OpenProcess(ProcessAccessFlags.VirtualMemoryWrite | ProcessAccessFlags.VirtualMemoryWrite | ProcessAccessFlags.VirtualMemoryOperation, false, process.Id);           
        _log.Info("Opening process resulted in message '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);

        _log.Info("Allocating memory for dll file.");            
        IntPtr allocAddress = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)Encoding.Unicode.GetByteCount(DllFile.ToCharArray()), AllocationType.Commit, MemoryProtection.ReadWrite);
        _log.Info("Allocating memory for '{0}' resulted in '{1}'.", DllFile, new Win32Exception(Marshal.GetLastWin32Error()).Message);

        CloseHandle(hProcess);

        foreach (ProcessModule module in process.Modules)
        {
            if (module.FileName.Equals(DllFile))
            {
                _log.Info("Success! {0} inside process.", module.FileName);
            }
        }

        return true;
    }

}
}
  • 如何确保new Win32Exception(Marshal.GetLastWin32Error()).Message)中的消息与上次通话有关?也许其他事情失败了?
  • 如何在没有访问被拒绝的消息的情况下打开进程?
  • 我如何知道OpenProcess()方法是否在C#中有效?是否正在检查hProcess是否IntPtr.Zero正常?

1 个答案:

答案 0 :(得分:2)

第一个找到答案的地方

  

我怎么知道(任何功能)是否起作用?

将在该功能的文档页面中。对于OpenProcess(),文档页面为https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openprocess

除其他外,该页面包含以下语句:

  

如果函数成功,则返回值是指定进程的打开句柄。

     

如果函数失败,则返回值为NULL。要获取扩展的错误信息,请调用GetLastError。

将基本逻辑应用于第二条语句,我们得出结论

  • 如果返回值不为NULL,则函数没有失败。

因此,比较返回值与IntPtr.Zero是可以的,实际上是最好的方法。

还请注意,“要获取扩展的错误信息,请调用GetLastError。”属于“如果功能失败”。如果函数成功,则没有详细的错误信息,因此您没有理由调用GetLastError,也没有理由解释它的结果。