我的硬盘上有几个DLL文件。服务器上的进程包含重要的文件数据,我想通过在进程内部分配虚拟内存来记录这些数据。我没有该过程的源代码,因此我需要保留更多的外部措施。我希望它启动DLL主要功能。由于我想将其与WPF一起使用,因此需要使用C#编写外部的内存分配。
您如何使用C#在另一个进程中执行自己的源代码?
为了在进程内执行您自己的源代码,您需要为进程虚拟分配内存,并将DLL的路径写入分配的内存地址内。您将使用该DLL路径,使用kernel32.dll中 的导出函数在进程内部弹跳dll LoadLibraryW
。
Windows平台上的每个进程都有一个专用于该进程的指定内存大小。原因之一是出于安全性考虑,一个进程无法读取数据或将数据写入其他进程。因此,为了能够编写/注入您的DLL,您需要打开一个HANDLE
。如果OpenProcess
从kernel32.dll导入函数,则可以执行此操作。这简短的意思是您正在使用Windows API。这是在C#中导入kernel32 DLL的方法
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(
uint dwDesiredAccess,
int bInheritHandle,
uint dwProcessId
);
您可以在圣经中找到Windows API的完整文档
现在,您想通过使用OpenProcess函数将内存分配给您从中获得句柄的进程。使用VirtualAllocEx函数,让我们咨询MSDN
您如何分配记忆?
LPVOID WINAPI VirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
);
如我们所见,它需要5个参数。HANDLE
您先前收集的对象。我们不会使用的可选参数。如果将DLL转换为字节数组,则可以获得DLL的大小。内存分配的类型,我们既要保留又要提交分配,因此请使用(0x1000 | 0x2000)并最后对分配的内存进行保护,该保护将在写入0x40时进行。
步骤1分配内存✓
步骤2写入DLL路径
步骤3使用LoadLibraryW
第二步涉及使用WriteProcessMemory来简单地将dll路径写入内存中。将字符串转换为字节数组
byte[] bytes = Encoding.ASCII.GetBytes(DllPath);
像这样,将字节数组写在使用Windows api函数WriteProcessMemory分配的内存上。
WriteProcessMemory(processHandle, allocatedMemory, bytes, (uint)bytes.Length, 0)
步骤1分配内存✓
步骤2写入DLL路径✓
步骤3使用LoadLibraryW
如果您不了解哪些导出函数不正确,请尝试一点抽象的技巧,这将很难解释。
创建应用程序时,您需要导入Windows提供的DLL,以便使用某些功能。例如,您要在应用程序中发送HTTP请求。即使您不知道,也需要加载Windows ws2.dll(Windows套接字)库。Windows操作系统提供了一个方便的功能,可以从字面上加载一个名为的库LoadLibraryW
。在哪里可以找到这个出色的功能?好吧,不用担心孩子,kernel32.dll让您满意。您需要做的就是找到指向该LoadLibraryW
函数的指针。再次,对MSDN表现出信心,它会回报您。
FARPROC WINAPI GetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
HMODULE WINAPI GetModuleHandle(
_In_opt_ LPCTSTR lpModuleName
);
您可以阅读文档以获取更多信息。简单地说,这将LoadLibraryW
在kernel32.dll中找到您的函数,因为它是导出的函数。
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
步骤1分配内存✓
步骤2写入DLL路径✓
步骤3使用LoadLibraryW✓
在您的进程中启动一个远程线程,该线程将仅执行您的负载库代码
CreateRemoteThread(hndProc, (IntPtr)null, (IntPtr)null, lpLLAddress, lpAddress, 0, (IntPtr)null)
之后,只需关闭进程的句柄,您的dll应该被“注入”到进程内。无论如何,如果您还没有弄清楚它,或者只是想要一个可以为您完成此任务的类,那么这里是一些源代码
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");
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句