Exemplo n.º 1
0
        // Helpers
        public static RUNTIME_CHECK CheckAllTheThings(String Launch)
        {
            RUNTIME_CHECK rt = new RUNTIME_CHECK();

            if (IntPtr.Size == 4)
            {
                rt.SwampIs32 = true;
            }
            else
            {
                rt.SwampIs32 = false;
            }

            if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("ProgramFiles(x86)")))
            {
                rt.OSIs32 = false;
            }
            else
            {
                rt.OSIs32 = true;
            }

            bool bExists = File.Exists(Launch);

            rt.PePathIsValid = bExists;

            Int16 Arch = GetPeArch(Launch);

            rt.PeArch = Arch;

            return(rt);
        }
Exemplo n.º 2
0
        // Main logic
        public static void SpawnTheThing(String Launch, String RealCmdLine, String FakeCmdLine = "")
        {
            // Invoke all the checks
            RUNTIME_CHECK RunTime = CheckAllTheThings(Launch);

            if (RunTime.PePathIsValid == false)
            {
                Console.WriteLine("[!] Invalid PE path specified..");
                return;
            }
            if (RunTime.PeArch == 0)
            {
                Console.WriteLine("[!] Invalid PE image..");
                return;
            }
            if (RunTime.SwampIs32 && RunTime.PeArch == 0x020b || !RunTime.SwampIs32 && RunTime.PeArch == 0x010b)
            {
                Console.WriteLine("[!] SwampThing and target PE architectures do not match..");
                return;
            }

            // Create the target process
            SecurityAttributes SecAttrib  = new SecurityAttributes();
            String             CurrentDir = Directory.GetCurrentDirectory();
            StartupInfo        si         = new StartupInfo();
            ProcessInformation pi;
            bool bProc = CreateProcess(Launch, FakeCmdLine, SecAttrib, SecAttrib, false, CreateProcessFlags.CREATE_SUSPENDED, IntPtr.Zero, CurrentDir, si, out pi);

            if (!bProc)
            {
                Console.WriteLine("[!] Process execution failed..");
                return;
            }
            else
            {
                Console.WriteLine("[>] CreateProcess -> Suspended");
            }

            // Get PBI
            PROCESS_BASIC_INFORMATION CallResult = PBI(pi.hProcess);

            if (CallResult.PebBaseAddress == IntPtr.Zero)
            {
                Console.WriteLine("[!] Failed to aquire PBI");
                return;
            }
            else
            {
                if (RunTime.PeArch == 0x010b)
                {
                    Console.WriteLine("[+] PE Arch                       : 32-bit");
                }
                else
                {
                    Console.WriteLine("[+] PE Arch                       : 64-bit");
                }
                Console.WriteLine("[+] Process Id                    : " + CallResult.UniqueProcessId);
                Console.WriteLine("[+] PEB Base                      : 0x" + string.Format("{0:X}", (CallResult.PebBaseAddress).ToInt64()));
            }

            // Get PEB->(IntPtr)_RTL_USER_PROCESS_PARAMETERS->(UNICODE_STRING)CommandLine
            Int32 RTL_USER_PROCESS_PARAMETERS;
            Int32 CommandLine;
            Int32 ReadSize;

            if (RunTime.PeArch == 0x010b)
            {
                RTL_USER_PROCESS_PARAMETERS = 0x10;
                CommandLine = 0x40;
                ReadSize    = 0x4;
            }
            else
            {
                RTL_USER_PROCESS_PARAMETERS = 0x20;
                CommandLine = 0x70;
                ReadSize    = 0x8;
            }

            // We can't acquire a remote PEB lock so we sleep briefly
            System.Threading.Thread.Sleep(500); // 500ms

            // Read remote PEB offsets
            UInt64 ProcParams;
            IntPtr pProcParams = ReadRemoteMem(pi.hProcess, ((CallResult.PebBaseAddress).ToInt64() + RTL_USER_PROCESS_PARAMETERS), ReadSize);

            if (ReadSize == 0x4)
            {
                ProcParams = (UInt64)Marshal.ReadInt32(pProcParams);
            }
            else
            {
                ProcParams = (UInt64)Marshal.ReadInt64(pProcParams);
            }
            Console.WriteLine("[+] RTL_USER_PROCESS_PARAMETERS   : 0x" + string.Format("{0:X}", ProcParams));
            UInt64 CmdLineUnicodeStruct = ProcParams + (UInt64)CommandLine;

            Console.WriteLine("[+] CommandLine                   : 0x" + string.Format("{0:X}", CmdLineUnicodeStruct));

            // Get current CommandLine -> UNICODE_STRING
            UNICODE_STRING CurrentCmdLineStruct = new UNICODE_STRING();
            Int32          UniStructSize        = Marshal.SizeOf(CurrentCmdLineStruct);
            IntPtr         pCmdLineStruct       = ReadRemoteMem(pi.hProcess, (Int64)CmdLineUnicodeStruct, UniStructSize);

            CurrentCmdLineStruct = (UNICODE_STRING)Marshal.PtrToStructure(pCmdLineStruct, typeof(UNICODE_STRING));
            Console.WriteLine("[+] UNICODE_STRING |-> Len        : " + CurrentCmdLineStruct.Length);
            Console.WriteLine("                   |-> MaxLen     : " + CurrentCmdLineStruct.MaximumLength);
            Console.WriteLine("                   |-> pBuff      : 0x" + string.Format("{0:X}", (UInt64)CurrentCmdLineStruct.Buffer));

            // Create replacement CommandLine
            Console.WriteLine("\n[>] Rewrite -> RTL_USER_PROCESS_PARAMETERS");

            // RTL_USER_PROCESS_PARAMETERS unicode string params
            String WinDir       = Environment.GetEnvironmentVariable("windir");
            IntPtr uSystemDir   = EmitUnicodeString((WinDir + "\\System32"));
            IntPtr uLaunchPath  = EmitUnicodeString(Launch);
            IntPtr uWindowName  = EmitUnicodeString("SwampThing");
            IntPtr uRealCmdLine = EmitUnicodeString(" " + RealCmdLine);

            // Create local RTL_USER_PROCESS_PARAMETERS
            IntPtr pProcessParams   = IntPtr.Zero;
            uint   RtlCreateSuccess = RtlCreateProcessParametersEx(ref pProcessParams, uLaunchPath, uSystemDir, uSystemDir, uRealCmdLine, IntPtr.Zero, uWindowName, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1);

            if (RtlCreateSuccess != 0)
            {
                Console.WriteLine("[!] Failed to create process parameters");
                return;
            }
            else
            {
                Console.WriteLine("[+] RtlCreateProcessParametersEx  : 0x" + string.Format("{0:X}", (UInt64)pProcessParams));
            }

            // Remote map RTL_USER_PROCESS_PARAMETERS
            Int32   iProcessParamsSize   = Marshal.ReadInt32((IntPtr)((Int64)pProcessParams + 4));
            IntPtr  pRemoteProcessParams = AllocRemoteMem(pi.hProcess, iProcessParamsSize, pProcessParams);
            Boolean bRemoteWriteSuccess  = WriteRemoteMem(pi.hProcess, pProcessParams, pProcessParams, iProcessParamsSize, AllocationProtect.PAGE_READWRITE);

            if (bRemoteWriteSuccess)
            {
                Console.WriteLine("[+] RemoteAlloc                   : 0x" + string.Format("{0:X}", (UInt64)pRemoteProcessParams));
                Console.WriteLine("[+] Size                          : " + iProcessParamsSize);
            }
            else
            {
                Console.WriteLine("[!] Failed to allocate custom RTL_USER_PROCESS_PARAMETERS");
                return;
            }

            // Rewrite the process parameters pointer
            IntPtr pRewriteProcessParams = Marshal.AllocHGlobal(ReadSize);

            if (ReadSize == 0x4)
            {
                Marshal.WriteInt32(pRewriteProcessParams, (Int32)pProcessParams);
            }
            else
            {
                Marshal.WriteInt64(pRewriteProcessParams, (Int64)pProcessParams);
            }
            bRemoteWriteSuccess = WriteRemoteMem(pi.hProcess, pRewriteProcessParams, (IntPtr)((CallResult.PebBaseAddress).ToInt64() + RTL_USER_PROCESS_PARAMETERS), ReadSize, AllocationProtect.PAGE_READWRITE);
            if (bRemoteWriteSuccess)
            {
                Console.WriteLine("[?] Success, sleeping 500ms..");
            }
            else
            {
                Console.WriteLine("[!] Failed to rewrite PEB->pProcessParameters");
                return;
            }

            // Resume process
            UInt32 ResumeProc = ResumeThread(pi.hThread);

            System.Threading.Thread.Sleep(500);

            // Finally we rewrite the commandline to the fake value
            Console.WriteLine("\n[>] Reverting RTL_USER_PROCESS_PARAMETERS");
            IntPtr uFakeCmdLine = EmitUnicodeString(" " + FakeCmdLine);

            Console.WriteLine("[+] Local UNICODE_STRING          : 0x" + string.Format("{0:X}", (UInt64)uFakeCmdLine));

            // Copy unicode buffer to remote process
            IntPtr pRemoteCmdLine = AllocRemoteMem(pi.hProcess, (Marshal.ReadInt16((IntPtr)((UInt64)uFakeCmdLine + 2)))); // MaxLength

            if (ReadSize == 0x4)
            {
                bRemoteWriteSuccess = WriteRemoteMem(pi.hProcess, (IntPtr)(Marshal.ReadInt32((IntPtr)((UInt64)uFakeCmdLine + 4))), pRemoteCmdLine, (Marshal.ReadInt16(uFakeCmdLine)), AllocationProtect.PAGE_READWRITE);
            }
            else
            {
                bRemoteWriteSuccess = WriteRemoteMem(pi.hProcess, (IntPtr)(Marshal.ReadInt64((IntPtr)((UInt64)uFakeCmdLine + 8))), pRemoteCmdLine, (Marshal.ReadInt16(uFakeCmdLine)), AllocationProtect.PAGE_READWRITE);
            }
            Console.WriteLine("[+] Remote UNICODE_STRING.Buffer  : 0x" + string.Format("{0:X}", (UInt64)pRemoteCmdLine));

            // Recalculate new RTL_USER_PROCESS_PARAMETERS
            pProcParams = ReadRemoteMem(pi.hProcess, ((CallResult.PebBaseAddress).ToInt64() + RTL_USER_PROCESS_PARAMETERS), ReadSize);
            if (ReadSize == 0x4)
            {
                ProcParams = (UInt64)Marshal.ReadInt32(pProcParams);
            }
            else
            {
                ProcParams = (UInt64)Marshal.ReadInt64(pProcParams);
            }
            Console.WriteLine("[+] pRTL_USER_PROCESS_PARAMETERS  : 0x" + string.Format("{0:X}", ProcParams));

            // Rewrite RTL_USER_PROCESS_PARAMETERS->CommandLine => Length, MaxLength, Buffer
            bRemoteWriteSuccess = WriteRemoteMem(pi.hProcess, uFakeCmdLine, (IntPtr)(ProcParams + (UInt32)CommandLine), 2, AllocationProtect.PAGE_READWRITE);
            bRemoteWriteSuccess = WriteRemoteMem(pi.hProcess, (IntPtr)((UInt64)uFakeCmdLine + 2), (IntPtr)(ProcParams + (UInt32)CommandLine + 2), 2, AllocationProtect.PAGE_READWRITE);
            IntPtr pRemoteBuff = Marshal.AllocHGlobal(8);

            if (ReadSize == 0x4)
            {
                Marshal.WriteInt32(pRemoteBuff, (Int32)pRemoteCmdLine);
                bRemoteWriteSuccess = WriteRemoteMem(pi.hProcess, pRemoteBuff, (IntPtr)(ProcParams + (UInt32)CommandLine + 4), 4, AllocationProtect.PAGE_READWRITE);
            }
            else
            {
                Marshal.WriteInt64(pRemoteBuff, (Int64)pRemoteCmdLine);
                bRemoteWriteSuccess = WriteRemoteMem(pi.hProcess, pRemoteBuff, (IntPtr)(ProcParams + (UInt32)CommandLine + 8), 8, AllocationProtect.PAGE_READWRITE);
            }
            Console.WriteLine("[?] Success rewrote Len, MaxLen, Buffer..");
        }