在纯C#中使用extern`kernel32.dll`函数重写代码,以便与Mono一起工作[重复]

问题描述 投票:0回答:1

TL;DR

我想实现从 kernel32.dll 在纯C#中(ReadProcessMemoryCloseHandle)因为 kernel32.dll 是Windows特有的,我需要运行它们 在GNULinux下使用Mono.


我有下面的C#代码来读取给定进程的特定地址的内容;它依靠的是 extern 的函数,基于 kernel32.dll :

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace MyProject
{
    public enum ProcessAccess : int
    {
        VM_READ = 0x0010,
    }

    class ReadMemory
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(ProcessAccess dwDesiredAccess,
            bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll")]
        static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress,
            byte[] lpBuffer, IntPtr dwSize, ref int lpNumberOfBytesRead);

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

        static string GetProcessContentAtAddress(string processName, int address, int contentLength) {
            Process process = Process.GetProcessesByName(processName)[0];
            IntPtr processHandle = OpenProcess(ProcessAccess.VM_READ, false, process.Id);

            UIntPtr addressPtr = (UIntPtr)address;
            byte[] buffer = new byte[contentLength];

            int lpNumberOfBytesRead = 0;

            ReadProcessMemory(processHandle, addressPtr, buffer,
                (IntPtr)buffer.Length, ref lpNumberOfBytesRead);

            string contents = BitConverter.ToString(buffer);

            CloseHandle(processHandle);

            return contents;
        }

        static void Main(string[] args)
        {
            // read 4 bytes at address 0x12345678 of my_process
            Console.WriteLine(
                GetProcessContentAtAddress("my_process", 0x12345678, 4)
            );
        }
    }
}

这在Windows下工作,这里是一个预期结果的例子。

00-04-A8-00

但使用 单声道 在GNULinux上, kernel32.dll 是不存在的,执行代码会返回一个错误。

[ERROR] FATAL UNHANDLED EXCEPTION:
System.EntryPointNotFoundException: OpenProcess assembly:<unknown assembly> type:<unknown type> member:(null)
  at (wrapper managed-to-native) MyProject.ReadMemory.OpenProcess(MyProject.ProcessAccess,bool,int)
  at MyProject.ReadMemory.GetProcessContentAtAddress (System.String processName, System.Int32 address, System.Int32 contentLength) [0x00029] in <e1ed4e23c9fb45098da80208134b52bb>:0 
  at MyProject.ReadMemory.Main (System.String[] args) [0x00001] in <e1ed4e23c9fb45098da80208134b52bb>:0

我的想法是用纯粹的C#语言重写3 extern 职能 (OpenProcess, ReadProcessMemoryCloseHandle),以避免依靠 kernel32.dll :

static IntPtr OpenProcess(ProcessAccess dwDesiredAccess,
    bool bInheritHandle, int dwProcessId) {
        return System.Diagnostics.Process
            .GetProcessById(dwProcessId).Handle;
}

static bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress,
    byte[] lpBuffer, IntPtr dwSize, ref int lpNumberOfBytesRead) {
        // ???
        return true;
}

static bool CloseHandle(IntPtr hObject) {
    // ???
    return true;
}

OpenProcess 似乎在工作 在GNULinux上使用Mono. 但是,由于我没有使用 dwDesiredAccessbInheritedHandle我想它在Windows上可能无法工作(我没有Windows机器来测试它)。

我不知道如何编写另外两个函数(ReadProcessMemoryCloseHandle)中的纯C#(或至少不依赖 kernel32.dll),既能在Windows 并在GNULinux下使用Mono.

有谁有实现的想法,或者只是在这些功能中使用的类?也许我应该依靠Windows和Mono上的另一个DLL来完成这项工作?我不是一个C#专家。

编辑

替换时 [DllImport("kernel32.dll")][DllImport("kernel32")]当运行 在GNULinux下使用Mono :

[ERROR] FATAL UNHANDLED EXCEPTION:
System.DllNotFoundException: kernel32 assembly:<unknown assembly> type:<unknown type> member:(null)
  at (wrapper managed-to-native) MyProject.ReadMemory.OpenProcess(MyProject.ProcessAccess,bool,int)
  at MyProject.ReadMemory.GetProcessContentAtAddress (System.String processName, System.Int32 address, System.Int32 contentLength) [0x00013] in <411171bde77146b8b0aa4953209bbc2e>:0 
  at MyProject.ReadMemory.Main (System.String[] args) [0x00001] in <411171bde77146b8b0aa4953209bbc2e>:0

如果能帮上忙的话。

c# mono kernel32
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.