using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace injectprocedure
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// LPVOID VirtualAllocEx(
// [in] HANDLE hProcess,
// [in, optional] LPVOID lpAddress,
// [in] SIZE_T dwSize,
// [in] DWORD flAllocationType,
// [in] DWORD flProtect
//);
///
/// 开辟内存
///
/// 开辟内存的进程指针
/// 开辟内存的起始地址如果 lpAddress 为 NULL,则该函数确定分配区域的位置。
/// 开辟内存的大小
/// 内存分配的类型
/// 要分配的页区域的内存操作权限
/// 开辟内存的指针
[DllImport("Kernel32.dll")]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, FlAllocationType flAllocationType, FlProtect flProtect);
// BOOL WriteProcessMemory(
// [in] HANDLE hProcess,
// [in] LPVOID lpBaseAddress,
// [in] LPCVOID lpBuffer,
// [in] SIZE_T nSize,
// [out] SIZE_T* lpNumberOfBytesWritten
//);
//https://learn.microsoft.com/zh-cn/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
///
/// 写入内存
///
/// 写人内存的进程指针
/// 写入内存的指针
/// 写入内存的数据
/// 写入内存的大小
/// 指向变量的指针,该变量接收传输到指定进程的字节数。 此参数是可选的。 如果 lpNumberOfBytesWritten 为 NULL,则忽略参数。
/// 是否写入成功
[DllImport("Kernel32.dll")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, string lpBuffer, int nSize, IntPtr lpNumberOfBytesWritten);
// HMODULE GetModuleHandleA(
// [in, optional] LPCSTR lpModuleName
//);
//https://learn.microsoft.com/zh-cn/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea
///
/// 获取模块(dll)
///
/// 模块名称
/// 该模块的指针
[DllImport("Kernel32.dll")]
public static extern IntPtr GetModuleHandleA(string lpModuleName);
// FARPROC GetProcAddress(
// [in] HMODULE hModule,
// [in] LPCSTR lpProcName
//);
//https://learn.microsoft.com/zh-cn/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
///
/// 获取模块内的函数指针
///
/// 模块指针
/// 函数名称
/// 该函数的指针
[DllImport("Kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
// HANDLE CreateRemoteThread(
// [in] HANDLE hProcess,
// [in] LPSECURITY_ATTRIBUTES lpThreadAttributes,
// [in] SIZE_T dwStackSize,
// [in] LPTHREAD_START_ROUTINE lpStartAddress,
// [in] LPVOID lpParameter,
// [in] DWORD dwCreationFlags,
// [out] LPDWORD lpThreadId
//);
//https://learn.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread
///
/// 创建远程线程
///
/// 创建线程的进程指针
/// 如果 lpThreadAttributes 为 NULL,则线程将获取默认安全描述符,并且无法继承句柄。 访问控制在来自创建者主令牌的线程的默认安全描述符中列出 (ACL)
/// 堆栈的初始大小(以字节为单位)。
/// 线程执行的应用程序定义函数的指针,表示远程进程中线程的起始地址。 函数必须存在于远程进程中。(创建的函数指针)
/// 指向要传递给线程函数的变量的指针。(函数变量指针)
/// 控制线程创建的标志。0:线程在创建后立即运行
/// 指向接收线程标识符的变量的指针。如果此参数为 NULL,则不返回线程标识符。
/// 如果函数成功,则返回值是新线程的句柄。
[DllImport("Kernel32.dll")]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, int dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, int dwCreationFlags, IntPtr lpThreadId);
private void button1_Click(object sender, EventArgs e)
{
//1.遍历进程找到微信进程(CreateToolhelp32Snapshot、Processes32Next)
Process[] processes = Process.GetProcesses();
string processName = string.Empty;
int ProcessPId = 0;
//2。打开微信进程,获得微信句柄(OpenProcess)
IntPtr processintPtr = IntPtr.Zero;
foreach (Process process in processes)
{
if (process.ProcessName == "WeChat") {
processName= process.ProcessName;
ProcessPId = process.Id;
processintPtr = process.Handle;
break;
}
}
if (processintPtr == IntPtr.Zero) {
MessageBox.Show("未找到微信");
return;
}
//3.打开微信进程,为dll文件路径字符串事情内存空间(VirtualAllocEx)
string dllFilePath = @"";
int dllFilePathLenth = dllFilePath.Length+1;
IntPtr dllFilePathintPtr= VirtualAllocEx(processintPtr, IntPtr.Zero, dllFilePathLenth, FlAllocationType.MEM_COMMIT, FlProtect.PAGE_READWRITE);
if (dllFilePathintPtr == IntPtr.Zero) {
MessageBox.Show("字符串内存分配失败!");
return;
}
//4.把dll文件路径字符串写入到申请内存中(WriteProcessMemory)
bool isWriteOk=WriteProcessMemory(processintPtr, dllFilePathintPtr, dllFilePath, dllFilePathLenth, IntPtr.Zero);
if (!isWriteOk) {
MessageBox.Show("写入进程的内存失败!");
return;
}
//5.从kernel32.dll中获取loadLibraryA的函数地址(GetModuleHandle、GetProcAddress)
IntPtr moduleIntPtr = GetModuleHandleA("Kernel32.dll");
IntPtr loadLibraryAintPtr = GetProcAddress(moduleIntPtr, "loadLibraryA");
if (loadLibraryAintPtr == IntPtr.Zero) {
MessageBox.Show("寻找loadLibraryA失败");
return;
}
//6.在微信中启动内存中指定了文件名路径的dll(CreateRemoteThredad)
IntPtr remoteThreadIntPtr = CreateRemoteThread(processintPtr, IntPtr.Zero, 0, loadLibraryAintPtr, dllFilePathintPtr, 0, IntPtr.Zero);
if (IntPtr.Zero == remoteThreadIntPtr) {
MessageBox.Show("注入失败");
return;
}
MessageBox.Show("注入成功");
}
}
//https://learn.microsoft.com/zh-cn/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
public enum FlAllocationType {
///
/// 从指定保留内存页的磁盘) 的总内存大小和分页文件 (分配内存费用
///
MEM_COMMIT = 0x00001000,
MEM_RESERVE = 0x00002000,
MEM_RESET = 0x00080000,
MEM_RESET_UNDO = 0x1000000,
MEM_LARGE_PAGES= 0x20000000,
MEM_PHYSICAL= 0x00400000,
MEM_TOP_DOWN= 0x00100000,
}
//https://learn.microsoft.com/zh-cn/windows/win32/Memory/memory-protection-constants
public enum FlProtect {
PAGE_EXECUTE= 0x10,
PAGE_EXECUTE_READ = 0x20,
PAGE_EXECUTE_READWRITE = 0x40,
PAGE_EXECUTE_WRITECOPY = 0x80,
PAGE_NOACCESS=0x01,
///
/// 启用对已提交页面区域的只读或读/写访问。 如果启用了 数据执行保护 ,则尝试在提交的区域中执行代码会导致访问冲突。
///
PAGE_READWRITE = 0x04,
}
}