# T1489 - Service Stop

## SOC Recommendation
Investigate Service Stop activity in the context of Impact: confirm scope, affected host/identity, and whether it matches expected administrative behaviour before deciding this is benign.

## D3FEND Mappings
| D3FEND Technique | Relationship | Practical SOC Action |
|---|---|---|
| Network Traffic Analysis | Detect | Monitor for Network Traffic Analysis indicators relevant to this technique. |

## Investigation Steps
1. Review Defender for Endpoint / Defender XDR alerts and timeline for the affected host or identity.
2. Check Sentinel analytics rules and incidents correlated with this technique.
3. Review Entra ID sign-in and audit logs if the technique involves an identity or cloud resource.

## Evidence to Collect
- Host or resource affected
- Account or identity involved
- Timestamp of the activity
- Related process, file, or network artifact
- Any preceding or follow-on alerts

## Response Actions
| Action | Risk | Automation Safe | Approval Required |
|---|---|---|---|
| Contain the affected host or account | Medium | No | Yes |
| Collect and preserve evidence | Low | Yes | No |

## KQL
```kql
let timeframe = 1h;
let threshold = 15; // update threshold value based on organization's preference
let NotableEvents = CrowdStrikeFalconEventStream
| where TimeGenerated > ago(timeframe)
| where EventType == "DetectionSummaryEvent"
| where Severity in ("Critical", "High")
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), Total = count() by DstUserName, DstHostName, SrcIpAddr, FileName, FileHash, Message
| where Total > threshold;
NotableEvents
| extend timestamp = StartTimeUtc, AccountCustomEntity = DstUserName, HostCustomEntity = DstHostName, IPCustomEntity = SrcIpAddr, FileHashCustomEntity = FileHash, FileHashAlgo = "MD5"
| project timestamp, StartTimeUtc, EndTimeUtc, DstUserName, DstHostName, SrcIpAddr, FileName, FileHash, FileHashAlgo, Message, Total, AccountCustomEntity, HostCustomEntity, IPCustomEntity, FileHashCustomEntity
```
```kql
// UniFi ISP Downtime Detection
let MinDowntimeSeconds = 60;
Unifi_SiteManager_ISPMetrics_CL
| where TimeGenerated > ago(30m)
| mv-expand period = Periods
| extend
    metricTime = todatetime(period.metricTime),
    downtime = toint(period.data.wan.downtime),
    uptime = todouble(period.data.wan.uptime),
    ispName = tostring(period.data.wan.ispName),
    ispAsn = tostring(period.data.wan.ispAsn)
// De-duplicate Periods: each poll returns the same hour buckets, so collapse to latest value per metricTime
| summarize arg_max(TimeGenerated, downtime, uptime, ispAsn) by tostring(SiteId), ispName, metricTime
| where metricTime > ago(30m)
| where downtime > 0
| summarize
    TotalDowntimeSeconds = sum(downtime),
    EventCount = count(),
    AvgUptime = round(avg(uptime), 2),
    FirstSeen = min(metricTime),
    LastSeen = max(metricTime)
    by SiteId, ispName, ispAsn
| where TotalDowntimeSeconds >= MinDowntimeSeconds
| extend
    TimeGenerated = now(),
    DowntimeMinutes = round(TotalDowntimeSeconds / 60.0, 2)
| project
    TimeGenerated,
    SiteId = SiteId,
    ISPName = ispName,
    ISPAsn = ispAsn,
    TotalDowntimeSeconds,
    DowntimeMinutes,
    AvgUptimePct = AvgUptime,
    EventCount,
    FirstSeen,
    LastSeen
```
```kql
let prev_offline_ids = Unifi_SiteManager_Devices_CL
    | where TimeGenerated between (ago(45m) .. ago(15m))
    | summarize arg_max(TimeGenerated, *) by Id
    | where Status == "offline"
    | distinct Id;
Unifi_SiteManager_Devices_CL
| where TimeGenerated > ago(15m)
| summarize arg_max(TimeGenerated, *) by Id
| where Status == "offline"
| extend IsNew = Id !in (prev_offline_ids)
| summarize
    OfflineDeviceCount = count(),
    NewlyOfflineCount = countif(IsNew),
    OfflineDevices = make_list(coalesce(Name, Id)),
    NewlyOfflineDevices = make_list_if(coalesce(Name, Id), IsNew),
    ProductLines = make_set(ProductLine)
| where OfflineDeviceCount >= 3
| where NewlyOfflineCount > 0
| extend
    TimeGenerated = now(),
    OfflineDeviceList = strcat_array(OfflineDevices, ", "),
    NewlyOfflineList = strcat_array(NewlyOfflineDevices, ", "),
    AffectedProductLines = strcat_array(ProductLines, ", ")
| extend Activity = strcat(NewlyOfflineCount, ' device(s) newly offline (', OfflineDeviceCount, ' total offline): ', NewlyOfflineList)
| project
    TimeGenerated,
    OfflineDeviceCount,
    NewlyOfflineCount,
    OfflineDeviceList,
    NewlyOfflineList,
    AffectedProductLines,
    Activity
```

## Escalation Criteria
- Service Stop activity observed on a privileged account or critical system.
- Activity follows or precedes other suspicious behaviour in the same investigation.
- Automated triage cannot confidently rule out malicious intent.

## False Positive Considerations
- Legitimate administrative or maintenance activity matching this pattern.
- Approved security testing or red team exercise.
- Known benign software producing similar telemetry.

Generated by SOC Response Atlas by Basyrix.
