导入用于在 C# 中分配虚拟内存的 kernel32 函数?
Importing kernel32 functions for allocating virtual memory in C#?
我的硬盘上有几个 DLL 文件。我服务器上的一个进程包含重要的文件数据,我想通过在进程内分配虚拟内存来记录这些数据。我没有那个过程的源代码,所以我需要采取更多的极端措施。我想让它启动 DLL 主函数。外部内存的分配需要用C#写,因为我想用在WPF中
如何用C#在另一个进程中执行自己的源代码?
为了在进程中执行您自己的源代码,您需要为进程虚拟分配内存,并将您的 DLL 路径写入您分配的内存地址。您将使用该 DLL 路径通过 kernel32.dll LoadLibraryW
中的导出函数将您的 dll 弹射到进程中。
windows 平台上的每个进程都有专用于该进程的指定内存大小。原因之一是出于安全考虑,一个进程不能向其他进程读取或写入数据。所以为了能够 write/inject 你的 DLL 你需要打开一个 HANDLE
。如果从 kernel32.dll 导入 OpenProcess
函数,则可以执行此操作。这简要意味着您正在使用 windows api。以下是如何在 C#
中导入 kernel32 DLL
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(
uint dwDesiredAccess,
int bInheritHandle,
uint dwProcessId
);
You can find the full documentation of the windows api in the holy bible
现在,您想使用 OpenProcess 函数为您从中获得句柄的进程分配内存。使用VirtualAllocEx函数,参考MSDN
How hath thou allocated thou memory?
LPVOID WINAPI VirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
);
正如我们所见,它有 5 个参数。您之前收集的 HANDLE
object。我们不会使用的可选参数。如果将 DLL 转换为字节数组,则可以获得 DLL 的大小。内存分配的类型,我们想要保留和提交分配,所以使用 (0x1000 | 0x2000) 并最后保护我们将写入的已分配内存 0x40.
步骤 1 分配内存 ✓
STEP 2 写入DLL路径
步骤 3 使用 LoadLibraryW
第二步涉及到使用WriteProcessMemory简单的将dll路径写入内存。将字符串转换为字节数组
byte[] bytes = Encoding.ASCII.GetBytes(DllPath);
像这样在您使用 windows api 函数 WriteProcessMemory 分配的内存中写入该字节数组。
WriteProcessMemory(processHandle, allocatedMemory, bytes, (uint)bytes.Length, 0)
步骤 1 分配内存 ✓
STEP 2 写入DLL路径✓
步骤 3 使用 LoadLibraryW
如果您不知道导出的函数是什么,那么解释起来会有点棘手,请尝试给您一个抽象的理解。
创建应用程序时,您需要导入 windows 提供的 DLL 才能使用某些功能。例如,您想要在您的应用程序中发送一个 HTTP 请求。即使你不知道你需要加载 windows ws2.dll (windows socket) 库。 windows OS 提供了一个方便的函数,可以从字面上加载一个名为 LoadLibraryW
的库。我在哪里可以找到这个奇妙的功能?好吧,不用担心 child,kernel32.dll 可以满足您的需求。您需要做的就是找到指向 LoadLibraryW
函数的指针。再次强调,相信 MSDN,它会给你回报。
FARPROC WINAPI GetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
HMODULE WINAPI GetModuleHandle(
_In_opt_ LPCTSTR lpModuleName
);
您可以阅读文档了解更多信息。简单地说,这会在 kernel32.dll 中找到您的 LoadLibraryW
函数,因为它是一个导出函数。
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
步骤 1 分配内存 ✓
STEP 2 写入DLL路径✓
第 3 步使用 LoadLibraryW ✓
在您的进程中启动一个远程线程,它将简单地执行您的加载库代码
CreateRemoteThread(hndProc, (IntPtr)null, (IntPtr)null, lpLLAddress, lpAddress, 0, (IntPtr)null)
之后,只需关闭该进程的句柄,您的 dll 就会在该进程中“注入”。无论如何,如果您仍然没有弄清楚或者只是想要一个 class 来为您完成这里是一些源代码
DLLinjector
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace dllInjectExample
{
public enum DllInjectionResult
{
DllNotFound,
GameProcessNotFound,
InjectionFailed,
Success
}
public static class DllInjector
{
static readonly IntPtr INTPTR_ZERO = (IntPtr)0;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress,
IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
public static DllInjectionResult Inject(string sProcName, string sDllPath)
{
if (!File.Exists(sDllPath))
{
return DllInjectionResult.DllNotFound;
}
uint _procId = 0;
Process[] _procs = Process.GetProcesses();
for (int i = 0; i < _procs.Length; i++)
{
if (_procs[i].ProcessName == sProcName)
{
_procId = (uint)_procs[i].Id;
break;
}
}
if (_procId == 0)
{
return DllInjectionResult.GameProcessNotFound;
}
if (!bInject(_procId, sDllPath))
{
return DllInjectionResult.InjectionFailed;
}
return DllInjectionResult.Success;
}
private static bool bInject(uint pToBeInjected, string sDllPath)
{
IntPtr hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, pToBeInjected);
if (hndProc == INTPTR_ZERO)
{
return false;
}
IntPtr lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)sDllPath.Length, (0x1000 | 0x2000), 0X40);
if (lpAddress == INTPTR_ZERO)
{
return false;
}
byte[] bytes = Encoding.ASCII.GetBytes(sDllPath);
if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
return false;
}
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
if (lpLLAddress == INTPTR_ZERO)
{
return false;
}
if (CreateRemoteThread(hndProc, (IntPtr)null, INTPTR_ZERO, lpLLAddress, lpAddress, 0, (IntPtr)null) == INTPTR_ZERO)
{
return false;
}
CloseHandle(hndProc);
return true;
}
}
}
注入到 csgo 的示例,因为我不知道为什么要注入 dll?
if (Process.GetProcessesByName("csgo").Count() == 0)
{
Process Proc = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo(@"D:\Application\Steam\Steam.exe");
Proc.StartInfo = startInfo;
Proc.StartInfo.Arguments = "-applaunch 730";
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.CreateNoWindow = false;
Proc.Start();
Thread.Sleep(15000);
}
while (Process.GetProcessesByName("csgo").Count() == 0)
{
}
var something = DllInjector.Inject("csgo", @"C:\Visual Studio 2015\Projects\XGame\Debug\XGamedll.dll");
我的硬盘上有几个 DLL 文件。我服务器上的一个进程包含重要的文件数据,我想通过在进程内分配虚拟内存来记录这些数据。我没有那个过程的源代码,所以我需要采取更多的极端措施。我想让它启动 DLL 主函数。外部内存的分配需要用C#写,因为我想用在WPF中
如何用C#在另一个进程中执行自己的源代码?
为了在进程中执行您自己的源代码,您需要为进程虚拟分配内存,并将您的 DLL 路径写入您分配的内存地址。您将使用该 DLL 路径通过 kernel32.dll LoadLibraryW
中的导出函数将您的 dll 弹射到进程中。
windows 平台上的每个进程都有专用于该进程的指定内存大小。原因之一是出于安全考虑,一个进程不能向其他进程读取或写入数据。所以为了能够 write/inject 你的 DLL 你需要打开一个 HANDLE
。如果从 kernel32.dll 导入 OpenProcess
函数,则可以执行此操作。这简要意味着您正在使用 windows api。以下是如何在 C#
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(
uint dwDesiredAccess,
int bInheritHandle,
uint dwProcessId
);
You can find the full documentation of the windows api in the holy bible
现在,您想使用 OpenProcess 函数为您从中获得句柄的进程分配内存。使用VirtualAllocEx函数,参考MSDN
How hath thou allocated thou memory?
LPVOID WINAPI VirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
);
正如我们所见,它有 5 个参数。您之前收集的 HANDLE
object。我们不会使用的可选参数。如果将 DLL 转换为字节数组,则可以获得 DLL 的大小。内存分配的类型,我们想要保留和提交分配,所以使用 (0x1000 | 0x2000) 并最后保护我们将写入的已分配内存 0x40.
步骤 1 分配内存 ✓
STEP 2 写入DLL路径
步骤 3 使用 LoadLibraryW
第二步涉及到使用WriteProcessMemory简单的将dll路径写入内存。将字符串转换为字节数组
byte[] bytes = Encoding.ASCII.GetBytes(DllPath);
像这样在您使用 windows api 函数 WriteProcessMemory 分配的内存中写入该字节数组。
WriteProcessMemory(processHandle, allocatedMemory, bytes, (uint)bytes.Length, 0)
步骤 1 分配内存 ✓
STEP 2 写入DLL路径✓
步骤 3 使用 LoadLibraryW
如果您不知道导出的函数是什么,那么解释起来会有点棘手,请尝试给您一个抽象的理解。
创建应用程序时,您需要导入 windows 提供的 DLL 才能使用某些功能。例如,您想要在您的应用程序中发送一个 HTTP 请求。即使你不知道你需要加载 windows ws2.dll (windows socket) 库。 windows OS 提供了一个方便的函数,可以从字面上加载一个名为 LoadLibraryW
的库。我在哪里可以找到这个奇妙的功能?好吧,不用担心 child,kernel32.dll 可以满足您的需求。您需要做的就是找到指向 LoadLibraryW
函数的指针。再次强调,相信 MSDN,它会给你回报。
FARPROC WINAPI GetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
HMODULE WINAPI GetModuleHandle(
_In_opt_ LPCTSTR lpModuleName
);
您可以阅读文档了解更多信息。简单地说,这会在 kernel32.dll 中找到您的 LoadLibraryW
函数,因为它是一个导出函数。
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
步骤 1 分配内存 ✓
STEP 2 写入DLL路径✓
第 3 步使用 LoadLibraryW ✓
在您的进程中启动一个远程线程,它将简单地执行您的加载库代码
CreateRemoteThread(hndProc, (IntPtr)null, (IntPtr)null, lpLLAddress, lpAddress, 0, (IntPtr)null)
之后,只需关闭该进程的句柄,您的 dll 就会在该进程中“注入”。无论如何,如果您仍然没有弄清楚或者只是想要一个 class 来为您完成这里是一些源代码
DLLinjector
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace dllInjectExample
{
public enum DllInjectionResult
{
DllNotFound,
GameProcessNotFound,
InjectionFailed,
Success
}
public static class DllInjector
{
static readonly IntPtr INTPTR_ZERO = (IntPtr)0;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress,
IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
public static DllInjectionResult Inject(string sProcName, string sDllPath)
{
if (!File.Exists(sDllPath))
{
return DllInjectionResult.DllNotFound;
}
uint _procId = 0;
Process[] _procs = Process.GetProcesses();
for (int i = 0; i < _procs.Length; i++)
{
if (_procs[i].ProcessName == sProcName)
{
_procId = (uint)_procs[i].Id;
break;
}
}
if (_procId == 0)
{
return DllInjectionResult.GameProcessNotFound;
}
if (!bInject(_procId, sDllPath))
{
return DllInjectionResult.InjectionFailed;
}
return DllInjectionResult.Success;
}
private static bool bInject(uint pToBeInjected, string sDllPath)
{
IntPtr hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, pToBeInjected);
if (hndProc == INTPTR_ZERO)
{
return false;
}
IntPtr lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)sDllPath.Length, (0x1000 | 0x2000), 0X40);
if (lpAddress == INTPTR_ZERO)
{
return false;
}
byte[] bytes = Encoding.ASCII.GetBytes(sDllPath);
if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
return false;
}
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
if (lpLLAddress == INTPTR_ZERO)
{
return false;
}
if (CreateRemoteThread(hndProc, (IntPtr)null, INTPTR_ZERO, lpLLAddress, lpAddress, 0, (IntPtr)null) == INTPTR_ZERO)
{
return false;
}
CloseHandle(hndProc);
return true;
}
}
}
注入到 csgo 的示例,因为我不知道为什么要注入 dll?
if (Process.GetProcessesByName("csgo").Count() == 0)
{
Process Proc = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo(@"D:\Application\Steam\Steam.exe");
Proc.StartInfo = startInfo;
Proc.StartInfo.Arguments = "-applaunch 730";
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.CreateNoWindow = false;
Proc.Start();
Thread.Sleep(15000);
}
while (Process.GetProcessesByName("csgo").Count() == 0)
{
}
var something = DllInjector.Inject("csgo", @"C:\Visual Studio 2015\Projects\XGame\Debug\XGamedll.dll");