mirror of
				https://github.com/Ylianst/MeshCentral.git
				synced 2025-03-09 15:40:18 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			328 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			328 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | |
| YST: create_negotiate_message: 4e544c4d53535000010000003582086000000000000000000000000000000000
 | |
| WRITE: negotiate_message 302fa003020102a12830263024a02204204e544c4d53535000010000003582086000000000000000000000000000000000
 | |
| READ: read_ts_server_challenge 3081b2a003020106a181aa3081a73081a4a081a104819e4e544c4d53535000020000000e000e003800000035828a62f2290572b3cac375000000000000000058005800460000000a00614a0000000f430045004e005400520041004c0002000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000
 | |
| YST: read_challenge_message1: 4e544c4d53535000020000000e000e003800000035828a62f2290572b3cac375000000000000000058005800460000000a00614a0000000f430045004e005400520041004c0002000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000
 | |
| YST: target_name: 02000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000
 | |
| YST: timestamp: afbc2c2a9256d801
 | |
| YST: client_challenge: f8d1e2057b9c7169
 | |
| YST: nt_challenge_response: 32e87ea049485920fca6695ae9daee820101000000000000afbc2c2a9256d801f8d1e2057b9c71690000000002000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000
 | |
| YST: lm_challenge_response: 2b0f863797a00d4446a1c9f49de124a5f8d1e2057b9c7169
 | |
| YST: session_base_key: 52f86f741e92e2e9d8013c1afcecfa13
 | |
| YST: key_exchange_key: 52f86f741e92e2e9d8013c1afcecfa13
 | |
| YST: encrypted_random_session_key: d9b2353a7f7ba9569ece01e96686cdef
 | |
| YST: self.is_unicode: true
 | |
| YST: domain:
 | |
| YST: user: 640065006600610075006c007400
 | |
| YST: tmp_final_auth_message: 4e544c4d53535000030000001800180058000000840084007000000000000000f40000000e000e00f40000000000000002010000100010000201000035828a62060072170000000f000000000000000000000000000000002b0f863797a00d4446a1c9f49de124a5f8d1e2057b9c716932e87ea049485920fca6695ae9daee820101000000000000afbc2c2a9256d801f8d1e2057b9c71690000000002000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000640065006600610075006c007400d9b2353a7f7ba9569ece01e96686cdef
 | |
| YST: signature: 4cbff4ee21ce4114c7657d7aa427ca3f
 | |
| YST: read_challenge_message2: 4e544c4d53535000030000001800180058000000840084007000000000000000f40000000e000e00f40000000000000002010000100010000201000035828a62060072170000000f4cbff4ee21ce4114c7657d7aa427ca3f2b0f863797a00d4446a1c9f49de124a5f8d1e2057b9c716932e87ea049485920fca6695ae9daee820101000000000000afbc2c2a9256d801f8d1e2057b9c71690000000002000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000640065006600610075006c007400d9b2353a7f7ba9569ece01e96686cdef
 | |
| WRITE challenge: 30820251a003020102a18201223082011e3082011aa0820116048201124e544c4d53535000030000001800180058000000840084007000000000000000f40000000e000e00f40000000000000002010000100010000201000035828a62060072170000000f4cbff4ee21ce4114c7657d7aa427ca3f2b0f863797a00d4446a1c9f49de124a5f8d1e2057b9c716932e87ea049485920fca6695ae9daee820101000000000000afbc2c2a9256d801f8d1e2057b9c71690000000002000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000640065006600610075006c007400d9b2353a7f7ba9569ece01e96686cdefa38201220482011e0100000095fb7df84ffcd81d00000000a0588a3354258442e2997c79a4005e91ac49759b3c362228f42aefa5daad071a8eb905d7bc16611df35a50c0c577acf4543609e3ade8ff8289d371d8baed9eb2bd738de6c208f6a9885f1b0ee8aee2b26be87aa189bb41989c79716d938eb68e2f1e4bdc74c25e995c438aa5e5e30c2784214f4763c6737417edac43371f65f22aab68619f022b2f46b4cb9d00d0befe6d7e83d0d2c4ae69b544b1e90b1d5198459722eff903e8550864a46c552d75c83fb8ca8491b573fcd59d17cdc34e2505995fa6922554fdf03016161b430e476875a3752907087e993388f56675957a75b42b062f1f66ef8597a69deb466337396747ec8e46c573344b24fc8fba9305207eb10462ce355299063bab4cf105
 | |
