0xC00002EE Windows logon failure code Triage: low

0xC00002EE: Windows Logon Failure — Security Context Deleted Early

Published

The authentication exchange was torn down before it finished, so Windows recorded the attempt as a logon failure — the code describes an abandoned handshake, not a rejected username or password.

Did the attacker have the password? Cannot tell from this code alone — correlate with the events around it.

Microsoft's definition

STATUS_UNFINISHED_CONTEXT_DELETED

A security context was deleted before the context was completed. This is considered a logon failure.

Source: [MS-ERREF] NTSTATUS Values · checked against the published table on every build · look up another code

Where it appears

  • Event 4625 (An account failed to log on): the Status or Sub Status field
  • Microsoft Sentinel / Log Analytics: the Status and SubStatus columns of the SecurityEvent table

What it means

Windows authentication through SSPI — NTLM, Kerberos or Negotiate behind a protocol such as SMB or RDP — is not a single message. The client and the server build a security context over several exchanges before the logon is either accepted or refused. 0xC00002EE is recorded when that context is deleted before the exchange reaches an outcome; Microsoft’s NTSTATUS table words it as “A security context was deleted before the context was completed. This is considered a logon failure.”

For triage the key point is what the code does not say. It makes no claim about the account name or the password. Windows has dedicated values for those outcomes — 0xC0000064 for a name that does not exist, 0xC000006A for a real account with the wrong password, 0xC0000234 for a locked account — and none of them is present here. Treat 0xC00002EE as “the attempt stopped mid-handshake” and look elsewhere in the same source’s events for whether credentials were ever evaluated.

Read both fields in the event. When Status is 0xC000006D the real reason lives in Sub Status; when this code sits in Status and Sub Status is 0x0, the event carries nothing more specific.

Microsoft does not publish a list of the client or network conditions that produce this status, so any mapping you make to a particular product or protocol behaviour should be confirmed against your own logs before you rely on it in a runbook.

Is it an attack?

PatternReading
Occasional events from known workstations, one account eachInterrupted or abandoned authentication attempts; low interest on their own
Steady low-rate events from one internal server, always the same accountInvestigate as an application or service problem, not an intrusion
One external source, many different account namesAuthentication probing — pivot to the other 4625 codes from that source
This code alongside 0xC000006A or 0xC0000064 from the same IPThe source is guessing credentials; this code is a by-product, the others carry the evidence
Followed by a 4624 success from the same source and accountSomething completed later — reconstruct the session before dismissing anything

Because the code is silent about credentials, severity comes from the surrounding events, not from this one.

How to investigate

Start by grouping the events by source to see whether any single address is spraying names:

SecurityEvent
| where TimeGenerated > ago(1d)
| where EventID == 4625
| where Status =~ "0xc00002ee" or SubStatus =~ "0xc00002ee"
| summarize Events = count(), Accounts = dcount(TargetUserName),
            AccountList = make_set(TargetUserName, 20),
            LogonTypes = make_set(LogonType, 5), Hosts = make_set(Computer, 10)
    by IpAddress
| order by Events desc

Then take any source that touched several accounts and look at the full mix of failure codes it produced — that is where a credential attack shows itself:

let suspect = "192.0.2.50";
SecurityEvent
| where TimeGenerated > ago(1d) and EventID == 4625 and IpAddress == suspect
| summarize Events = count(), Accounts = dcount(TargetUserName),
            AccountList = make_set(TargetUserName, 20)
    by Status, SubStatus, LogonType
| order by Events desc

Finally, check whether that source ever succeeded:

SecurityEvent
| where TimeGenerated > ago(1d) and EventID == 4624 and IpAddress == "192.0.2.50"
| project TimeGenerated, Computer, TargetUserName, TargetDomainName, LogonType, WorkstationName
| order by TimeGenerated asc

If the source is internal and repeats on a schedule, hand it to the owning team as a configuration fault. If it is external and paired with wrong-password or unknown-user failures, handle it as credential guessing — the Windows 4625 password-spray rule groups those failures by source. Without a SIEM, export the Security log as XML from Event Viewer and load it into the free browser analyzer to group 4625 events by source address and status.

Related codes

  • 0xC000006D STATUS_LOGON_FAILURE The logon was rejected as invalid without saying which half was wrong — it is the general failure result that event 4625 usually carries in Status, with the real reason in Sub Status.
  • 0xC000006A STATUS_WRONG_PASSWORD The account exists and the password was wrong. One event is a typo; many against one account is brute force; one source failing across many real accounts is password spraying.
  • 0xC0000064 STATUS_NO_SUCH_USER Someone tried to log on with an account name that does not exist. Occasional typos are normal; bursts of invented names from one source are username guessing or spraying with a generic list.
  • 0xC0000234 STATUS_ACCOUNT_LOCKED_OUT The account is locked because the lockout threshold was reached; every further attempt fails with this code until the lockout ends or an administrator unlocks it.

Detect it

MITRE ATT&CK: T1110

Frequently Asked Questions

Does 0xC00002EE mean the password was wrong?
No. Microsoft describes it as a security context that "was deleted before the context was completed", which is a statement about the authentication exchange ending early, not about the credentials. Windows has specific codes for those — 0xC0000064 for an account that does not exist and 0xC000006A for a real account with a bad password — so if you need to know whether a password was checked, look for those codes from the same source instead.
Why does the event show Status 0xC00002EE and Sub Status 0x0?
In event 4625 the Status field holds the general result and Sub Status the more specific reason. When Sub Status is 0x0 there is no extra detail to read, so the Status value is all the event gives you. Always check both fields before triaging, because the pairing differs between events and the credential-specific codes normally appear in Sub Status.
Is a burst of 0xC00002EE events worth alerting on?
On its own it is weak evidence, because the code only says the exchange was abandoned. It becomes interesting when one source address produces it against many different account names, when it arrives from an internet-facing host, or when the same source also generates wrong-password and unknown-user failures. Alert on the combination and the source, not on this code in isolation.
Can I filter 0xC00002EE out of my 4625 alerting?
Only after baselining it per source and per host. Suppressing it blindly removes evidence that a source was attempting authentication at all, which matters when you later reconstruct an attacker's activity. A safer approach is to keep the events searchable but exclude known-noisy internal hosts from alert rules, and review that exclusion list periodically.

Find 0xC00002EE in your own logs

Load a Windows Security event export into the free browser analyzer to group failures by account, source IP and status code (nothing is uploaded), or run it through LogTriage for threat-intel enrichment and an AI-written incident report.