{"record":{"id":"4026dcb4bc70c4dd","repo":"projectdiscovery/nuclei","slug":"expected-ntlm-challenge-message-got-type-d","errorCode":null,"errorMessage":"expected NTLM challenge message, got type %d","messagePattern":"expected NTLM challenge message, got type (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/utils/telnetmini/ntlm.go","lineNumber":52,"sourceCode":"\t// Find the end of NTLM data (Sub-option End: 0xFF 0xF0)\n\tntlmEnd := bytes.Index(data[ntlmStart:], []byte{0xFF, 0xF0})\n\tif ntlmEnd == -1 {\n\t\treturn nil, fmt.Errorf(\"NTLM response not properly terminated with Sub-option End\")\n\t}\n\n\t// Extract NTLM data (NTLMSSP.*\\xff\\xf0)\n\tntlmData := data[ntlmStart : ntlmStart+ntlmEnd]\n\n\t// Check message type (should be 2 for Challenge).\n\t// The fixed header runs to offset 48 (target-info offset field ends at byte 48),\n\t// so reject anything shorter before touching any field offsets.\n\tif len(ntlmData) < 48 {\n\t\treturn nil, fmt.Errorf(\"NTLM response too short: need at least 48 bytes, got %d\", len(ntlmData))\n\t}\n\n\tmessageType := binary.LittleEndian.Uint32(ntlmData[8:12])\n\tif messageType != 2 {\n\t\treturn nil, fmt.Errorf(\"expected NTLM challenge message, got type %d\", messageType)\n\t}\n\n\t// Parse target name fields\n\ttargetNameLen := binary.LittleEndian.Uint16(ntlmData[12:14])\n\ttargetNameOffset := binary.LittleEndian.Uint32(ntlmData[16:20])\n\n\t// Parse target info fields\n\ttargetInfoLen := binary.LittleEndian.Uint16(ntlmData[40:42])\n\ttargetInfoOffset := binary.LittleEndian.Uint32(ntlmData[44:48])\n\n\t// Extract target name (Target Name will always be returned under any implementation)\n\tvar targetName string\n\tif targetNameLen > 0 && int(targetNameOffset) < len(ntlmData) {\n\t\tend := int(targetNameOffset) + int(targetNameLen)\n\t\tif end <= len(ntlmData) {\n\t\t\ttargetName = string(ntlmData[targetNameOffset:end])\n\t\t}\n\t}","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/utils/telnetmini/ntlm.go#L34-L70","documentation":"ParseNTLMResponse reads the NTLM message type at offset 8 and requires 2 (NEGOTIATE-to-CHALLENGE exchange: the server's Challenge message is what carries target name, timestamps, and NetBIOS info this parser extracts). Type 1 (Negotiate), type 3 (Authenticate), or garbage yields 'expected NTLM challenge message, got type %d'.","triggerScenarios":"The captured sub-option contains a different NTLM message than the challenge: e.g. a server that echoes the client's type-1 Negotiate back, a capture that picked up a type-3 exchange, or 4+ bytes of non-message data that happens to follow the signature. Type values other than 2 (commonly 1 or 3) appear in the message.","commonSituations":"Non-compliant telnet implementations that mirror negotiation; security appliances that respond with odd NTLM blobs; off-by-one conditions where the signature match lands on embedded NTLM bytes inside other data (e.g. SMB-over-telnet tunnels).","solutions":["Treat as unsupported — the parser only exists to harvest Challenge-message info, other types carry none of it","If the reported type is 1, the server likely echoed your negotiation — one retry occasionally gets the real Challenge","Verify the target really is Windows telnet (banner/other probes) before investing further","Hexdump the blob when integrating telnetmini yourself, to confirm which message type the device emits"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Peek at the message type (offset 8, LE uint32) before full parsing:\nstart := bytes.Index(raw, []byte(\"NTLMSSP\"))\nif start >= 0 && len(raw) >= start+12 {\n    if mt := binary.LittleEndian.Uint32(raw[start+8 : start+12]); mt != 2 {\n        return nil, fmt.Errorf(\"not a challenge message (type %d) — nothing to extract\", mt)\n    }\n}","typeGuard":"func isNTLMChallenge(data []byte) bool {\n    i := bytes.Index(data, []byte(\"NTLMSSP\"))\n    return i >= 0 && len(data) >= i+12 && binary.LittleEndian.Uint32(data[i+8:i+12]) == 2\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"expected NTLM challenge\") {\n    return nil, nil // wrong message type — no info to harvest, skip host\n}","preventionTips":["Only the Challenge (type 2) message carries extractable target info — validate type first","One retry can resolve servers that echo the type-1 Negotiate","Confirm the target is Windows telnet before relying on NTLM extraction"],"tags":["telnet","ntlm","message-type","parsing","network-protocol"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}