[英]Importing kernel32 functions for allocating virtual memory in C#?
我的硬盤上有幾個DLL文件。 服務器上的進程包含重要的文件數據,我想通過在進程內部分配虛擬內存來記錄這些數據。 我沒有該過程的源代碼,因此我需要保留更多的措施。 我希望它啟動DLL主要功能。 由於我想將其與WPF一起使用,因此需要使用C#編寫外部的內存分配。
您如何使用C#在另一個進程中執行自己的源代碼?
為了在進程內執行自己的源代碼,您需要為進程虛擬分配內存 ,並在分配的內存地址內寫入DLL的路徑。 您將使用該DLL路徑,使用kernel32.dll LoadLibraryW
的導出函數在進程內部彈跳dll。
Windows平台上的每個進程都有一個專用於該進程的指定內存大小。 原因之一是出於安全性考慮,一個進程不能向其他進程讀取或寫入數據。 因此,為了能夠編寫/注入您的DLL,您需要打開一個HANDLE
。 如果從kernel32.dll導入OpenProcess
函數,則可以執行此OpenProcess
。 這簡短的意思是您正在使用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路徑
STEP 3使用LoadLibraryW
第二步涉及使用WriteProcessMemory簡單地將dll路徑寫入內存。 將字符串轉換為字節數組
byte[] bytes = Encoding.ASCII.GetBytes(DllPath);
像這樣,將字節數組寫在使用Windows api函數WriteProcessMemory分配的內存上。
WriteProcessMemory(processHandle, allocatedMemory, bytes, (uint)bytes.Length, 0)
步驟1分配內存✓
步驟2寫入DLL路徑✓
STEP 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
);
您可以閱讀文檔以獲取更多信息。 簡單地說,這將在kernel32.dll中找到您的LoadLibraryW
函數,因為它是導出的函數。
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
步驟1分配內存✓
步驟2寫入DLL路徑✓
STEP 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");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.