我想实现从 kernel32.dll
在纯C#中(ReadProcessMemory
和 CloseHandle
)因为 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
, ReadProcessMemory
和 CloseHandle
),以避免依靠 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. 但是,由于我没有使用 dwDesiredAccess
和 bInheritedHandle
我想它在Windows上可能无法工作(我没有Windows机器来测试它)。
我不知道如何编写另外两个函数(ReadProcessMemory
和 CloseHandle
)中的纯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
如果能帮上忙的话。