Query Details

Lotusblo Obfuscated Powershell Script Detection

Query

# *Lotusblo Obfuscated Powershell Script Detection*

## Query Information

#### MITRE ATT&CK Technique(s)

| Technique ID | Title    | Link    |
| ---  | --- | --- |
| T1059.001 | Powershell | https://attack.mitre.org/techniques/T1059/001/ |
| T1027 | Obfuscated Files or Information | https://attack.mitre.org/techniques/T1027/ |

#### Description

This rule detects suspicious, obfuscated PowerShell commands by analyzing the command line for long string literals with low character diversity and high frequency of a single character. It extracts strings enclosed in single quotes, double quotes, or backticks, and then calculates the ratio of distinct characters to total length and the ratio of the most frequent character's count to total length. If these ratios fall below and above certain thresholds, respectively, the command is flagged as suspicious.

I would appreciate any feedback or suggestions for improvement. This query is intentionally flagged as EXPERIMENTAL.

#### Author <Optional>
- **Name: Benjamin Zulliger**
- **Github: https://github.com/benscha/KQLAdvancedHunting**
- **LinkedIn: https://www.linkedin.com/in/benjamin-zulliger/**

#### References
- https://www.cyberproof.com/blog/fileless-remcos-attacks-on-the-rise/


## Defender XDR
```KQL
// EXPERIMENTAL
// Searches for suspicious, obfuscated PowerShell commands
// Based on the PowerShell command in this report: https://www.cyberproof.com/blog/fileless-remcos-attacks-on-the-rise/
DeviceProcessEvents
| where InitiatingProcessFileName =~ "powershell.exe"
| extend CommandLine = tolower(ProcessCommandLine) 
| where strlen(CommandLine) > 100
// Find string literals with different types of quotation marks
| extend SingleQuoteStrings = extract_all(@"'([^']{20,})'", CommandLine)
| extend DoubleQuoteStrings = extract_all("\"([^\"]{20,})\"", CommandLine)
| extend BacktickStrings = extract_all(@"`([^`]{20,})`", CommandLine)
// Combine all extracted strings
| extend AllStrings = array_concat(SingleQuoteStrings, DoubleQuoteStrings, BacktickStrings)
| where array_length(AllStrings) > 0
// Expand each extracted string literal
| mv-expand SuspiciousString = AllStrings to typeof(string)
| where isnotempty(SuspiciousString)
| extend TotalLength = strlen(SuspiciousString)
| where TotalLength > 20
// Create an index for every character in the string
| mv-apply Index = range(0, TotalLength - 1, 1) on (
    project Character = substring(SuspiciousString, toint(Index), 1)
)
// Count how often each character occurs
| summarize CharFrequency = count() 
    by DeviceId, Timestamp, Character, TotalLength, TimeGenerated, DeviceName, CommandLine, SuspiciousString, ReportId
// Find the maximum frequency and number of unique characters
| summarize 
    DistinctChars = dcount(Character),
    MostFrequentCharCount = max(CharFrequency),
    TotalLength = any(TotalLength),
    TimeGenerated = any(TimeGenerated),
    DeviceName = any(DeviceName),
    CommandLine = any(CommandLine),
    ReportId = any(ReportId)
    by DeviceId, Timestamp, SuspiciousString
// Calculate ratios
| extend Ratio_Diversity_Total = todouble(DistinctChars) / TotalLength 
| extend Ratio_Junk_Total = todouble(MostFrequentCharCount) / TotalLength 
// Apply threshold values for detection
| where Ratio_Diversity_Total < 0.38 // lower value = more aggressive detection
| where Ratio_Junk_Total > 0.25 // lower value = more aggressive detection
| project TimeGenerated, DeviceId, DeviceName, ReportId, CommandLine, SuspiciousString, TotalLength, DistinctChars, MostFrequentCharCount, Ratio_Diversity_Total, Ratio_Junk_Total
| sort by Ratio_Junk_Total desc
```

Explanation

This query is designed to detect suspicious PowerShell commands that may be obfuscated, which is a common technique used by attackers to hide malicious code. Here's a simplified breakdown of what the query does:

  1. Target Process: It focuses on events where the process name is "powershell.exe", indicating that PowerShell is being used.

  2. Command Line Analysis: It examines the command line input for PowerShell commands that are longer than 100 characters, as longer commands are more likely to contain obfuscation.

  3. String Extraction: The query extracts string literals from the command line that are enclosed in single quotes, double quotes, or backticks. These strings must be at least 20 characters long to be considered.

  4. Character Analysis: For each extracted string, the query calculates:

    • The total length of the string.
    • The diversity of characters in the string (how many unique characters are present).
    • The frequency of the most common character in the string.
  5. Ratio Calculation: It computes two ratios for each string:

    • Ratio of Character Diversity: The number of unique characters divided by the total length of the string. A lower ratio suggests less diversity, which is typical in obfuscated code.
    • Ratio of Character Frequency: The frequency of the most common character divided by the total length of the string. A higher ratio indicates that one character is overly represented, which can be a sign of obfuscation.
  6. Suspicion Thresholds: The query flags strings as suspicious if:

    • The diversity ratio is below 0.38, indicating low character variety.
    • The frequency ratio is above 0.25, indicating high repetition of a single character.
  7. Output: It lists the details of the suspicious commands, including the time, device information, and the suspicious string itself, sorted by the frequency ratio in descending order.

This query is experimental and aims to identify potentially malicious PowerShell activity by detecting patterns typical of obfuscated scripts. It uses specific thresholds to balance between catching true positives and minimizing false positives.

Details

Benjamin Zulliger profile picture

Benjamin Zulliger

Released: October 31, 2025

Tables

DeviceProcessEvents

Keywords

DeviceProcessEvents

Operators

=~tolowerstrlenextract_allarray_concatarray_lengthmv-expandisnotemptystrlenmv-applyprojectsubstringtointsummarizedcountmaxanyextendtodoublewhereprojectsort

Actions