The following code introduces the Injector method in Paint.net and gets the MainForm fields.
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 (native)
#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; }
Conclusion:
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}