TL;DR
Я хочу реализовать функции из kernel32.dll
на чистом C# (ReadProcessMemory
и CloseHandle
), потому что kernel32.dll
зависит от Windows, и мне нужно запускать их в Mono под GNU/Linux.
У меня есть следующий код С# для чтения содержимого по определенному адресу данного процесса; он опирается на 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
но при использовании Mono в GNU/Linux 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
работает с Mono в GNU/Linux. Но, поскольку я не использую dwDesiredAccess
и bInheritedHandle
, я думаю, что это может не работать в Windows (у меня нет компьютера с Windows, чтобы проверить это).
Я понятия не имею, как написать две другие функции (ReadProcessMemory
и CloseHandle
) на чистом C# (или, по крайней мере, не зависящем от kernel32.dll
), которые будут работать как в Windows , так и под GNU/Linux с использованием Mono .
Есть ли у кого-нибудь идеи реализации или просто классы, которые можно было бы использовать в этих функциях? Может быть, мне следует полагаться на другую DLL, присутствующую в Windows и Mono, которая уже выполняет эту работу? Я не эксперт в C#.
Редактировать
При замене [DllImport("kernel32.dll")]
на [DllImport("kernel32")]
я получил новую ошибку при работе с Mono под 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
Если бы это могло помочь.
kernel32.dll
- это dll для Windows, вы не можете использовать ее в Linux. - person Pavel Anikhouski   schedule 26.04.2020kernel32.dll
? Я хотел бы найти замену, которая будет работать под GNU/Linux с Mono. - person norbjd   schedule 26.04.2020kernel32.dll
, поэтому[DllImport("kernel32.dll")]
не удалось импортировать функцию, поскольку она определена какextern
. - person norbjd   schedule 26.04.2020OpenProcess
например? Если я не определяю его как методstatic extern
, как я могу вызватьOpenProcess
? Есть что импортировать? В каждом примере, который я видел, эти методы определены какstatic extern
(например, stackoverflow.com/questions/34467311/) сDLLImport
. - person norbjd   schedule 26.04.2020[DllImport("kernel32.dll")]
на[DllImport("kernel32")]
, и получил новую ошибку при запуске с Mono в GNU/Linux. Я проверил и действительно не могу найтиkernel32.dll
в моем контейнере Docker для сборки (я строю его в контейнере, чтобы иметь свежую среду). - person norbjd   schedule 26.04.2020.dll
в директивеDLLImport
. Я пытался просто посмотреть. В любом случае не получается :( У вас есть идея? Можем продолжить обсуждение здесь, чтобы избежать затянувшихся дискуссий в комментариях: chat.stackoverflow.com/rooms/212545/ - person norbjd   schedule 26.04.2020