接下来代码在 Paint.net 中注入 Injector 方法并获取 MainForm 字段。
NInject.exe
public static int Injector(string parameter)
{
try
{
var mainForm = Application.OpenForms.OfType<Form>().FirstOrDefault(form => form.GetType().FullName.EndsWith("MainForm"));
var builder = new StringBuilder();
builder.AppendFormat("process: {0}\r\n\r\n", Application.ExecutablePath);
builder.AppendFormat("type: {0}\r\n", mainForm.GetType().FullName);
foreach (var field in mainForm.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
builder.AppendFormat("field {0}: {1}\r\n", field.Name, field.GetValue(mainForm));
}
new Form()
{
Controls =
{
new TextBox
{
Text = builder.ToString(),
Multiline = true,
Dock = DockStyle.Fill
}
}
}
.ShowDialog();
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString());
}
return 0;
}
static void Main(string[] args)
{
var process = System.Diagnostics.Process.GetProcessesByName("PaintDotNet").FirstOrDefault();
var processHandle = OpenProcess(ProcessAccessFlags.All, false, process.Id);
var proxyPath = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "NInjector.dll");
var pathBytes = System.Text.Encoding.ASCII.GetBytes(proxyPath);
var remoteBuffer = VirtualAllocEx(processHandle, IntPtr.Zero, (uint)pathBytes.Length, AllocationType.Commit, MemoryProtection.ReadWrite);
WriteProcessMemory(process.Handle, remoteBuffer, pathBytes, (uint)pathBytes.Length, IntPtr.Zero);
var remoteThread = CreateRemoteThread(processHandle, IntPtr.Zero, 0, GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA") , remoteBuffer, 0, IntPtr.Zero);
WaitForSingleObject(remoteThread, unchecked((uint)-1));
CloseHandle(remoteThread);
}
NInjector.dll(本机)
#include "MSCorEE.h"
#pragma comment (lib, "MSCorEE")
void StartTheDotNetRuntime()
{
MessageBox(0, L"Started", L"proxy", 0);
ICLRRuntimeHost *pClrHost = NULL;
HRESULT hr = CorBindToRuntimeEx(
NULL, L"wks", 0, CLSID_CLRRuntimeHost,
IID_ICLRRuntimeHost, (PVOID*)&pClrHost);
hr = pClrHost->Start();
DWORD dwRet = 0;
hr = pClrHost->ExecuteInDefaultAppDomain(
L"bla-bla\\NInject.exe",
L"NInject.NInject_Program", L"Injector", L"MyParameter", &dwRet);
hr = pClrHost->Stop();
pClrHost->Release();
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
StartTheDotNetRuntime();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
输出:
process: C:\Program Files\Paint.NET\PaintDotNet.exe
type: PaintDotNet.Dialogs.MainForm
field appWorkspace: PaintDotNet.Controls.AppWorkspace
field defaultButton: System.Windows.Forms.Button, Text:
field floaters: PaintDotNet.Dialogs.FloatingToolForm[]
field floaterOpacityTimer: [System.Windows.Forms.Timer], Interval: 25
field deferredInitializationTimer:
field components: System.ComponentModel.Container
field killAfterInit: False
field singleInstanceManager: PaintDotNet.SystemLayer.SingleInstanceManager
field queuedInstanceMessages: System.Collections.Generic.List`1[System.String]
field processingOpen: False
field scrollPosition: {X=0,Y=0}