Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Powershell Empire Cmdlets Executed in Command Line

Back
Idef88eb96-861c-43a0-ab16-f3835a97c928
RulenamePowershell Empire Cmdlets Executed in Command Line
DescriptionThis query identifies use of PowerShell Empire’s cmdlets within the command line data of the PowerShell process, indicating potential use of the post-exploitation tool.
SeverityMedium
TacticsCollection
CommandAndControl
CredentialAccess
DefenseEvasion
Discovery
Execution
Exfiltration
LateralMovement
Persistence
PrivilegeEscalation
TechniquesT1548.002
T1134
T1134.002
T1134.005
T1087.001
T1087.002
T1557.001
T1071.001
T1560
T1547.001
T1547.005
T1547.009
T1217
T1115
T1059
T1059.001
T1059.003
T1136.001
T1136.002
T1543.003
T1555.003
T1484.001
T1482
T1114.001
T1573.002
T1546.008
T1041
T1567.001
T1567.002
T1068
T1210
T1083
T1615
T1574.001
T1574.004
T1574.007
T1574.008
T1574.009
T1070.006
T1105
T1056.001
T1056.004
T1106
T1046
T1135
T1040
T1027
T1003.001
T1057
T1055
T1021.003
T1021.004
T1053.005
T1113
T1518.001
T1558.002
T1558.003
T1082
T1016
T1049
T1569.002
T1127.001
T1552.001
T1552.004
T1550.002
T1125
T1102.002
T1047
Required data connectorsSecurityEvents
WindowsForwardedEvents
WindowsSecurityEvents
KindScheduled
Query frequency12h
Query period12h
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Attacker Tools Threat Protection Essentials/Analytic Rules/powershell_empire.yaml
Version1.3.1
Arm templateef88eb96-861c-43a0-ab16-f3835a97c928.json
Deploy To Azure
let regexEmpire = tostring(toscalar(externaldata(cmdlets:string)[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/EmpireCommandString.txt"] with (format="txt")));
(union isfuzzy=true
 (SecurityEvent
| where EventID == 4688
//consider filtering on filename if perf issues occur
//where FileName in~ ("powershell.exe","powershell_ise.exe","pwsh.exe")
| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))
| where CommandLine has "-encodedCommand"
| parse kind=regex flags=i CommandLine with * "-EncodedCommand " encodedCommand
| extend encodedCommand = iff(encodedCommand has " ", tostring(split(encodedCommand, " ")[0]), encodedCommand)
// Note: currently the base64_decode_tostring function is limited to supporting UTF8
| extend decodedCommand = translate('\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) -  (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)
| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)
| where EfectiveCommand matches regex regexEmpire
| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName
| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')
),
(WindowsEvent
| where EventID == 4688
| where EventData has_any ("-encodedCommand", "powershell.exe","powershell_ise.exe","pwsh.exe")
| where not(EventData has_any ('gc_worker.exe', 'gc_service.exe'))
//consider filtering on filename if perf issues occur
//extend NewProcessName = tostring(EventData.NewProcessName)
//extend Process=tostring(split(NewProcessName, '\\')[-1])
//FileName = Process
//where FileName in~ ("powershell.exe","powershell_ise.exe","pwsh.exe")
| extend ParentProcessName = tostring(EventData.ParentProcessName)
| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))
| extend CommandLine = tostring(EventData.CommandLine)
| where CommandLine has "-encodedCommand"
| parse kind=regex flags=i CommandLine with * "-EncodedCommand " encodedCommand
| extend encodedCommand = iff(encodedCommand has " ", tostring(split(encodedCommand, " ")[0]), encodedCommand)
// Note: currently the base64_decode_tostring function is limited to supporting UTF8
| extend decodedCommand = translate('\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) -  (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)
| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)
| where EfectiveCommand matches regex regexEmpire
| extend SubjectUserName = tostring(EventData.SubjectUserName)
| extend SubjectDomainName = tostring(EventData.SubjectDomainName)
| extend NewProcessName = tostring(EventData.NewProcessName)
| extend Process=tostring(split(NewProcessName, '\\')[-1])
| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName
| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')
))
triggerThreshold: 0
severity: Medium
id: ef88eb96-861c-43a0-ab16-f3835a97c928
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: SubjectUserName
  - identifier: NTDomain
    columnName: SubjectDomainName
- entityType: Host
  fieldMappings:
  - identifier: HostName
    columnName: HostName
  - identifier: DnsDomain
    columnName: DnsDomain
status: Available
requiredDataConnectors:
- connectorId: SecurityEvents
  dataTypes:
  - SecurityEvent
