NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state, uchar *data, size_t length, uchar *whole_pdu, size_t pdu_length, DATA_BLOB *sig) { if (!(ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) { DEBUG(3, ("NTLMSSP Sealing not negotiated - cannot seal packet!\n")); return NT_STATUS_INVALID_PARAMETER; } if (!ntlmssp_state->session_key.length) { DEBUG(3, ("NO session key, cannot seal packet\n")); return NT_STATUS_NO_USER_SESSION_KEY; } DEBUG(10,("ntlmssp_seal_data: seal\n")); dump_data_pw("ntlmssp clear data\n", data, length); if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { /* The order of these two operations matters - we must first seal the packet, then seal the sequence number - this is becouse the send_seal_hash is not constant, but is is rather updated with each iteration */ NTSTATUS nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, whole_pdu, pdu_length, NTLMSSP_SEND, sig, False); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } arcfour_crypt_sbox(&ntlmssp_state->send_seal_arc4_state, data, length); if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { arcfour_crypt_sbox(&ntlmssp_state->send_seal_arc4_state, sig->data+4, 8); } } else { uint32 crc; crc = crc32_calc_buffer(data, length); if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) { return NT_STATUS_NO_MEMORY; } /* The order of these two operations matters - we must first seal the packet, then seal the sequence number - this is becouse the ntlmv1_arc4_state is not constant, but is is rather updated with each iteration */ dump_arc4_state("ntlmv1 arc4 state:\n", &ntlmssp_state->ntlmv1_arc4_state); arcfour_crypt_sbox(&ntlmssp_state->ntlmv1_arc4_state, data, length); dump_arc4_state("ntlmv1 arc4 state:\n", &ntlmssp_state->ntlmv1_arc4_state); arcfour_crypt_sbox(&ntlmssp_state->ntlmv1_arc4_state, sig->data+4, sig->length-4); ntlmssp_state->ntlmv1_seq_num++; } dump_data_pw("ntlmssp signature\n", sig->data, sig->length); dump_data_pw("ntlmssp sealed data\n", data, length); return NT_STATUS_OK; }
// START FUNC DECL void crc32_I8( unsigned long long *in, long long nR, uint32_t *out ) // STOP FUNC DECL { int sz = sizeof(long long); for ( long long i = 0; i < nR; i++ ) { long long inval = in[i]; const uint8_t *data_ptr = (const uint8_t *)(&inval); uint32_t outval = crc32_calc_buffer(data_ptr, sz); out[i] = outval; } }
static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state, const uchar *data, size_t length, enum ntlmssp_direction direction, DATA_BLOB *sig) { if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { HMACMD5Context ctx; uchar seq_num[4]; uchar digest[16]; SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num); hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx); hmac_md5_update(seq_num, 4, &ctx); hmac_md5_update(data, length, &ctx); hmac_md5_final(digest, &ctx); if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */ , ntlmssp_state->ntlmssp_seq_num)) { return NT_STATUS_NO_MEMORY; } if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { switch (direction) { case NTLMSSP_SEND: NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash, sig->data+4, sig->length-4); break; case NTLMSSP_RECEIVE: NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash, sig->data+4, sig->length-4); break; } } } else { uint32 crc; crc = crc32_calc_buffer((const char *)data, length); if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) { return NT_STATUS_NO_MEMORY; } dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, sizeof(ntlmssp_state->ntlmssp_hash)); NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4); } return NT_STATUS_OK; }
int plf_write_payload(int fileIdx, int sectIndx, const void* buffer, u32 len, u8 compress) { u32 bytes_written; s_plf_file_entry* fileEntry; s_plf_section_entry* sectEntry; PLF_VERIFY_IDX(fileIdx); fileEntry = &plf_files[fileIdx]; if (sectIndx > fileEntry->num_entries || buffer == 0) return PLF_E_PARAM; /* Check if this filentry is writable */ if ( (fileEntry->flags & PLF_FILE_FLAG_WRITE) == 0) return PLF_E_WRITE; /* Check if section previous section is opened */ if ( (fileEntry->flags & PLF_FILE_FLAG_SECTOPEN) == 0) return PLF_E_NOT_OPENED; if (compress != 0) return PLF_E_NOT_IMPLEMENTED; sectEntry = plf_int_get_section(fileIdx, sectIndx); bytes_written = plf_int_write(fileIdx, buffer, fileEntry->current_size, len); if (bytes_written > 0) { u32 num_crc=0; fileEntry->current_size += bytes_written; sectEntry->hdr.dwSectionSize += bytes_written; crc32_calc_buffer(§Entry->hdr.dwCRC32, &num_crc, buffer, bytes_written); } return bytes_written; }
NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state, uchar *data, size_t length, DATA_BLOB *sig) { if (!ntlmssp_state->session_key.length) { DEBUG(3, ("NO session key, cannot seal packet\n")); return NT_STATUS_NO_USER_SESSION_KEY; } DEBUG(10,("ntlmssp_seal_data: seal\n")); dump_data_pw("ntlmssp clear data\n", data, length); if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { HMACMD5Context ctx; char seq_num[4]; uchar digest[16]; SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num); hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx); hmac_md5_update((const unsigned char *)seq_num, 4, &ctx); hmac_md5_update(data, length, &ctx); hmac_md5_final(digest, &ctx); if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */ , ntlmssp_state->ntlmssp_seq_num)) { return NT_STATUS_NO_MEMORY; } dump_data_pw("ntlmssp client sealing hash:\n", ntlmssp_state->send_seal_hash, sizeof(ntlmssp_state->send_seal_hash)); NTLMSSPcalc_ap(ntlmssp_state->send_seal_hash, data, length); dump_data_pw("ntlmssp client signing hash:\n", ntlmssp_state->send_sign_hash, sizeof(ntlmssp_state->send_sign_hash)); NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash, sig->data+4, sig->length-4); } else { uint32 crc; crc = crc32_calc_buffer((const char *)data, length); if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) { return NT_STATUS_NO_MEMORY; } /* The order of these two operations matters - we must first seal the packet, then seal the sequence number - this is becouse the ntlmssp_hash is not constant, but is is rather updated with each iteration */ dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, sizeof(ntlmssp_state->ntlmssp_hash)); NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length); dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, sizeof(ntlmssp_state->ntlmssp_hash)); NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4); } dump_data_pw("ntlmssp sealed data\n", data, length); /* increment counter on send */ ntlmssp_state->ntlmssp_seq_num++; return NT_STATUS_OK; }
WERROR drsuapi_decrypt_attribute_value(TALLOC_CTX *mem_ctx, const DATA_BLOB *gensec_skey, bool rid_crypt, uint32_t rid, DATA_BLOB *in, DATA_BLOB *out) { DATA_BLOB confounder; DATA_BLOB enc_buffer; MD5_CTX md5; uint8_t _enc_key[16]; DATA_BLOB enc_key; DATA_BLOB dec_buffer; uint32_t crc32_given; uint32_t crc32_calc; DATA_BLOB checked_buffer; DATA_BLOB plain_buffer; /* * users with rid == 0 should not exist */ if (rid_crypt && rid == 0) { return WERR_DS_DRA_INVALID_PARAMETER; } /* * the first 16 bytes at the beginning are the confounder * followed by the 4 byte crc32 checksum */ if (in->length < 20) { return WERR_DS_DRA_INVALID_PARAMETER; } confounder = data_blob_const(in->data, 16); enc_buffer = data_blob_const(in->data + 16, in->length - 16); /* * build the encryption key md5 over the session key followed * by the confounder * * here the gensec session key is used and * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! */ enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); MD5Init(&md5); MD5Update(&md5, gensec_skey->data, gensec_skey->length); MD5Update(&md5, confounder.data, confounder.length); MD5Final(enc_key.data, &md5); /* * copy the encrypted buffer part and * decrypt it using the created encryption key using arcfour */ dec_buffer = data_blob_const(enc_buffer.data, enc_buffer.length); arcfour_crypt_blob(dec_buffer.data, dec_buffer.length, &enc_key); /* * the first 4 byte are the crc32 checksum * of the remaining bytes */ crc32_given = IVAL(dec_buffer.data, 0); crc32_calc = crc32_calc_buffer(dec_buffer.data + 4 , dec_buffer.length - 4); checked_buffer = data_blob_const(dec_buffer.data + 4, dec_buffer.length - 4); plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length); W_ERROR_HAVE_NO_MEMORY(plain_buffer.data); if (crc32_given != crc32_calc) { return WERR_SEC_E_DECRYPT_FAILURE; } /* * The following rid_crypt obfuscation isn't session specific * and not really needed here, because we allways know the rid of the * user account. * * some attributes with this 'additional encryption' include * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory * * But for the rest of samba it's easier when we remove this static * obfuscation here */ if (rid_crypt) { uint32_t i, num_hashes; if ((checked_buffer.length % 16) != 0) { return WERR_DS_DRA_INVALID_PARAMETER; } num_hashes = plain_buffer.length / 16; for (i = 0; i < num_hashes; i++) { uint32_t offset = i * 16; sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0); } } *out = plain_buffer; return WERR_OK; }
static WERROR drsuapi_encrypt_attribute_value(TALLOC_CTX *mem_ctx, const DATA_BLOB *gensec_skey, bool rid_crypt, uint32_t rid, DATA_BLOB *in, DATA_BLOB *out) { DATA_BLOB rid_crypt_out = data_blob(NULL, 0); DATA_BLOB confounder; MD5_CTX md5; uint8_t _enc_key[16]; DATA_BLOB enc_key; DATA_BLOB enc_buffer; uint32_t crc32_calc; /* * users with rid == 0 should not exist */ if (rid_crypt && rid == 0) { return WERR_DS_DRA_INVALID_PARAMETER; } /* * The following rid_crypt obfuscation isn't session specific * and not really needed here, because we allways know the rid of the * user account. * * some attributes with this 'additional encryption' include * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory * * But for the rest of samba it's easier when we remove this static * obfuscation here */ if (rid_crypt) { uint32_t i, num_hashes; rid_crypt_out = data_blob_talloc(mem_ctx, in->data, in->length); W_ERROR_HAVE_NO_MEMORY(rid_crypt_out.data); if ((rid_crypt_out.length % 16) != 0) { return WERR_DS_DRA_INVALID_PARAMETER; } num_hashes = rid_crypt_out.length / 16; for (i = 0; i < num_hashes; i++) { uint32_t offset = i * 16; sam_rid_crypt(rid, in->data + offset, rid_crypt_out.data + offset, 1); } in = &rid_crypt_out; } /* * the first 16 bytes at the beginning are the confounder * followed by the 4 byte crc32 checksum */ enc_buffer = data_blob_talloc(mem_ctx, NULL, in->length+20); if (!enc_buffer.data) { talloc_free(rid_crypt_out.data); return WERR_NOMEM; }; confounder = data_blob_const(enc_buffer.data, 16); generate_random_buffer(confounder.data, confounder.length); /* * build the encryption key md5 over the session key followed * by the confounder * * here the gensec session key is used and * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! */ enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); MD5Init(&md5); MD5Update(&md5, gensec_skey->data, gensec_skey->length); MD5Update(&md5, confounder.data, confounder.length); MD5Final(enc_key.data, &md5); /* * the first 4 byte are the crc32 checksum * of the remaining bytes */ crc32_calc = crc32_calc_buffer(in->data, in->length); SIVAL(enc_buffer.data, 16, crc32_calc); /* * copy the plain buffer part and * encrypt it using the created encryption key using arcfour */ memcpy(enc_buffer.data+20, in->data, in->length); talloc_free(rid_crypt_out.data); arcfour_crypt_blob(enc_buffer.data+16, enc_buffer.length-16, &enc_key); *out = enc_buffer; return WERR_OK; }
BOOL create_next_pdu(pipes_struct *p) { RPC_HDR_RESP hdr_resp; BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0); BOOL auth_seal = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0); uint32 ss_padding_len = 0; uint32 data_len; uint32 data_space_available; uint32 data_len_left; prs_struct outgoing_pdu; uint32 data_pos; /* * If we're in the fault state, keep returning fault PDU's until * the pipe gets closed. JRA. */ if(p->fault_state) { setup_fault_pdu(p, NT_STATUS(0x1c010002)); return True; } memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); /* Change the incoming request header to a response. */ p->hdr.pkt_type = RPC_RESPONSE; /* Set up rpc header flags. */ if (p->out_data.data_sent_length == 0) { p->hdr.flags = RPC_FLG_FIRST; } else { p->hdr.flags = 0; } /* * Work out how much we can fit in a single PDU. */ data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; if(p->ntlmssp_auth_validated) { data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN); } else if(p->netsec_auth_validated) { data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN); } /* * The amount we send is the minimum of the available * space and the amount left to send. */ data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; /* * Ensure there really is data left to send. */ if(!data_len_left) { DEBUG(0,("create_next_pdu: no data left to send !\n")); return False; } data_len = MIN(data_len_left, data_space_available); /* * Set up the alloc hint. This should be the data left to * send. */ hdr_resp.alloc_hint = data_len_left; /* * Work out if this PDU will be the last. */ if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { p->hdr.flags |= RPC_FLG_LAST; if ((auth_seal || auth_verify) && (data_len_left % 8)) { ss_padding_len = 8 - (data_len_left % 8); DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n", ss_padding_len )); } } /* * Set up the header lengths. */ if (p->ntlmssp_auth_validated) { p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN; p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; } else if (p->netsec_auth_validated) { p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN; p->hdr.auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN; } else { p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len; p->hdr.auth_len = 0; } /* * Init the parse struct to point at the outgoing * data. */ prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* Store the header in the data stream. */ if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR.\n")); prs_mem_free(&outgoing_pdu); return False; } if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_RESP.\n")); prs_mem_free(&outgoing_pdu); return False; } /* Store the current offset. */ data_pos = prs_offset(&outgoing_pdu); /* Copy the data into the PDU. */ if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) { DEBUG(0,("create_next_pdu: failed to copy %u bytes of data.\n", (unsigned int)data_len)); prs_mem_free(&outgoing_pdu); return False; } /* Copy the sign/seal padding data. */ if (ss_padding_len) { char pad[8]; memset(pad, '\0', 8); if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) { DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); prs_mem_free(&outgoing_pdu); return False; } } if (p->ntlmssp_auth_validated) { /* * NTLMSSP processing. Mutually exclusive with Schannel. */ uint32 crc32 = 0; char *data; DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n", BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len)); /* * Set data to point to where we copied the data into. */ data = prs_data_p(&outgoing_pdu) + data_pos; if (auth_seal) { crc32 = crc32_calc_buffer(data, data_len + ss_padding_len); NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len); } if (auth_seal || auth_verify) { RPC_HDR_AUTH auth_info; init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL, (auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0)); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&outgoing_pdu); return False; } } if (auth_verify) { RPC_AUTH_NTLMSSP_CHK ntlmssp_chk; char *auth_data = prs_data_p(&outgoing_pdu); p->ntlmssp_seq_num++; init_rpc_auth_ntlmssp_chk(&ntlmssp_chk, NTLMSSP_SIGN_VERSION, crc32, p->ntlmssp_seq_num++); auth_data = prs_data_p(&outgoing_pdu) + prs_offset(&outgoing_pdu) + 4; if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_AUTH_NTLMSSP_CHK.\n")); prs_mem_free(&outgoing_pdu); return False; } NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4); } } else if (p->netsec_auth_validated) { /* * Schannel processing. Mutually exclusive with NTLMSSP. */ int auth_type, auth_level; char *data; RPC_HDR_AUTH auth_info; RPC_AUTH_NETSEC_CHK verf; prs_struct rverf; prs_struct rauth; data = prs_data_p(&outgoing_pdu) + data_pos; /* Check it's the type of reply we were expecting to decode */ get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level); init_rpc_hdr_auth(&auth_info, auth_type, auth_level, ss_padding_len, 1); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&outgoing_pdu); return False; } prs_init(&rverf, 0, p->mem_ctx, MARSHALL); prs_init(&rauth, 0, p->mem_ctx, MARSHALL); netsec_encode(&p->netsec_auth, p->netsec_auth.auth_flags, SENDER_IS_ACCEPTOR, &verf, data, data_len + ss_padding_len); smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, &verf, &outgoing_pdu, 0); p->netsec_auth.seq_num++; } /* * Setup the counts for this PDU. */ p->out_data.data_sent_length += data_len; p->out_data.current_pdu_len = p->hdr.frag_len; p->out_data.current_pdu_sent = 0; prs_mem_free(&outgoing_pdu); return True; }
DATA_BLOB decrypt_drsuapi_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *session_key, bool rcrypt, uint32_t rid, const DATA_BLOB *buffer) { DATA_BLOB confounder; DATA_BLOB enc_buffer; struct MD5Context md5; uint8_t _enc_key[16]; DATA_BLOB enc_key; DATA_BLOB dec_buffer; uint32_t crc32_given; uint32_t crc32_calc; DATA_BLOB checked_buffer; DATA_BLOB plain_buffer; /* * the combination "c[3] s[1] e[1] d[0]..." * was successful!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* * the first 16 bytes at the beginning are the confounder * followed by the 4 byte crc32 checksum */ if (buffer->length < 20) { return data_blob_const(NULL, 0); } confounder = data_blob_const(buffer->data, 16); enc_buffer = data_blob_const(buffer->data + 16, buffer->length - 16); /* * build the encryption key md5 over the session key followed * by the confounder * * here the gensec session key is used and * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! */ enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); MD5Init(&md5); MD5Update(&md5, session_key->data, session_key->length); MD5Update(&md5, confounder.data, confounder.length); MD5Final(enc_key.data, &md5); /* * copy the encrypted buffer part and * decrypt it using the created encryption key using arcfour */ dec_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length); if (!dec_buffer.data) { return data_blob_const(NULL, 0); } SamOEMhashBlob(dec_buffer.data, dec_buffer.length, &enc_key); /* * the first 4 byte are the crc32 checksum * of the remaining bytes */ crc32_given = IVAL(dec_buffer.data, 0); crc32_calc = crc32_calc_buffer((const char *)dec_buffer.data + 4 , dec_buffer.length - 4); if (crc32_given != crc32_calc) { DEBUG(1,("CRC32: given[0x%08X] calc[0x%08X]\n", crc32_given, crc32_calc)); return data_blob_const(NULL, 0); } checked_buffer = data_blob_talloc(mem_ctx, dec_buffer.data + 4, dec_buffer.length - 4); if (!checked_buffer.data) { return data_blob_const(NULL, 0); } /* * some attributes seem to be in a usable form after this decryption * (supplementalCredentials, priorValue, currentValue, trustAuthOutgoing, * trustAuthIncoming, initialAuthOutgoing, initialAuthIncoming) * At least supplementalCredentials contains plaintext * like "Primary:Kerberos" (in unicode form) * * some attributes seem to have some additional encryption * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory * * it's the sam_rid_crypt() function, as the value is constant, * so it doesn't depend on sessionkeys. */ if (rcrypt) { uint32_t i, num_hashes; if ((checked_buffer.length % 16) != 0) { return data_blob_const(NULL, 0); } plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length); if (!plain_buffer.data) { return data_blob_const(NULL, 0); } num_hashes = plain_buffer.length / 16; for (i = 0; i < num_hashes; i++) { uint32_t offset = i * 16; sam_pwd_hash(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0); } } else { plain_buffer = checked_buffer; } return plain_buffer; }
static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state, const uchar *data, size_t length, const uchar *whole_pdu, size_t pdu_length, enum ntlmssp_direction direction, DATA_BLOB *sig, bool encrypt_sig) { if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { HMACMD5Context ctx; uchar seq_num[4]; uchar digest[16]; *sig = data_blob(NULL, NTLMSSP_SIG_SIZE); if (!sig->data) { return NT_STATUS_NO_MEMORY; } switch (direction) { case NTLMSSP_SEND: DEBUG(100,("ntlmssp_make_packet_signature: SEND seq = %u, len = %u, pdu_len = %u\n", ntlmssp_state->ntlm2_send_seq_num, (unsigned int)length, (unsigned int)pdu_length)); SIVAL(seq_num, 0, ntlmssp_state->ntlm2_send_seq_num); ntlmssp_state->ntlm2_send_seq_num++; hmac_md5_init_limK_to_64(ntlmssp_state->send_sign_key, 16, &ctx); break; case NTLMSSP_RECEIVE: DEBUG(100,("ntlmssp_make_packet_signature: RECV seq = %u, len = %u, pdu_len = %u\n", ntlmssp_state->ntlm2_recv_seq_num, (unsigned int)length, (unsigned int)pdu_length)); SIVAL(seq_num, 0, ntlmssp_state->ntlm2_recv_seq_num); ntlmssp_state->ntlm2_recv_seq_num++; hmac_md5_init_limK_to_64(ntlmssp_state->recv_sign_key, 16, &ctx); break; } dump_data_pw("pdu data ", whole_pdu, pdu_length); hmac_md5_update(seq_num, 4, &ctx); hmac_md5_update(whole_pdu, pdu_length, &ctx); hmac_md5_final(digest, &ctx); if (encrypt_sig && (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { switch (direction) { case NTLMSSP_SEND: arcfour_crypt_sbox(&ntlmssp_state->send_seal_arc4_state, digest, 8); break; case NTLMSSP_RECEIVE: arcfour_crypt_sbox(&ntlmssp_state->recv_seal_arc4_state, digest, 8); break; } } SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION); memcpy(sig->data + 4, digest, 8); memcpy(sig->data + 12, seq_num, 4); dump_data_pw("ntlmssp v2 sig ", sig->data, sig->length); } else { uint32 crc; crc = crc32_calc_buffer(data, length); if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) { return NT_STATUS_NO_MEMORY; } ntlmssp_state->ntlmv1_seq_num++; dump_arc4_state("ntlmssp hash: \n", &ntlmssp_state->ntlmv1_arc4_state); arcfour_crypt_sbox(&ntlmssp_state->ntlmv1_arc4_state, sig->data+4, sig->length-4); } return NT_STATUS_OK; }
int plf_check_crc(int fileIdx, int sectIdx) { u32 crc_accum = 0; u32 crc_num_size = 0; s_plf_section_entry* section; s_plf_file_entry* fileEntry; PLF_VERIFY_IDX(fileIdx); section = plf_int_get_section(fileIdx, sectIdx); fileEntry = &plf_files[fileIdx]; if (section == 0) return PLF_E_PARAM; if (fileEntry->fildes == -1) { // Buffer case crc32_calc_buffer(&crc_accum, &crc_num_size, (((u8*) fileEntry->buffer) + section->offset), section->hdr.dwSectionSize); crc32_calc_dw(&crc_accum, &crc_num_size); } else { // File case.. we need to read the contents of the file u8* tmpBuf = (u8*) malloc(0x1000); if (tmpBuf == 0) return PLF_E_MEM; u32 bytes_remaining = section->hdr.dwSectionSize; while (bytes_remaining > 0) { u32 read_len; if (bytes_remaining > 0x1000) { read_len = 0x1000; } else { read_len = bytes_remaining; } u32 offset = section->hdr.dwSectionSize - bytes_remaining; u32 bytes_read = plf_get_payload_raw(fileIdx, sectIdx, tmpBuf, offset, read_len); if (bytes_read < 0) { free(tmpBuf); return bytes_read; } crc32_calc_buffer(&crc_accum, &crc_num_size, tmpBuf, read_len); bytes_remaining -= read_len; } // finish crc free(tmpBuf); crc32_calc_dw(&crc_accum, &crc_num_size); } if (crc_accum == section->hdr.dwCRC32) return 0; else return PLF_E_CRC; }