如何给WPF应用注入dll并执行初始化?
有一个工具软件A,它是用WPF Framework4.7.2编写的。它有一个接口能执行自定义方法。
但我不清楚怎么给这个应用进行注入C#类库。
我现在在使用Vanara.PInvoke库。还有网上说的DllExport库编写的代码。但是没法用DLL Export Viewer看到我定义的初始化函数。
在获取SayHello函数地址获取的值是0
下面是注入的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
namespace OmronWLXImport
{
public class Class1
{
[DllExport("SayHello")]
public static void SayHello()
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
MessageBox.Show("注入成功!");
}));
}
}
}
这个是触发注入的按钮
private void Btn_8_Click(object sender, RoutedEventArgs e)
{
List<Action> actions = new List<Action>();
try
{
// 1. 查找目标进程
Process[] targetProcess_Array = Process.GetProcessesByName("SysmacStudio");
Process targetProcess = null;
if (targetProcess_Array.Length == 0)
{
Trace.WriteLine("SysmacStudio 未启动");
return;
}
targetProcess = targetProcess_Array[0];
var PROCESS_ALL_ACCESS = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED | ACCESS_MASK.SYNCHRONIZE | ACCESS_MASK.SPECIFIC_RIGHTS_ALL;
var hProcess = Kernel32.OpenProcess(PROCESS_ALL_ACCESS, false, (uint)targetProcess.Id);
if (hProcess.IsInvalid)
{
Trace.WriteLine("句柄无效, 应用权限可能不足");
return;
}
actions.Add(() =>
{
hProcess.Dispose();
Trace.WriteLine("句柄释放成功!");
});
// 3. 获取LoadLibraryW函数地址(使用Vanara的Kernel32.GetProcAddress)
var k = Kernel32.GetModuleHandle("kernel32.dll");
IntPtr loadLibraryAddr = Kernel32.GetProcAddress(Kernel32.GetModuleHandle("kernel32.dll"), "LoadLibraryW");
if (loadLibraryAddr == IntPtr.Zero)
{
Trace.WriteLine("无法获取LoadLibraryW地址!");
return;
}
// 4. 在目标进程中分配内存(使用Vanara的Kernel32.VirtualAllocEx)
string dllPath = OmronWLXImportPath;
if (!File.Exists(dllPath))
{
Trace.WriteLine("dll文件不存在");
return;
}
byte[] dllPathBytes = Encoding.Unicode.GetBytes(dllPath+'\0');
IntPtr allocMemAddress = Kernel32.VirtualAllocEx(
hProcess,
IntPtr.Zero,
(uint)dllPathBytes.Length,
Kernel32.MEM_ALLOCATION_TYPE.MEM_COMMIT | Kernel32.MEM_ALLOCATION_TYPE.MEM_RESERVE,
Kernel32.MEM_PROTECTION.PAGE_READWRITE);
if (allocMemAddress == IntPtr.Zero)
{
Trace.WriteLine("内存分配失败!");
return;
}
actions.Add(()=>
{
VirtualFreeEx(hProcess, allocMemAddress, 0, MEM_ALLOCATION_TYPE.MEM_RELEASE);
Trace.WriteLine("路径内存释放成功!");
});
// 5. 写入 DLL路径 到目标进程(使用Vanara的Kernel32.WriteProcessMemory)
if (!Kernel32.WriteProcessMemory(
hProcess,
allocMemAddress,
dllPathBytes,
(uint)dllPathBytes.Length,
out _))
{
Trace.WriteLine("写入内存失败!");
return;
}
// 6. 创建远程线程执行LoadLibraryW(使用Vanara的Kernel32.CreateRemoteThread)
using var hThread = Kernel32.CreateRemoteThread(
hProcess,
lpThreadAttributes: null,
dwStackSize: 0,
lpStartAddress: loadLibraryAddr,
lpParameter: allocMemAddress,
dwCreationFlags: 0,
out _);
if (hThread.IsInvalid)
{
Trace.WriteLine("远程线程创建失败!");
return;
}
// 等待线程执行完成
Kernel32.WaitForSingleObject(hThread, 3000);
Trace.WriteLine("DLL注入成功!");
targetProcess_Array = Process.GetProcessesByName("SysmacStudio");
targetProcess = targetProcess_Array[0];
;
// 获取 SayHello 函数地址
// 首先需要确保 DLL 已经在目标进程中加载
IntPtr hModule = IntPtr.Zero;
foreach (ProcessModule module in targetProcess.Modules)
{
if (module.FileName == dllPath)
{
hModule = module.BaseAddress;
break;
}
}
if (hModule == IntPtr.Zero)
{
Trace.WriteLine("DLL 在目标进程中未加载!");
return;
}
//在这里获取不到接口
// 获取SayHello函数地址
IntPtr sayHelloAddr = Kernel32.GetProcAddress(hModule, "SayHello");
if (sayHelloAddr == IntPtr.Zero)
{
Trace.WriteLine("无法获取SayHello地址!");
return;
}
;
// 创建远程线程执行 SayHello 方法
using var hSayHelloThread = Kernel32.CreateRemoteThread(
hProcess,
lpThreadAttributes: null,
dwStackSize: 0,
lpStartAddress: sayHelloAddr,
lpParameter: IntPtr.Zero,
dwCreationFlags: 0,
out _);
if (hSayHelloThread.IsInvalid)
{
Trace.WriteLine("远程线程创建失败!");
return;
}
// 等待 SayHello 方法执行完成
Kernel32.WaitForSingleObject(hSayHelloThread, 3000);
Trace.WriteLine("DLL注入成功,SayHello方法执行完成!");
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
finally
{
actions.Reverse();
//资源释放
foreach (var action in actions)
{
action.Invoke();
}
}
}