- connectorId: WindowsSecurityEvents
  dataTypes:
  - SecurityEvent
- connectorId: WindowsSecurityEvents
  dataTypes:
  - SecurityEvents
- connectorId: WindowsForwardedEvents
  dataTypes:
  - WindowsEvent
version: 1.3.1
queryFrequency: 12h
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Attacker Tools Threat Protection Essentials/Analytic Rules/powershell_empire.yaml
description: |
    'This query identifies use of PowerShell Empire's cmdlets within the command line data of the PowerShell process, indicating potential use of the post-exploitation tool.'
tactics:
- Collection
- CommandAndControl
- CredentialAccess
- DefenseEvasion
- Discovery
- Execution
- Exfiltration
- LateralMovement
- Persistence
- PrivilegeEscalation
triggerOperator: gt
queryPeriod: 12h
name: Powershell Empire Cmdlets Executed in Command Line
relevantTechniques:
- T1548.002
- T1134
- T1134.002
- T1134.005
- T1087.001
- T1087.002
- T1557.001
- T1071.001
- T1560
- T1547.001
- T1547.005
- T1547.009
- T1217
- T1115
- T1059
- T1059.001
- T1059.003
- T1136.001
- T1136.002
- T1543.003
- T1555.003
- T1484.001
- T1482
- T1114.001
- T1573.002
- T1546.008
- T1041
- T1567.001
- T1567.002
- T1068
- T1210
- T1083
- T1615
- T1574.001
- T1574.004
- T1574.007
- T1574.008
- T1574.009
- T1070.006
- T1105
- T1056.001
- T1056.004
- T1106
- T1046
- T1135
- T1040
- T1027
- T1003.001
- T1057
- T1055
- T1021.003
- T1021.004
- T1053.005
- T1113
- T1518.001
- T1558.002
- T1558.003
- T1082
- T1016
- T1049
- T1569.002
- T1127.001
- T1552.001
- T1552.004
- T1550.002
- T1125
- T1102.002
- T1047
kind: Scheduled
query: |
  let regexEmpire = tostring(toscalar(externaldata(cmdlets:string)[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/EmpireCommandString.txt"] with (format="txt")));
  (union isfuzzy=true
   (SecurityEvent
  | where EventID == 4688
  //consider filtering on filename if perf issues occur
  //where FileName in~ ("powershell.exe","powershell_ise.exe","pwsh.exe")
  | where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))
  | where CommandLine has "-encodedCommand"
  | parse kind=regex flags=i CommandLine with * "-EncodedCommand " encodedCommand
  | extend encodedCommand = iff(encodedCommand has " ", tostring(split(encodedCommand, " ")[0]), encodedCommand)
  // Note: currently the base64_decode_tostring function is limited to supporting UTF8
  | extend decodedCommand = translate('\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) -  (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)
  | extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)
  | where EfectiveCommand matches regex regexEmpire
  | project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName
  | extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')
  ),
  (WindowsEvent
  | where EventID == 4688
  | where EventData has_any ("-encodedCommand", "powershell.exe","powershell_ise.exe","pwsh.exe")
  | where not(EventData has_any ('gc_worker.exe', 'gc_service.exe'))
  //consider filtering on filename if perf issues occur
  //extend NewProcessName = tostring(EventData.NewProcessName)
  //extend Process=tostring(split(NewProcessName, '\\')[-1])
  //FileName = Process
  //where FileName in~ ("powershell.exe","powershell_ise.exe","pwsh.exe")
  | extend ParentProcessName = tostring(EventData.ParentProcessName)
  | where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))
  | extend CommandLine = tostring(EventData.CommandLine)
  | where CommandLine has "-encodedCommand"
  | parse kind=regex flags=i CommandLine with * "-EncodedCommand " encodedCommand
  | extend encodedCommand = iff(encodedCommand has " ", tostring(split(encodedCommand, " ")[0]), encodedCommand)
  // Note: currently the base64_decode_tostring function is limited to supporting UTF8
  | extend decodedCommand = translate('\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) -  (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)
  | extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)
  | where EfectiveCommand matches regex regexEmpire
  | extend SubjectUserName = tostring(EventData.SubjectUserName)
  | extend SubjectDomainName = tostring(EventData.SubjectDomainName)
  | extend NewProcessName = tostring(EventData.NewProcessName)
  | extend Process=tostring(split(NewProcessName, '\\')[-1])
  | project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName
  | extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')
  ))  
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2023-02-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/ef88eb96-861c-43a0-ab16-f3835a97c928')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/ef88eb96-861c-43a0-ab16-f3835a97c928')]",
      "properties": {
        "alertRuleTemplateName": "ef88eb96-861c-43a0-ab16-f3835a97c928",
        "customDetails": null,
        "description": "'This query identifies use of PowerShell Empire's cmdlets within the command line data of the PowerShell process, indicating potential use of the post-exploitation tool.'\n",
        "displayName": "Powershell Empire Cmdlets Executed in Command Line",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "SubjectUserName",
                "identifier": "Name"
              },
              {
                "columnName": "SubjectDomainName",
                "identifier": "NTDomain"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "HostName",
                "identifier": "HostName"
              },
              {
                "columnName": "DnsDomain",
                "identifier": "DnsDomain"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Attacker Tools Threat Protection Essentials/Analytic Rules/powershell_empire.yaml",
        "query": "let regexEmpire = tostring(toscalar(externaldata(cmdlets:string)[@\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/EmpireCommandString.txt\"] with (format=\"txt\")));\n(union isfuzzy=true\n (SecurityEvent\n| where EventID == 4688\n//consider filtering on filename if perf issues occur\n//where FileName in~ (\"powershell.exe\",\"powershell_ise.exe\",\"pwsh.exe\")\n| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))\n| where CommandLine has \"-encodedCommand\"\n| parse kind=regex flags=i CommandLine with * \"-EncodedCommand \" encodedCommand\n| extend encodedCommand = iff(encodedCommand has \" \", tostring(split(encodedCommand, \" \")[0]), encodedCommand)\n// Note: currently the base64_decode_tostring function is limited to supporting UTF8\n| extend decodedCommand = translate('\\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) -  (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)\n| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)\n| where EfectiveCommand matches regex regexEmpire\n| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName\n| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')\n),\n(WindowsEvent\n| where EventID == 4688\n| where EventData has_any (\"-encodedCommand\", \"powershell.exe\",\"powershell_ise.exe\",\"pwsh.exe\")\n| where not(EventData has_any ('gc_worker.exe', 'gc_service.exe'))\n//consider filtering on filename if perf issues occur\n//extend NewProcessName = tostring(EventData.NewProcessName)\n//extend Process=tostring(split(NewProcessName, '\\\\')[-1])\n//FileName = Process\n//where FileName in~ (\"powershell.exe\",\"powershell_ise.exe\",\"pwsh.exe\")\n| extend ParentProcessName = tostring(EventData.ParentProcessName)\n| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))\n| extend CommandLine = tostring(EventData.CommandLine)\n| where CommandLine has \"-encodedCommand\"\n| parse kind=regex flags=i CommandLine with * \"-EncodedCommand \" encodedCommand\n| extend encodedCommand = iff(encodedCommand has \" \", tostring(split(encodedCommand, \" \")[0]), encodedCommand)\n// Note: currently the base64_decode_tostring function is limited to supporting UTF8\n| extend decodedCommand = translate('\\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) -  (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)\n| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)\n| where EfectiveCommand matches regex regexEmpire\n| extend SubjectUserName = tostring(EventData.SubjectUserName)\n| extend SubjectDomainName = tostring(EventData.SubjectDomainName)\n| extend NewProcessName = tostring(EventData.NewProcessName)\n| extend Process=tostring(split(NewProcessName, '\\\\')[-1])\n| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName\n| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')\n))\n",
        "queryFrequency": "PT12H",
        "queryPeriod": "PT12H",
        "severity": "Medium",
        "status": "Available",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Collection",
          "CommandAndControl",
          "CredentialAccess",
          "DefenseEvasion",
          "Discovery",
          "Execution",
          "Exfiltration",
          "LateralMovement",
          "Persistence",
          "PrivilegeEscalation"
        ],
        "techniques": [
          "T1003",
          "T1016",
          "T1021",
          "T1027",
          "T1040",
          "T1041",
          "T1046",
          "T1047",
          "T1049",
          "T1053",
          "T1055",
          "T1056",
          "T1057",
          "T1059",
          "T1068",
          "T1070",
          "T1071",
          "T1082",
          "T1083",
          "T1087",
          "T1102",
          "T1105",
          "T1106",
          "T1113",
          "T1114",
          "T1115",
          "T1125",
          "T1127",
          "T1134",
          "T1135",
          "T1136",
          "T1210",
          "T1217",
          "T1482",
          "T1484",
          "T1518",
          "T1543",
          "T1546",
          "T1547",
          "T1548",
          "T1550",
          "T1552",
          "T1555",
          "T1557",
          "T1558",
          "T1560",
          "T1567",
          "T1569",
          "T1573",
          "T1574",
          "T1615"
        ],
        "templateVersion": "1.3.1",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}