Rewrite code using extern `kernel32.dll` functions in pure C# to work with Mono [duplicate]

人走茶凉 提交于 2020-04-30 06:24:08

问题


TL;DR

I want to implement functions from kernel32.dll in pure C# (ReadProcessMemory and CloseHandle) because kernel32.dll is Windows specific and I need to run them with Mono under GNU/Linux.


I have the following C# code to read contents at a specific address of a given process; it relies on extern functions based on 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)
            );
        }
    }
}

This works under Windows, here is an example of the expected result :

00-04-A8-00

but using Mono on GNU/Linux, kernel32.dll is not present and executing the code returns an error :

[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

My idea was to rewrite in pure C# the 3 extern functions (OpenProcess, ReadProcessMemory and CloseHandle), to avoid relying on 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 appears to work with Mono on GNU/Linux. But, since I don't use dwDesiredAccess and bInheritedHandle, I think it may not work on Windows (I don't have a Windows machine to test it).

I have no idea how to write the other 2 functions (ReadProcessMemory and CloseHandle) in pure C# (or at least that does not rely on kernel32.dll) that will work both in Windows and under GNU/Linux using Mono.

Does anybody have ideas of implementation or just classes that would work to use in these functions? Maybe should I rely on another DLL present on Windows and Mono that already does that job? I am not an expert in C#.

Edit

When replacing [DllImport("kernel32.dll")] to [DllImport("kernel32")], I got a new error when running with Mono under GNU/Linux :

[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

If that could help.

来源:https://stackoverflow.com/questions/61438447/rewrite-code-using-extern-kernel32-dll-functions-in-pure-c-sharp-to-work-with

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!