| READ: read_ts_validate 3081b2a003020106a181aa3081a73081a4a081a104819e4e544c4d53535000020000000e000e003800000035828a62f2290572b3cac375000000000000000058005800460000000a00614a0000000f430045004e005400520041004c0002000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000
 | |
| WRITE credentials: 302fa003020102a12830263024a02204204e544c4d53535000010000003582086000000000000000000000000000000000
 | |
| */
 | |
| 
 | |
| /*
 | |
|         "Signature" => Check::new(b"NTLMSSP\x00".to_vec()),
 | |
|         "MessageType" => Check::new(U32::LE(2)),
 | |
|         "TargetNameLen" => U16::LE(0),
 | |
|         "TargetNameLenMax" => U16::LE(0),
 | |
|         "TargetNameBufferOffset" => U32::LE(0),
 | |
|         "NegotiateFlags" => DynOption::new(U32::LE(0), |node| {
 | |
|             if node.inner() & (Negotiate::NtlmsspNegociateVersion as u32) == 0 {
 | |
|                 return MessageOption::SkipField("Version".to_string())
 | |
|             }
 | |
|             return MessageOption::None
 | |
|         }),
 | |
|         "ServerChallenge" => vec![0; 8],
 | |
|         "Reserved" => vec![0; 8],
 | |
|         "TargetInfoLen" => U16::LE(0),
 | |
|         "TargetInfoMaxLen" => U16::LE(0),
 | |
|         "TargetInfoBufferOffset" => U32::LE(0),
 | |
|         "Version" => version(),
 | |
|         "Payload" => Vec::<u8>::new()
 | |
| */
 | |
| 
 | |
| const NegotiateFlags = {
 | |
|     NtlmsspNegociate56: 0x80000000,
 | |
|     NtlmsspNegociateKeyExch: 0x40000000,
 | |
|     NtlmsspNegociate128: 0x20000000,
 | |
|     NtlmsspNegociateVersion: 0x02000000,
 | |
|     NtlmsspNegociateTargetInfo: 0x00800000,
 | |
|     NtlmsspRequestNonNTSessionKey: 0x00400000,
 | |
|     NtlmsspNegociateIdentify: 0x00100000,
 | |
|     NtlmsspNegociateExtendedSessionSecurity: 0x00080000,
 | |
|     NtlmsspTargetTypeServer: 0x00020000,
 | |
|     NtlmsspTargetTypeDomain: 0x00010000,
 | |
|     NtlmsspNegociateAlwaysSign: 0x00008000,
 | |
|     NtlmsspNegociateOEMWorkstationSupplied: 0x00002000,
 | |
|     NtlmsspNegociateOEMDomainSupplied: 0x00001000,
 | |
|     NtlmsspNegociateNTLM: 0x00000200,
 | |
|     NtlmsspNegociateLMKey: 0x00000080,
 | |
|     NtlmsspNegociateDatagram: 0x00000040,
 | |
|     NtlmsspNegociateSeal: 0x00000020,
 | |
|     NtlmsspNegociateSign: 0x00000010,
 | |
|     NtlmsspRequestTarget: 0x00000004,
 | |
|     NtlmNegotiateOEM: 0x00000002,
 | |
|     NtlmsspNegociateUnicode: 0x00000001
 | |
| }
 | |
| 
 | |
| const MajorVersion = {
 | |
|     WindowsMajorVersion5: 0x05,
 | |
|     WindowsMajorVersion6: 0x06
 | |
| }
 | |
| 
 | |
| const MinorVersion = {
 | |
|     WindowsMinorVersion0: 0x00,
 | |
|     WindowsMinorVersion1: 0x01,
 | |
|     WindowsMinorVersion2: 0x02,
 | |
|     WindowsMinorVersion3: 0x03
 | |
| }
 | |
| 
 | |
| const NTLMRevision = {
 | |
|     NtlmSspRevisionW2K3: 0x0F
 | |
| }
 | |
| 
 | |
