Agent Foskett Academy • Lesson 32 • Normalising Text with tolower() and toupper()

Normalising Text with tolower() and toupper()

Microsoft security telemetry often contains usernames, domains and email addresses that appear in different letter casing.

One event may show MICROSOFT.COM, another Microsoft.com and another microsoft.com.

Using tolower() and toupper(), defenders can normalise text before comparing, grouping and investigating evidence.

In this lesson, you'll learn how these functions help create cleaner and more reliable Microsoft Defender XDR and Sentinel investigations.

Agent Foskett Academy lesson explaining how to use tolower and toupper in KQL investigations
Lesson overview

Learn how tolower() and toupper() help defenders normalise text before comparing investigation evidence.

Normalise text evidence
Compare values consistently
Clean grouped results
🎯 tolower() and toupper() help remove casing noise from investigation evidence.
Use them when domains, accounts, filenames, URLs or command-line values need to be compared consistently.
Review Lesson 31 →

Why text normalisation matters

Text casing can create unnecessary investigation noise.

A sender domain, user principal name, device name or command-line value may appear with mixed casing depending on the source system, application, operating system or log pipeline.

Normalising text helps defenders compare values fairly, group related evidence together and avoid treating the same indicator as multiple different values.
Reduce duplicate valuesGroup MICROSOFT.COM, Microsoft.com and microsoft.com together by converting them to the same case.
Improve comparisonsCompare users, domains, filenames and URLs without casing differences getting in the way.
Clean investigation outputCreate readable and consistent fields that are easier to summarise, explain and reuse.

Investigation scenario

Agent Foskett is reviewing email, identity and endpoint telemetry after several phishing reports and suspicious PowerShell events.

The evidence contains mixed casing across sender domains, user names and command lines.

Before grouping and comparing the results, the analyst creates normalised fields using tolower() and toupper() so the investigation can focus on behaviour instead of formatting differences.

Step 1 — Normalise sender domains in EmailEvents

Use tolower() to convert sender domains into consistent lowercase text before grouping email activity.
tolower-normalise-sender-domains.kql
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
EmailEvents
| where Timestamp > ago(30d)
| extend SenderDomainLower = tolower(SenderFromDomain)
| summarize EmailCount = count() by SenderDomainLower
| order by EmailCount desc

Step 2 — Normalise user names before comparison

User values can appear in different casing across platforms. Normalise them before comparing or joining evidence.
tolower-normalise-usernames.kql
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
SigninLogs
| where TimeGenerated > ago(7d)
| extend UserLower = tolower(UserPrincipalName)
| project TimeGenerated, UserPrincipalName, UserLower, IPAddress, Location, ResultType
| order by TimeGenerated desc

Step 3 — Normalise command-line evidence

tolower() can make command-line searches more consistent when casing varies across process execution logs.
tolower-commandline-evidence.kql
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| extend CommandLower = tolower(ProcessCommandLine)
| where CommandLower has_any ("encodedcommand", "downloadstring", "invoke-webrequest")
| project Timestamp, DeviceName, AccountName, FileName, CommandLower
| order by Timestamp desc

How tolower() and toupper() work

The tolower() function converts text into lowercase.

The toupper() function converts text into uppercase.

Both functions are useful when the investigation needs consistent values before filtering, summarising, joining or reporting.
Original valueThe field or expression that contains text, such as a domain, username, filename, URL or command line.
Normalised valueThe consistent lowercase or uppercase value returned by tolower() or toupper().
Reliable comparisonThe normalised field can be compared, grouped or joined without casing differences creating noise.

Step 4 — Use toupper() for consistent reporting labels

toupper() can be useful when you want output values or classification labels to appear consistently in reports.
toupper-consistent-reporting-labels.kql
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
EmailEvents
| where Timestamp > ago(30d)
| extend DeliveryActionUpper = toupper(DeliveryAction)
| summarize TotalEvents = count() by DeliveryActionUpper
| order by TotalEvents desc

Normalised text compared with raw text

Use raw text for displayKeep original fields when you need to preserve exactly what appeared in the log.
Use normalised text for logicCreate lowercase or uppercase fields when you need consistent comparisons and grouping.
Show both when usefulProject the original value and the normalised value together when explaining investigation evidence.

Common investigation uses

Email investigationsNormalise sender domains, recipient addresses and authentication-related text before grouping suspicious activity.
Identity investigationsNormalise user principal names and account fields before comparing activity across identity logs.
Endpoint huntingNormalise command lines, file names and paths before searching for suspicious tools or arguments.

Common mistakes

Forgetting the original valueNormalised fields are helpful, but original values may still matter when preserving forensic detail.
Normalising after groupingCreate the normalised field before summarize, join or comparison logic that depends on it.
Using casing as evidence too earlyMixed casing may be suspicious in some cases, but first confirm whether it is just normal log variation.

What you learned

tolower() creates lowercase evidenceYou learned how to normalise domains, users and command lines into consistent lowercase values.
toupper() creates uppercase evidenceYou learned how uppercase conversion can help with consistent reporting labels and clean outputs.
Normalisation improves investigationsYou learned how consistent text helps defenders compare, group and explain evidence more reliably.
Next lesson: Working with Numeric Values using toint()
Now that you can convert and normalise text, the next step is learning how to convert values into numbers for thresholds, counts and comparisons.
Back to Academy →

Related Agent Foskett Academy lessons

Converting Values with tostring() Review how defenders convert values into readable text before cleaning and normalising evidence.
Creating New Evidence Fields with extend Review how defenders create new fields before applying text conversion and normalisation logic.

Continue learning with Using has_any to Find Suspicious Text, KQL Threat Hunting Guide and Microsoft Security.

Develop IT. Protect IT. GEMXIT PTY LTD | GEMXIT UK LTD

Normalising Text with tolower() and toupper()

Agent Foskett Academy Lesson 32 teaches defenders how to use the KQL tolower() and toupper() functions to normalise text values before comparing Microsoft security telemetry.

Learn KQL text normalisation for Microsoft Defender XDR and Sentinel

This lesson explains how tolower() and toupper() support Microsoft Defender XDR and Microsoft Sentinel investigations by cleaning usernames, domains, filenames, URLs and command-line evidence.