我做了一个dll,可以自定义windows 10记事本,它有一个ui,但需要注入。我用 C++ 制作了一个控制台注入器,它可以完美地工作,但我想要一个用于注入器的用户界面。我尝试使用 CLR,但没有成功。所以我在 c# winforms 中做了这个 calsses:
`
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows.Forms;
namespace TestUI { public class DllInjector { public bool InjectDll(string processName, int processId, string dllPath) { // Get a handle to the target process IntPtr processHandle = OpenProcess(ProcessAccessFlags.All, false, processId); if (processHandle == IntPtr.Zero) { MessageBox.Show("Failed to get handle to the target process"); return false; }
// Allocate memory in the target process for the DLL path
IntPtr dllPathAddress = VirtualAllocEx(processHandle, IntPtr.Zero, (uint)dllPath.Length + 1,
AllocationType.Commit, MemoryProtection.ReadWrite);
if (dllPathAddress == IntPtr.Zero)
{
MessageBox.Show("Failed to allocate memory in the target process");
return false;
}
// Write the DLL path to the target process
byte[] dllPathBytes = System.Text.Encoding.ASCII.GetBytes(dllPath);
if (!WriteProcessMemory(processHandle, dllPathAddress, dllPathBytes,
(uint)dllPathBytes.Length, out _))
{
MessageBox.Show("Failed to write DLL path to target process");
return false;
}
// Get the address of LoadLibraryA in kernel32.dll
IntPtr loadLibraryAddress = GetLoadLibraryAddress();
if (loadLibraryAddress == IntPtr.Zero)
{
MessageBox.Show("Failed to get address of LoadLibraryA");
return false;
}
// Call LoadLibraryA in the target process to load the DLL
IntPtr remoteThread = CreateRemoteThread(processHandle, IntPtr.Zero, 0, loadLibraryAddress,
dllPathAddress, 0, IntPtr.Zero);
if (remoteThread == IntPtr.Zero)
{
MessageBox.Show("Failed to create remote thread in the target process");
return false;
}
// Wait for the remote thread to finish
WaitForSingleObject(remoteThread, 0xFFFFFFFF);
// Free the memory allocated in the target process for the DLL path
VirtualFreeEx(processHandle, dllPathAddress, 0, 0x8000);
// Close the handle to the target process
CloseHandle(processHandle);
return true;
}
private static IntPtr GetLoadLibraryAddress()
{
// Load kernel32.dll into the current process
IntPtr kernel32 = LoadLibraryA("kernel32.dll");
if (kernel32 == IntPtr.Zero)
{
return IntPtr.Zero;
}
// Get the address of LoadLibraryA from kernel32.dll
IntPtr loadLibraryAddress = GetProcAddress(kernel32, "LoadLibraryA");
if (loadLibraryAddress == IntPtr.Zero)
{
return IntPtr.Zero;
}
// Free the library handle
FreeLibrary(kernel32);
return loadLibraryAddress;
}
// Declare the necessary WinAPI functions for injecting the DLL
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize,
AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer,
uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize,
IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint dwFreeType);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryA(string lpLibFileName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FreeLibrary(IntPtr hModule);
}
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Reset = 0x80000,
TopDown = 0x100000,
WriteWatch = 0x200000,
Physical = 0x400000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection
{
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
Guard = 0x100,
NoCache = 0x200,
WriteCombine = 0x400
}
}`
这是注入代码,获取进程id:
`
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace TestUI { public static class ProcessHelpers { public static int GetProcessIdByName(string processName) { var processes = Process.GetProcessesByName(processName);
if (processes.Length == 0)
{
throw new ArgumentException($"Could not find process with name '{processName}'");
}
// Return the ID of the first matching process
return processes[0].Id;
}
}
} `
这就是我按下按钮后的称呼:
`
private void button1_Click(object sender, EventArgs e)
{
string processName = "notepad"; string dllPath; int processId = ProcessHelpers.GetProcessIdByName("notepad");
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "DLL files (*.dll)|*.dll";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
dllPath = openFileDialog.FileName;
DllInjector injector = new DllInjector();
if (injector.InjectDll(processName, processId, dllPath))
{
MessageBox.Show("Injection successful");
}
else
{
MessageBox.Show("Injection failed");
}
}
else
{
}
}
}`
返回是真的,我得到的消息框说它是成功的,但是没有显示菜单。谁能帮帮我?
我希望菜单会出现。我也有一个热键
INS
,这可以打开和关闭菜单。我使用了亲爱的 ImGui。
我在这里插入的代码被网站弄乱了,但它是可读的