| function decodeTargetInfo(targetInfoBuf) {
 | |
|     var r = {}, type, len, data, ptr = 0;
 | |
|     while (true) {
 | |
|         type = targetInfoBuf.readInt16LE(ptr);
 | |
|         if (type == 0) break;
 | |
|         len = targetInfoBuf.readInt16LE(ptr + 2);
 | |
|         r[type] = targetInfoBuf.slice(ptr + 4, ptr + 4 + len);
 | |
|         ptr += (4 + len);
 | |
|     }
 | |
|     return r;
 | |
| }
 | |
| 
 | |
| function bufToArr(b) { var r = []; for (var i = 0; i < b.length; i++) { r.push(b.readUInt8(i)); } return r; } // For unit testing
 | |
| function toUnicode(str) { return Buffer.from(str, 'ucs2'); }
 | |
| function md4(str) { return crypto.createHash('md4').update(str).digest(); }
 | |
| function md5(str) { return crypto.createHash('md5').update(str).digest(); }
 | |
| function hmacmd5(key, data) { return crypto.createHmac('md5', key).update(data).digest(); }
 | |
| function ntowfv2(password, user, domain) { return hmacmd5(md4(toUnicode(password)), toUnicode(user.toUpperCase() + domain)); }
 | |
| function lmowfv2(password, user, domain) { return ntowfv2(password, user, domain); }
 | |
| function zeroBuffer(len) { return Buffer.alloc(len); }
 | |
| function compute_response_v2(response_key_nt, response_key_lm, server_challenge, client_challenge, time, server_name) {
 | |
|     const response_version = Buffer.from('01', 'hex');
 | |
|     const hi_response_version = Buffer.from('01', 'hex');
 | |
|     const temp = Buffer.concat([response_version, hi_response_version, zeroBuffer(6), time, client_challenge, zeroBuffer(4), server_name]);
 | |
|     const nt_proof_str = hmacmd5(response_key_nt, Buffer.concat([server_challenge, temp]));
 | |
|     const nt_challenge_response = Buffer.concat([nt_proof_str, temp]);
 | |
|     const lm_challenge_response = Buffer.concat([hmacmd5(response_key_lm, Buffer.concat([server_challenge, client_challenge])), client_challenge]);
 | |
|     const session_base_key = hmacmd5(response_key_nt, nt_proof_str);
 | |
|     return [nt_challenge_response, lm_challenge_response, session_base_key];
 | |
| }
 | |
| function kx_key_v2(session_base_key, _lm_challenge_response, _server_challenge) { return session_base_key; }
 | |
| function rc4k(key, data) { return crypto.createCipheriv('rc4', key, null).update(data); }
 | |
| 
 | |
| function mac(rc4_handle, signing_key, seq_num, data) {
 | |
|     const buf = Buffer.alloc(4);
 | |
|     buf.writeInt32LE(seq_num, 0);
 | |
|     var signature = hmacmd5(signing_key, Buffer.concat([buf, data]));
 | |
|     return message_signature_ex(rc4_handle.update(signature.slice(0, 8)), seq_num);
 | |
| }
 | |
| 
 | |
| function message_signature_ex(check_sum, seq_num) {
 | |
|     const buf = Buffer.alloc(16);
 | |
|     buf.writeInt32LE(1, 0); // Version
 | |
|     if (check_sum) { check_sum.copy(buf, 4, 0, 8); } // check_sum
 | |
|     if (seq_num) { buf.writeInt32LE(seq_num, 12); } // seq_num
 | |
|     return buf;
 | |
| }
 | |
| 
 | |
| /// Compute a signature of all data exchange during NTLMv2 handshake
 | |
| function mic(exported_session_key, negotiate_message, challenge_message, authenticate_message) { return hmacmd5(exported_session_key, Buffer.concat([negotiate_message, challenge_message, authenticate_message])); }
 | |
| 
 | |
| /// NTLMv2 security interface generate a sign key
 | |
| /// By using MD5 of the session key + a static member (sentense)
 | |
