internal RpcInterfaceServiceTriggerInformation(SERVICE_TRIGGER trigger) : base(trigger) { if (CustomData.Count > 0 && CustomData[0].DataType == ServiceTriggerDataType.String) { InterfaceId = CustomData[0].Data.Split(':').Where(s => Guid.TryParse(s, out Guid _)).Select(s => Guid.Parse(s)).ToList().AsReadOnly(); } }
static void DumpCustomData(SERVICE_TRIGGER trigger) { SERVICE_TRIGGER_SPECIFIC_DATA_ITEM[] data_items; ReadArray(trigger.pDataItems, trigger.cDataItems, out data_items); for (int i = 0; i < data_items.Length; ++i) { var data_item = data_items[i]; Console.WriteLine("Data Item: {0} - Type: {1} - Size: {2}", i, data_item.dwDataType, data_item.cbData); if (data_item.pData != IntPtr.Zero && data_item.cbData > 0) { switch (data_item.dwDataType) { case ServiceTriggerDataType.Level: if (data_item.cbData == 1) { Console.WriteLine("Data: 0x{0:X02}", Marshal.ReadByte(data_item.pData)); } break; case ServiceTriggerDataType.KeywordAny: case ServiceTriggerDataType.KeywordAll: if (data_item.cbData == 8) { Console.WriteLine("Data: 0x{0:X016}", Marshal.ReadInt64(data_item.pData)); } break; case ServiceTriggerDataType.String: if ((data_item.cbData & 1) == 0) { string[] ss = Marshal.PtrToStringUni(data_item.pData, data_item.cbData / 2).TrimEnd('\0').Split('\0'); if (ss.Length == 1) { Console.WriteLine("Data: {0}", ss[0]); } else { for (int j = 0; j < ss.Length; ++j) { Console.WriteLine("Data[{0}]: {1}", j, ss[j]); } } } break; case ServiceTriggerDataType.Binary: default: { byte[] data = new byte[data_item.cbData]; Marshal.Copy(data_item.pData, data, 0, data.Length); Console.WriteLine("Data: [{0}]", String.Join(",", data.Select(b => String.Format("0x{0:X02}", b)))); } break; } } } }
internal NamedPipeServiceTriggerInformation(SERVICE_TRIGGER trigger) : base(trigger) { if (CustomData.Count > 0 && CustomData[0].DataType == ServiceTriggerDataType.String) { PipePath = $@"\??\pipe\{CustomData[0].Data}"; } }
internal EtwServiceTriggerInformation(SERVICE_TRIGGER trigger) : base(trigger) { var sd = EventTracing.QueryTraceSecurity(SubType, false); if (sd.IsSuccess) { SecurityDescriptor = sd.Result; } }
internal FirewallServiceTriggerInformation(SERVICE_TRIGGER trigger) : base(trigger) { if (CustomData.Count > 0) { var data = CustomData[0].DataArray; Port = data.Length > 0 ? data[0] : string.Empty; Protocol = data.Length > 1 ? data[1] : string.Empty; ExecutablePath = data.Length > 2 ? data[2] : string.Empty; User = data.Length > 3 ? data[3] : string.Empty; } }
internal WnfServiceTriggerInformation(SERVICE_TRIGGER trigger) : base(trigger) { var data = CustomData.FirstOrDefault(); if (data?.RawData?.Length != 8) { return; } Name = NtWnf.Open(BitConverter.ToUInt64(data.RawData, 0), true, false).GetResultOrDefault(); }
static void DumpTriggers(SafeServiceHandle service) { using (var buf = new SafeStructureInOutBuffer <SERVICE_TRIGGER_INFO>(8192, false)) { int required = 0; if (!QueryServiceConfig2(service, SERVICE_CONFIG_TRIGGER_INFO, buf, 8192, out required)) { return; } SERVICE_TRIGGER_INFO trigger_info = buf.Result; if (trigger_info.cTriggers == 0) { return; } SERVICE_TRIGGER[] trigger_arr; using (SafeHGlobalBuffer triggers = new SafeHGlobalBuffer(trigger_info.pTriggers, trigger_info.cTriggers * Marshal.SizeOf(typeof(SERVICE_TRIGGER)), false)) { trigger_arr = new SERVICE_TRIGGER[trigger_info.cTriggers]; triggers.ReadArray(0, trigger_arr, 0, trigger_arr.Length); } for (int i = 0; i < trigger_arr.Length; ++i) { SERVICE_TRIGGER trigger = trigger_arr[i]; Console.WriteLine("Trigger: {0} - Type: {1} - Action: {2}", i, trigger.dwTriggerType, trigger.dwAction); switch (trigger.dwTriggerType) { case ServiceTriggerType.Custom: Console.WriteLine("Subtype: [ETW UUID] {0:B}", trigger.GetSubType()); break; case ServiceTriggerType.DeviceInterfaceArrival: Console.WriteLine("Subtype: [Interface Class GUID] {0:B}", trigger.GetSubType()); break; case ServiceTriggerType.GroupPolicy: { Guid sub_type = trigger.GetSubType(); if (sub_type == MACHINE_POLICY_PRESENT_GUID) { Console.WriteLine("Subtype: [Machine Policy Present]"); } else if (sub_type == USER_POLICY_PRESENT_GUID) { Console.WriteLine("Subtype: [User Policy Present]"); } else { Console.WriteLine("Subtype: [Unknown Group Policy] {0:B}", sub_type); } } break; case ServiceTriggerType.NetworkEndpoint: { Guid sub_type = trigger.GetSubType(); if (sub_type == RPC_INTERFACE_EVENT_GUID) { Console.WriteLine("Subtype: [RPC Interface]"); } else if (sub_type == NAMED_PIPE_EVENT_GUID) { Console.WriteLine("Subtype: [Named Pipe]"); } else { Console.WriteLine("Subtype: [Unknown Network Endpoint] {0:B}", sub_type); } } break; case ServiceTriggerType.DomainJoin: { Guid sub_type = trigger.GetSubType(); if (sub_type == DOMAIN_JOIN_GUID) { Console.WriteLine("Subtype: [Domain Join]"); } else if (sub_type == DOMAIN_LEAVE_GUID) { Console.WriteLine("Subtype: [Domain Leave]"); } else { Console.WriteLine("Subtype: [Unknown Domain Join] {0:B}", sub_type); } } break; case ServiceTriggerType.IPAddressAvailability: { Guid sub_type = trigger.GetSubType(); if (sub_type == NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID) { Console.WriteLine("Subtype: [First IP Address Available]"); } else if (sub_type == NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID) { Console.WriteLine("Subtype: [Last IP Address Available]"); } else { Console.WriteLine("Subtype: [Unknown IP Address Availability] {0:B}", sub_type); } } break; } if (trigger.pDataItems != IntPtr.Zero && trigger.cDataItems > 0) { DumpCustomData(trigger); } } } }
/// <summary> /// Set the service to trigger-start when the first IP address on the TCP/IP /// networking stack becomes available, and trigger-stop when the last IP address on /// the TCP/IP networking stack becomes unavailable. /// </summary> /// <param name="serviceName"></param> private void SetServiceTriggerStartOnIPAddressArrival(string serviceName) { using (ServiceController sc = new ServiceController(serviceName)) { // Marshal Guid struct NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID and // NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID to native memory IntPtr pGuidIpAddressArrival = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid))); Marshal.StructureToPtr(NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID, pGuidIpAddressArrival, false); IntPtr pGuidIpAddressRemoval = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid))); Marshal.StructureToPtr(NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID, pGuidIpAddressRemoval, false); // Allocate and set the SERVICE_TRIGGER structure for // NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID to start the service SERVICE_TRIGGER serviceTrigger1 = new SERVICE_TRIGGER(); serviceTrigger1.dwTriggerType = ServiceTriggerType.SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY; serviceTrigger1.dwAction = ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_START; serviceTrigger1.pTriggerSubtype = pGuidIpAddressArrival; // Allocate and set the SERVICE_TRIGGER structure for // NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID to stop the service SERVICE_TRIGGER serviceTrigger2 = new SERVICE_TRIGGER(); serviceTrigger2.dwTriggerType = ServiceTriggerType.SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY; serviceTrigger2.dwAction = ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_STOP; serviceTrigger2.pTriggerSubtype = pGuidIpAddressRemoval; // Marshal the two SERVICE_TRIGGER structs to native memory as an array IntPtr pServiceTriggers = Marshal.AllocHGlobal(Marshal.SizeOf(typeof( SERVICE_TRIGGER)) * 2 /*2 elements*/); Marshal.StructureToPtr(serviceTrigger1, pServiceTriggers, false); Marshal.StructureToPtr(serviceTrigger2, new IntPtr((long)pServiceTriggers + Marshal.SizeOf(typeof(SERVICE_TRIGGER))), false); // Allocate and set the SERVICE_TRIGGER_INFO structure SERVICE_TRIGGER_INFO serviceTriggerInfo = new SERVICE_TRIGGER_INFO(); serviceTriggerInfo.cTriggers = 2; serviceTriggerInfo.pTriggers = pServiceTriggers; // Marshal the SERVICE_TRIGGER_INFO struct to native memory IntPtr pServiceTriggerInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof( SERVICE_TRIGGER_INFO))); Marshal.StructureToPtr(serviceTriggerInfo, pServiceTriggerInfo, false); // Call ChangeServiceConfig2 with the SERVICE_CONFIG_TRIGGER_INFO level // and pass to it the address of the SERVICE_TRIGGER_INFO structure. bool bSuccess = ServiceNative.ChangeServiceConfig2( sc.ServiceHandle.DangerousGetHandle(), ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, pServiceTriggerInfo); int errorCode = Marshal.GetLastWin32Error(); // Clean up the native resources Marshal.FreeHGlobal(pGuidIpAddressArrival); Marshal.FreeHGlobal(pGuidIpAddressRemoval); Marshal.FreeHGlobal(pServiceTriggers); Marshal.FreeHGlobal(pServiceTriggerInfo); // If the service failed to be set as trigger start, throw the error // returned by the ChangeServiceConfig2 function. if (!bSuccess) { Marshal.ThrowExceptionForHR(errorCode); } } }
internal EtwServiceTriggerInformation(SERVICE_TRIGGER trigger) : base(trigger) { _security_descriptor = new Lazy <SecurityDescriptor>(() => EventTracing.QueryTraceSecurity(SubType, false).GetResultOrDefault()); }