Query Details

Query

EmailEvents
| where Timestamp > ago(1d)
| where isnotempty(Subject)
| extend SenderIP = iff(isnotempty(SenderIPv4), SenderIPv4, SenderIPv6)
| extend Country = tostring(geo_info_from_ip_address(SenderIP).country)
| extend SubjectSuspiciousChars = extract_all(@"([\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFEFF])", Subject)
| extend SenderDisplaySuspiciousChars = extract_all(@"([\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFEFF])", SenderDisplayName)
| extend HasEmoji = Subject matches regex @"[\u2600-\u27BF]"
| extend SubjectUnicode = iff(array_length(SubjectSuspiciousChars) > 0, 1, 0), SenderDisplayUnicode = iff(array_length(SenderDisplaySuspiciousChars) > 0, 1, 0)
| summarize Timestamp=max(Timestamp), HasEmoji=max(toint(HasEmoji)), SubjectUnicode=max(SubjectUnicode), SenderDisplayUnicode=max(SenderDisplayUnicode), SubjectSuspiciousChars=make_set(SubjectSuspiciousChars), SenderDisplaySuspiciousChars=make_set(SenderDisplaySuspiciousChars), Countries=make_set(Country), SenderIPs=make_set(SenderIP), SenderDisplayNames=make_set(SenderDisplayName), SenderAddresses=make_set(SenderFromAddress), SenderDomains=make_set(SenderFromDomain), DeliveryLocations=make_set(LatestDeliveryLocation), ThreatTypes=make_set(ThreatTypes), ThreatNames=make_set(ThreatNames), EmailCount=count() by Subject, NetworkMessageId, RecipientEmailAddress
| extend CountryCount = array_length(Countries)
| extend MultiCountry = iff(CountryCount > 1, 1, 0)
| extend RiskScore = (HasEmoji * 40) + (SubjectUnicode * 20) + (SenderDisplayUnicode * 20) + (MultiCountry * 20)
| extend RiskReasons = strcat(iff(HasEmoji == 1, "Unicode symbol in Subject [+40]; ", ""), iff(SubjectUnicode == 1, "Hidden Unicode in Subject [+20]; ", ""), iff(SenderDisplayUnicode == 1, "Hidden Unicode in SenderDisplayName [+20]; ", ""), iff(MultiCountry == 1, strcat("Multiple Countries [+20] (", CountryCount, "); "), ""))
| where RiskScore > 0
| project Timestamp, NetworkMessageId, RecipientEmailAddress, RiskScore, RiskReasons, Subject, SubjectSuspiciousChars, SenderDisplayNames, SenderDisplaySuspiciousChars, Countries, CountryCount, SenderIPs, SenderAddresses, SenderDomains, DeliveryLocations, EmailCount, ThreatTypes, ThreatNames
| order by RiskScore desc, Timestamp desc

About this query

MITRE ATT&CK Technique(s)

Technique IDTitle
T1566Phishing

Author: Sergio Albea (22/09/2026)


𝗛𝘂𝗻𝘁𝗶𝗻𝗴 𝗜𝗻𝘃𝗶𝘀𝗶𝗯𝗹𝗲 𝗨𝗻𝗶𝗰𝗼𝗱𝗲 𝗶𝗻 𝗘𝗺𝗮𝗶𝗹𝘀

Description: For years, when hunting phishing emails, I have mainly focused on what the user sees inside of it. But I think AI agents are going to change this. An email may soon have two audiences: Human + AI Agent. And they may not always see exactly the same thing. In this new KQL, I explore a simple example: invisible Unicode characters. Microsoft and Micro<U+200B>soft may look the same to us, but not necessarily to a detection, filter, parser or AI agent. For attackers, this difference can be interesting as a way to obfuscate content and potentially evade keyword-based detections or other systems processing the text.

I hunt these patterns in email and add context around them. Because attackers will not only write emails for us. They will(are) start writing emails for our agents too.

Explanation

This query is designed to detect potentially suspicious emails by identifying hidden Unicode characters that might be used to evade detection systems. Here's a simplified breakdown of what the query does:

  1. Data Source: It looks at email events from the past day.

  2. Extract Information:

    • It checks if the email subject and sender display name contain invisible Unicode characters, which could be used to disguise the content.
    • It also checks if the subject contains emoji symbols.
  3. Geolocation: It determines the country of the sender based on their IP address.

  4. Risk Scoring:

    • It assigns a risk score to each email based on the presence of emojis, hidden Unicode characters, and if the email is sent from multiple countries.
    • Each factor contributes a certain number of points to the risk score.
  5. Summarization:

    • It summarizes the emails by various attributes like subject, sender, and recipient, and calculates the maximum risk score for each email.
    • It also compiles a list of suspicious characters found in the subject and sender display name.
  6. Filtering and Display:

    • It filters out emails with a risk score greater than zero, indicating potential suspicious activity.
    • It projects relevant information such as the timestamp, risk score, reasons for the risk score, and other email details.
    • Finally, it orders the results by risk score and timestamp, showing the most suspicious emails first.

Overall, the query helps identify emails that might be attempting to bypass detection systems by using hidden characters or other obfuscation techniques.