| function sign_key(exported_session_key, is_client) {
 | |
|     if (is_client) {
 | |
|         return md5(Buffer.concat([exported_session_key, Buffer.from("session key to client-to-server signing key magic constant\0")]));
 | |
|     } else {
 | |
|         return md5(Buffer.concat([exported_session_key, Buffer.from("session key to server-to-client signing key magic constant\0")]));
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// NTLMv2 security interface generate a seal key
 | |
| /// By using MD5 of the session key + a static member (sentense)
 | |
| function seal_key(exported_session_key, is_client) {
 | |
|     if (is_client) {
 | |
|         return md5(Buffer.concat([exported_session_key, Buffer.from("session key to client-to-server sealing key magic constant\0")]));
 | |
|     } else {
 | |
|         return md5(Buffer.concat([exported_session_key, Buffer.from("session key to server-to-client sealing key magic constant\0")]));
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// We are now able to build a security interface
 | |
| /// that will be used by the CSSP manager to cipherring message (private keys)
 | |
| /// To detect MITM attack
 | |
| function build_security_interface(ntlm) {
 | |
|     const obj = {};
 | |
|     if (ntlm) {
 | |
|         obj.signing_key = sign_key(ntlm.exported_session_key, true);
 | |
|         obj.verify_key = sign_key(ntlm.exported_session_key, false);
 | |
|         const client_sealing_key = seal_key(ntlm.exported_session_key, true);
 | |
|         const server_sealing_key = seal_key(ntlm.exported_session_key, false);
 | |
|         obj.encrypt = crypto.createCipheriv('rc4', client_sealing_key, null);
 | |
|         obj.decrypt = crypto.createCipheriv('rc4', server_sealing_key, null);
 | |
|     }
 | |
|     obj.seq_num = 0;
 | |
| 
 | |
|     obj.gss_wrapex = function (data) {
 | |
|         const encrypted_data = obj.encrypt.update(data);
 | |
|         const signature = mac(obj.encrypt, obj.signing_key, obj.seq_num, data);
 | |
|         obj.seq_num++;
 | |
|         return Buffer.concat([ signature, encrypted_data ] );
 | |
|     }
 | |
| 
 | |
|     obj.gss_unwrapex = function(data) {
 | |
|         const version = data.readInt32LE(0);
 | |
|         const checksum = data.slice(4, 12);
 | |
|         const seqnum = data.readInt32LE(12);
 | |
|         const payload = data.slice(16);
 | |
|         const plaintext_payload = obj.decrypt.update(payload);
 | |
|         const plaintext_checksum = obj.decrypt.update(checksum);
 | |
|         const seqnumbuf = Buffer.alloc(4);
 | |
|         seqnumbuf.writeInt32LE(seqnum, 0);
 | |
|         const computed_checksum = hmacmd5(obj.verify_key, Buffer.concat([ seqnumbuf, plaintext_payload ])).slice(0, 8);
 | |
|         if (!plaintext_checksum.equals(computed_checksum)) { console.log("Invalid checksum on NTLMv2"); }
 | |
|         return plaintext_payload.toString();
 | |
|     }
 | |
| 
 | |
|     return obj;
 | |
| }
 | |
| 
 | |
| function Create_Ntlm() {
 | |
|     return {
 | |
|         /// Microsoft Domain for Active Directory
 | |
|         domain: "", //String,
 | |
|         /// Username
 | |
|         user: "", //String,
 | |
|         /// Password
 | |
|         password: "", // String,
 | |
|         /// Key generated from NTLM hash
 | |
|         response_key_nt: null, // Buffer
 | |
|         /// Key generated from NTLM hash
 | |
|         response_key_lm: null, // Buffer
 | |
|         /// Keep trace of each messages to compute a final hash
 | |
|         negotiate_message: null, // Buffer
 | |
|         /// Key use to ciphering messages
 | |
|         exported_session_key: crypto.randomBytes(16), // Buffer
 | |
|         /// True if session use unicode
 | |
|         is_unicode: false // Boolean
 | |
|     }
 | |
| }
 | |
| 
 | |
| function authenticate_message(lm_challenge_response, nt_challenge_response, domain, user, workstation, encrypted_random_session_key, flags) {
 | |
|     const payload = Buffer.concat([lm_challenge_response, nt_challenge_response, domain, user, workstation, encrypted_random_session_key]);
 | |
|     const offset = ((flags & NegotiateFlags.NtlmsspNegociateVersion) == 0) ? 80 : 88;
 | |
|     const buf = Buffer.alloc(offset - 16);
 | |
|     buf.write('4e544c4d53535000', 0, 8, 'hex'); // Signature
 | |
|     buf.writeInt32LE(3, 8); // MessageType
 | |
|     buf.writeInt16LE(lm_challenge_response.length, 12); // LmChallengeResponseLen
 | |
|     buf.writeInt16LE(lm_challenge_response.length, 14); // LmChallengeResponseMaxLen
 | |
|     buf.writeInt32LE(offset, 16); // LmChallengeResponseBufferOffset
 | |
|     buf.writeInt16LE(nt_challenge_response.length, 20); // NtChallengeResponseLen
 | |
|     buf.writeInt16LE(nt_challenge_response.length, 22); // NtChallengeResponseMaxLen
 | |
|     buf.writeInt32LE(offset + lm_challenge_response.length, 24); // NtChallengeResponseBufferOffset
 | |
|     buf.writeInt16LE(domain.length, 28); // DomainNameLen
 | |
|     buf.writeInt16LE(domain.length, 30); // DomainNameMaxLen
 | |
|     buf.writeInt32LE(offset + lm_challenge_response.length + nt_challenge_response.length, 32); // DomainNameBufferOffset
 | |
|     buf.writeInt16LE(user.length, 36); // UserNameLen
 | |
|     buf.writeInt16LE(user.length, 38); // UserNameMaxLen
 | |
|     buf.writeInt32LE(offset + lm_challenge_response.length + nt_challenge_response.length + domain.length, 40); // UserNameBufferOffset
 | |
|     buf.writeInt16LE(workstation.length, 44); // WorkstationLen
 | |
|     buf.writeInt16LE(workstation.length, 46); // WorkstationMaxLen
 | |
|     buf.writeInt32LE(offset + lm_challenge_response.length + nt_challenge_response.length + domain.length + user.length, 48); // WorkstationBufferOffset
 | |
|     buf.writeInt16LE(encrypted_random_session_key.length, 52); // EncryptedRandomSessionLen
 | |
|     buf.writeInt16LE(encrypted_random_session_key.length, 54); // EncryptedRandomSessionMaxLen
 | |
|     buf.writeInt32LE(offset + lm_challenge_response.length + nt_challenge_response.length + domain.length + user.length + workstation.length, 56); // EncryptedRandomSessionBufferOffset
 | |
|     buf.writeInt32LE(flags, 60); // NegotiateFlags
 | |
|     if ((flags & NegotiateFlags.NtlmsspNegociateVersion) != 0) {
 | |
|         buf.writeUInt8(MajorVersion.WindowsMajorVersion6, 64); // ProductMajorVersion
 | |
|         buf.writeUInt8(MinorVersion.WindowsMinorVersion0, 65); // ProductMinorVersion
 | |
|         buf.writeInt16LE(6002, 66); // ProductBuild
 | |
|         //buf.writeInt16LE(0, 68); // Reserved
 | |
|         //buf.writeUInt8(0, 70); // Reserved
 | |
|         buf.writeUInt8(NTLMRevision.NtlmSspRevisionW2K3, 71); // NTLMRevisionCurrent
 | |
|     }
 | |
|     return [buf, payload];
 | |
| }
 | |
| 
 | |
| function read_challenge_message(ntlm, derBuffer) {
 | |
|     const headerSignature = derBuffer.slice(0, 8);
 | |
|     if (headerSignature.toString('hex') != '4e544c4d53535000') { console.log('BAD SIGNATURE'); }
 | |
|     const messageType = derBuffer.readInt32LE(8);
 | |
|     if (messageType != 2) { console.log('BAD MESSAGE TYPE'); }
 | |
|     const targetNameLen = derBuffer.readInt16LE(12);
 | |
|     const targetNameLenMax = derBuffer.readInt16LE(14);
 | |
|     const targetNameBufferOffset = derBuffer.readInt32LE(16);
 | |
|     const negotiateFlags = derBuffer.readInt32LE(20);
 | |
|     const serverChallenge = derBuffer.slice(24, 32);
 | |
|     const reserved = derBuffer.slice(32, 40);
 | |
|     if (reserved.toString('hex') != '0000000000000000') { console.log('BAD RESERVED'); }
 | |
|     const targetInfoLen = derBuffer.readInt16LE(40);
 | |
|     const targetInfoLenMax = derBuffer.readInt16LE(42);
 | |
|     const targetInfoBufferOffset = derBuffer.readInt32LE(44);
 | |
|     const targetName = derBuffer.slice(targetNameBufferOffset, targetNameBufferOffset + targetNameLen);
 | |
|     const targetInfo = decodeTargetInfo(derBuffer.slice(targetInfoBufferOffset, targetInfoBufferOffset + targetInfoLen));
 | |
|     const timestamp = targetInfo[7];
 | |
|     if (timestamp == null) { console.log('NO TIMESTAMP'); }
 | |
|     const clientChallenge = crypto.randomBytes(8);
 | |
|     const response_key_nt = ntowfv2(ntlm.password, ntlm.user, ntlm.domain); // Password, Username, Domain
 | |
|     const response_key_lm = lmowfv2(ntlm.password, ntlm.user, ntlm.domain); // Password, Username, Domain
 | |
| 
 | |
|     var resp = compute_response_v2(response_key_nt, response_key_lm, serverChallenge, clientChallenge, timestamp, targetName);
 | |
|     const nt_challenge_response = resp[0];
 | |
|     const lm_challenge_response = resp[1];
 | |
|     const session_base_key = resp[2];
 | |
| 
 | |
|     const key_exchange_key = kx_key_v2(session_base_key, lm_challenge_response, serverChallenge);
 | |
|     const encrypted_random_session_key = rc4k(key_exchange_key, ntlm.exported_session_key);
 | |
| 
 | |
|     ntlm.is_unicode = ((negotiateFlags & 1) != 0)
 | |
|     var xdomain = null;
 | |
|     var xuser = null;
 | |
|     if (ntlm.is_unicode) {
 | |
|         xdomain = toUnicode(ntlm.domain);
 | |
|         xuser = toUnicode(ntlm.user);
 | |
|     } else {
 | |
|         xdomain = Buffer.from(ntlm.domain, 'utf8');
 | |
|         xuser = Buffer.from(ntlm.user, 'utf8');
 | |
|     }
 | |
| 
 | |
|     const auth_message_compute = authenticate_message(lm_challenge_response, nt_challenge_response, xdomain, xuser, zeroBuffer(0), encrypted_random_session_key, negotiateFlags);
 | |
| 
 | |
|     // Write a tmp message to compute MIC and then include it into final message
 | |
|     const tmp_final_auth_message = Buffer.concat([auth_message_compute[0], zeroBuffer(16), auth_message_compute[1]]);
 | |
| 
 | |
|     const signature = mic(ntlm.exported_session_key, ntlm.negotiate_message, derBuffer, tmp_final_auth_message);
 | |
|     return Buffer.concat([auth_message_compute[0], signature, auth_message_compute[1]]);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| // Create create_ts_request
 | |
| const crypto = require('crypto');
 | |
| const forge = require('node-forge');
 | |
| const asn1 = forge.asn1;
 | |
| const pki = forge.pki;
 | |
| const entireBuffer = Buffer.from('3081b2a003020106a181aa3081a73081a4a081a104819e4e544c4d53535000020000000e000e003800000035828a62f2290572b3cac375000000000000000058005800460000000a00614a0000000f430045004e005400520041004c0002000e00430045004e005400520041004c0001000e00430045004e005400520041004c0004000e00430065006e007400720061006c0003000e00430065006e007400720061006c0007000800afbc2c2a9256d80100000000', 'hex').toString('binary');
 | |
| 
 | |
| const ntml = Create_Ntlm();
 | |
| ntml.domain = "";
 | |
| ntml.user = "default";
 | |
| ntml.password = "";
 | |
| ntml.negotiate_message = Buffer.from('4e544c4d53535000010000003582086000000000000000000000000000000000', 'hex');
 | |
| 
 | |
| // We have a full ASN1 data block, decode it now
 | |
| const der = asn1.fromDer(entireBuffer.toString('binary'));
 | |
| const derNum = der.value[0].value[0].value.charCodeAt(0);
 | |
| const derBuffer = Buffer.from(der.value[1].value[0].value[0].value[0].value[0].value, 'binary');
 | |
| const client_challenge = read_challenge_message(ntml, derBuffer);
 | |
| 
 | |
| console.log('client_challenge', client_challenge.toString('hex'));
 | |
| 
 | |
| const NTLMv2SecurityInterface = build_security_interface(ntml);
 | |
| 
 |