ntlmv2
import "github.com/TheManticoreProject/Manticore/crypto/ntlmv2"
Index
- Constants
- func LMOWFv2(Passwd, User, UserDomain string) []byte
- func NTOWFv2(Passwd, User, UserDomain string) []byte
- func SessionBaseKeyFromResponse(responseKeyNT []byte, ntChallengeResponse []byte) []byte
- func VerifyNTChallengeResponse(responseKeyNT []byte, serverChallenge [8]byte, ntChallengeResponse []byte) bool
- type NTLMv2Ctx
- func NewNTLMv2CtxWithNTHash(domain, username string, nthash [16]byte, serverChallenge, clientChallenge [8]byte) (*NTLMv2Ctx, error)
- func NewNTLMv2CtxWithPassword(domain, username, password string, serverChallenge, clientChallenge [8]byte) (*NTLMv2Ctx, error)
- func (ntlm *NTLMv2Ctx) ComputeLMChallengeResponse(hasTimestamp bool) []byte
- func (ntlm *NTLMv2Ctx) ComputeNTChallengeResponse(timestamp []byte, targetInfo []byte) ([]byte, []byte, error)
- func (ntlm *NTLMv2Ctx) ComputeResponse(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClientChallenge, timestamp []byte, ServerName []byte) ([]byte, error)
- func (ntlm *NTLMv2Ctx) ComputeSessionBaseKey(ntProofStr []byte) []byte
- type NTLMv2Response
- func NewNTLMv2Response(username, domain string, serverChallenge [8]byte, lmChallengeResponse [24]byte, ntChallengeResponse []byte) *NTLMv2Response
- func (r *NTLMv2Response) Blob() []byte
- func (r *NTLMv2Response) HashcatString() (string, error)
- func (r *NTLMv2Response) NTProofStr() []byte
- func (r *NTLMv2Response) String() string
Constants
HashcatMode is the hashcat hash-mode number for a NetNTLMv2 response, so a caller writing captured material to a file can label it correctly.
const HashcatMode = 5600
LmChallengeResponseLength is the length in bytes of an LMv2 response: a 16-byte HMAC-MD5 followed by the 8-byte client challenge. Unlike the NT response it is fixed-size, and it is all zeroes when the server’s TargetInfo carried a timestamp.
const LmChallengeResponseLength = 24
NTProofStrLength is the length in bytes of the NTProofStr that prefixes an NTLMv2 NtChallengeResponse. It is the HMAC-MD5 taken over the server challenge concatenated with the blob that follows it ([MS-NLMP] 3.3.2).
const NTProofStrLength = 16
func LMOWFv2
func LMOWFv2(Passwd, User, UserDomain string) []byte
LMOWFv2 computes the LMOWFv2 hash for a given password, username, and domain Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3
Returns:
- The LMOWFv2 hash as a byte slice
- An error if the computation fails
func NTOWFv2
func NTOWFv2(Passwd, User, UserDomain string) []byte
NTOWFv2 computes the NTOWFv2 hash (ResponseKeyNT) for a given password, username, and domain. Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3
func SessionBaseKeyFromResponse
func SessionBaseKeyFromResponse(responseKeyNT []byte, ntChallengeResponse []byte) []byte
SessionBaseKeyFromResponse derives the SessionBaseKey for a verified NTLMv2 response: HMAC_MD5(ResponseKeyNT, NTProofStr) ([MS-NLMP] 3.3.2). It is the acceptor’s route to the key material, taking the NTProofStr from the response as received rather than from a computation of its own.
Parameters:
- responseKeyNT: the NTOWFv2 for the claimed identity
- ntChallengeResponse: the response as received, NTProofStr(16) || blob
Returns:
- The 16-byte SessionBaseKey, or nil if the response carries no NTProofStr
func VerifyNTChallengeResponse
func VerifyNTChallengeResponse(responseKeyNT []byte, serverChallenge [8]byte, ntChallengeResponse []byte) bool
VerifyNTChallengeResponse reports whether an NTLMv2 NT challenge response was produced by a party holding responseKeyNT.
It is the acceptor-side counterpart of ComputeNTChallengeResponse. The two cannot share an implementation: the computing side builds the blob itself from a timestamp and a TargetInfo, whereas a verifier is handed a blob the client chose and must recompute the proof over exactly those bytes. Reconstructing the blob instead would reject every legitimate client whose blob differs in any detail from the one this implementation would have built.
NTProofStr = HMAC_MD5(ResponseKeyNT, ServerChallenge || blob)
where the response is NTProofStr(16) || blob(variable) ([MS-NLMP] 3.3.2). The comparison is constant-time.
Parameters:
- responseKeyNT: the NTOWFv2 for the claimed identity, as computed by NewNTLMv2CtxWithNTHash
- serverChallenge: the 8-byte challenge the response answers
- ntChallengeResponse: the response as received, NTProofStr(16) || blob
Returns:
- true when the response verifies against responseKeyNT
type NTLMv2Ctx
NTLMv2 represents the components needed for NTLMv2 authentication https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3
type NTLMv2Ctx struct {
Domain string
Username string
Password string
ServerChallenge [8]byte
ClientChallenge [8]byte
NTHash [16]byte
LMHash [16]byte
ResponseKeyNT [16]byte
ResponseKeyLM [16]byte
}
func NewNTLMv2CtxWithNTHash
func NewNTLMv2CtxWithNTHash(domain, username string, nthash [16]byte, serverChallenge, clientChallenge [8]byte) (*NTLMv2Ctx, error)
NewNTLMv2CtxWithNTHash creates a new NTLMv2 instance with the provided credentials and challenges
Parameters:
- domain: The domain name
- username: The username
- nthash: The 16-byte NT hash
- serverChallenge: The 8-byte server challenge
- clientChallenge: The 8-byte client challenge
func NewNTLMv2CtxWithPassword
func NewNTLMv2CtxWithPassword(domain, username, password string, serverChallenge, clientChallenge [8]byte) (*NTLMv2Ctx, error)
NewNTLMv2CtxWithPassword creates a new NTLMv2 instance with the provided credentials and challenges
Parameters:
- domain: The domain name
- username: The username
- password: The plaintext password
- serverChallenge: The 8-byte server challenge
- clientChallenge: The 8-byte client challenge
func (*NTLMv2Ctx) ComputeLMChallengeResponse
func (ntlm *NTLMv2Ctx) ComputeLMChallengeResponse(hasTimestamp bool) []byte
ComputeLMChallengeResponse computes the LmChallengeResponse per MS-NLMP 3.1.5.1.2.
When hasTimestamp is true (MsvAvTimestamp was present in the server TargetInfo), the spec requires LmChallengeResponse to be Z(24). Otherwise it is:
HMAC-MD5(ResponseKeyLM, ServerChallenge || ClientChallenge) || ClientChallenge (24 bytes)
Parameters:
- hasTimestamp: true when MsvAvTimestamp was present in the server’s TargetInfo
func (*NTLMv2Ctx) ComputeNTChallengeResponse
func (ntlm *NTLMv2Ctx) ComputeNTChallengeResponse(timestamp []byte, targetInfo []byte) ([]byte, []byte, error)
ComputeNTChallengeResponse builds the full NTChallengeResponse (NTProofStr || blob) as specified in MS-NLMP section 3.3.2.
The blob structure (called “temp” in the spec):
RespType(1) | HiRespType(1) | Z(2) | Z(4) | Timestamp(8) | ClientChallenge(8) | Z(4) | TargetInfo(var) | Z(4)
targetInfo should already have MsvAvFlags set (use targetinfo.BuildBlobTargetInfo to prepare it).
Parameters:
- timestamp: 8-byte Windows FILETIME from MsvAvTimestamp or derived from current time
- targetInfo: raw TargetInfo bytes prepared for the blob
Returns:
- ntChallengeResponse: NTProofStr(16) || blob(variable)
- ntProofStr: the 16-byte NTProofStr (needed for ComputeSessionBaseKey)
- error
func (*NTLMv2Ctx) ComputeResponse
func (ntlm *NTLMv2Ctx) ComputeResponse(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClientChallenge, timestamp []byte, ServerName []byte) ([]byte, error)
ComputeResponse computes the combined NTLMv2 challenge response (low-level, explicit params). Prefer ComputeNTChallengeResponse and ComputeLMChallengeResponse for new code.
Parameters:
- ResponseKeyNT: the 16-byte ResponseKeyNT (NTOWFv2 result)
- ResponseKeyLM: the 16-byte ResponseKeyLM (same as ResponseKeyNT for NTLMv2)
- ServerChallenge: the 8-byte server challenge
- ClientChallenge: the 8-byte client challenge
- timestamp: the 8-byte Windows FILETIME timestamp
- ServerName: the raw TargetInfo bytes for the blob
Returns:
- NTChallengeResponse || LmChallengeResponse concatenated
func (*NTLMv2Ctx) ComputeSessionBaseKey
func (ntlm *NTLMv2Ctx) ComputeSessionBaseKey(ntProofStr []byte) []byte
ComputeSessionBaseKey derives the SessionBaseKey from the NTProofStr.
SessionBaseKey = HMAC-MD5(ResponseKeyNT, NTProofStr)
This key is RC4-encrypted with a random session key when KEY_EXCH is negotiated.
Parameters:
- ntProofStr: the 16-byte NTProofStr returned by ComputeNTChallengeResponse
type NTLMv2Response
NTLMv2Response is a NetNTLMv2 authentication: the identity that was claimed, the server challenge it answered, and the responses it carried.
NtChallengeResponse is variable-length by construction — NTProofStr(16) || blob(variable), exactly what NTLMv2Ctx.ComputeNTChallengeResponse produces — where the blob holds the response type, a timestamp, the client challenge and the server’s TargetInfo AV_PAIR list. In practice it runs from roughly 44 bytes to a few hundred, so it cannot be held in a fixed-size array.
An NtChallengeResponse of exactly 24 bytes is an NTLMv1 response rather than an NTLMv2 one, and belongs in crypto/ntlmv1.NTLMv1Response, which renders the different layout hashcat expects for it.
type NTLMv2Response struct {
Username string // Username for authentication
Domain string // Domain name
ServerChallenge [8]byte // 8-byte challenge from the server
LmChallengeResponse [24]byte // 24-byte LMv2 challenge response
NtChallengeResponse []byte // NTProofStr(16) || blob(variable)
}
func NewNTLMv2Response
func NewNTLMv2Response(username, domain string, serverChallenge [8]byte, lmChallengeResponse [24]byte, ntChallengeResponse []byte) *NTLMv2Response
NewNTLMv2Response creates a new NTLMv2 response.
Parameters:
- username: The username
- domain: The domain name
- serverChallenge: The 8-byte server challenge
- lmChallengeResponse: The 24-byte LMv2 challenge response
- ntChallengeResponse: The NT challenge response, NTProofStr(16) || blob
Returns:
- A pointer to the new NTLMv2Response
func (*NTLMv2Response) Blob
func (r *NTLMv2Response) Blob() []byte
Blob returns the variable-length blob that follows the NTProofStr in the NT challenge response, or nil when the response is too short to carry one. The blob is what the NTProofStr is computed over, together with the server challenge, so cracking needs both.
Returns:
- The blob, or nil
func (*NTLMv2Response) HashcatString
func (r *NTLMv2Response) HashcatString() (string, error)
HashcatString renders the response in the format hashcat mode 5600 expects:
username::domain:serverchallenge:ntproofstr:blob
The hex is uppercased for consistency with the rest of this repository; hashcat parses hex case-insensitively.
Returns:
- The hashcat string
- An error if the NT challenge response cannot form a mode-5600 line
func (*NTLMv2Response) NTProofStr
func (r *NTLMv2Response) NTProofStr() []byte
NTProofStr returns the 16-byte NTProofStr prefix of the NT challenge response, or nil when the response is too short to carry one.
Returns:
- The NTProofStr, or nil
func (*NTLMv2Response) String
func (r *NTLMv2Response) String() string
String returns the NTLMv2 response in hashcat mode 5600 form, or the empty string when it cannot be rendered.
Returns:
- The hashcat string, or ""