All, Attached is a patch which essentially provides a forward port of Nessus's old LM/NTLM et al routines for SMB (with some minor changes to use GNU TLS where possible). These were taken from a Nessus 2.0.9 tar ball I had to hand. They seem broken but if we merge this patch at least we'll have a starting point to fix whatever bugs may exist. I'll take a further look when I get a chance but in the meantime if anyone wants to have a play, feel free.
Cheers, Tim -- Tim Brown <mailto:t...@nth-dimension.org.uk> <http://www.nth-dimension.org.uk/>
Index: nasl/Makefile =================================================================== --- nasl/Makefile (revision 2952) +++ nasl/Makefile (working copy) @@ -36,6 +36,10 @@ nasl_socket.o \ nasl_crypto.o \ nasl_crypto2.o \ + smb_crypt.o \ + smb_crypt2.o \ + hmacmd5.o \ + md5.o \ nasl_http.o \ nasl_host.o \ nasl_text_utils.o \ @@ -63,6 +67,10 @@ nasl_socket.lo \ nasl_crypto.lo \ nasl_crypto2.lo \ + smb_crypt.lo \ + smb_crypt2.lo \ + hmacmd5.lo \ + md5.lo \ nasl_http.lo \ nasl_host.lo \ nasl_text_utils.lo \ Index: nasl/nasl_crypto.c =================================================================== --- nasl/nasl_crypto.c (revision 2952) +++ nasl/nasl_crypto.c (working copy) @@ -30,7 +30,8 @@ #include "nasl_var.h" #include "nasl_lex_ctxt.h" #include "exec.h" - +#include "nasl_crypto.h" +#include "hmacmd5.h" #include "nasl_debug.h" #include "strutils.h" @@ -92,6 +93,12 @@ } tree_cell * +nasl_md2(lex_ctxt * lexic) +{ + return nasl_hash(lexic, GCRY_MD_MD2); +} + +tree_cell * nasl_md4(lex_ctxt * lexic) { return nasl_hash(lexic, GCRY_MD_MD4); @@ -103,10 +110,34 @@ return nasl_hash(lexic, GCRY_MD_MD5); } +tree_cell * nasl_sha(lex_ctxt * lexic) +{ + /* BROKEN + char * data = get_str_var_by_num(lexic, 0); + int len = get_var_size_by_num(lexic, 0); + char md[SHA_DIGEST_LENGTH+1]; + tree_cell * retc; + + if(data == NULL) + return NULL; + + SHA(data, len, md); + + retc = alloc_tree_cell(0, NULL); + retc->type = CONST_DATA; + retc->x.str_val = strndup(md, SHA_DIGEST_LENGTH); + retc->size = SHA_DIGEST_LENGTH; + return retc; + */ + return NULL; +} + + tree_cell * nasl_sha1(lex_ctxt * lexic) { return nasl_hash(lexic, GCRY_MD_SHA1); + return NULL; } @@ -116,13 +147,8 @@ return nasl_hash(lexic, GCRY_MD_RMD160); } - - - /*-------------------[ HMAC ]-------------------------------------*/ - - static tree_cell * nasl_hmac(lex_ctxt * lexic, int algorithm) { @@ -134,6 +160,11 @@ return nasl_gcrypt_hash(lexic, algorithm, data, data_len, key, key_len); } +tree_cell * +nasl_hmac_md2(lex_ctxt * lexic) +{ + return nasl_hmac(lexic, GCRY_MD_MD2); +} tree_cell * nasl_hmac_md5(lex_ctxt * lexic) @@ -147,8 +178,256 @@ return nasl_hmac(lexic, GCRY_MD_SHA1); } + +tree_cell * nasl_hmac_dss(lex_ctxt * lexic) +{ + /* BROKEN + return nasl_hmac(lexic, EVP_dss()); + */ + return NULL; +} + tree_cell * nasl_hmac_ripemd160(lex_ctxt * lexic) { return nasl_hmac(lexic, GCRY_MD_RMD160); } + +/*-------------------[ Windows ]-------------------------------------*/ + +tree_cell * nasl_ntlmv1_hash(lex_ctxt * lexic) +{ + char * cryptkey = get_str_var_by_name(lexic, "cryptkey"); + char * password = get_str_var_by_name(lexic, "passhash"); + int pass_len = get_var_size_by_name(lexic, "passhash"); + unsigned char p21[21]; + tree_cell * retc; + char * ret; + + if(cryptkey == NULL || password == NULL ) + { + nasl_perror(lexic, "Syntax : ntlmv1_hash(cryptkey:<c>, passhash:<p>)\n"); + return NULL; + } + + bzero(p21, sizeof(p21)); + memcpy(p21, password, pass_len < 16 ? pass_len : 16); + + ret = emalloc(24); + + E_P24(p21, cryptkey, ret); + retc = alloc_tree_cell(0, NULL); + retc->type = CONST_DATA; + retc->size = 24; + retc->x.str_val = ret; + + return retc; +} + +tree_cell * nasl_nt_owf_gen(lex_ctxt * lexic) +{ + char * pass = get_str_var_by_num(lexic, 0); + int pass_len = get_var_size_by_num(lexic, 0); + tree_cell * retc; + char md[MD4_DIGEST_LENGTH+1]; + char pwd[130]; + short upwd[130], * dst; + short val; + char * src; + + int i; + + if(pass_len < 0 || pass == NULL ) + { + nasl_perror(lexic, "Syntax : nt_owf_gen(cryptkey:<c>, password:<p>)\n"); + return NULL; + } + + dst = upwd; + src = pass; + for(i = 0 ; i < pass_len ; i ++) + { + val = *src; +#if __BYTE_ORDER == __BIG_ENDIAN + *dst = val << 8; +#else + *dst = val; +#endif + dst ++; + src ++; + if(val == 0) + break; + } + + bzero(pwd, sizeof(pwd)); + memcpy(pwd, upwd, sizeof(pwd) < pass_len * 2 ? sizeof(pwd) : pass_len * 2); + nasl_gcrypt_hash(lexic, GCRY_MD_MD4, pwd, pass_len * 2 > 128 ? 128 : pass_len * 2, md, MD4_DIGEST_LENGTH+1); + + retc = alloc_tree_cell(0, NULL); + retc->type = CONST_DATA; + retc->size = 16; + retc->x.str_val = strndup(md, 16); + return retc; +} + +tree_cell * nasl_lm_owf_gen(lex_ctxt * lexic) +{ + char * pass = get_str_var_by_num(lexic, 0); + int pass_len = get_var_size_by_num(lexic, 0); + tree_cell * retc; + char pwd[15]; + char p16[16]; + int i; + + + if(pass_len < 0 || pass == NULL ) + { + nasl_perror(lexic, "Syntax : nt_lm_gen(cryptkey:<c>, password:<p>)\n"); + return NULL; + } + + bzero(pwd, sizeof(pwd)); + strncpy(pwd, pass, sizeof(pwd) - 1); + for(i=0;i<sizeof(pwd);i++)pwd[i] = toupper(pwd[i]); + + E_P16(pwd, p16); + + + retc = alloc_tree_cell(0, NULL); + retc->type = CONST_DATA; + retc->size = 16; + retc->x.str_val = strndup(p16, 16); + return retc; +} + +/* Does both the NTLMv2 owfs of a user's password */ +tree_cell * nasl_ntv2_owf_gen(lex_ctxt * lexic) +{ + char *owf_in = get_str_var_by_name(lexic, "owf"); + int owf_in_len = get_var_size_by_name(lexic, "owf"); + char *user_in = get_str_var_by_name(lexic, "login"); + int user_in_len = get_var_size_by_name(lexic, "login"); + char *domain_in = get_str_var_by_name(lexic, "domain"); + int domain_len = get_var_size_by_name(lexic, "domain"); + char *src_user, *src_domain; + smb_ucs2_t *user, *dst_user, val_user; + smb_ucs2_t *domain, *dst_domain, val_domain; + int i; + size_t user_byte_len; + size_t domain_byte_len; + tree_cell * retc; + char * kr_buf; + HMACMD5Context ctx; + + if(owf_in_len<0 || owf_in == NULL || user_in_len<0 || user_in == NULL || domain_len<0 || domain_in==NULL) + { + nasl_perror(lexic, "Syntax : ntv2_owf_gen(owf:<o>, login:<l>, domain:<d>)\n"); + return NULL; + } + + assert(owf_in_len==16); + + user_byte_len=sizeof(smb_ucs2_t)*(strlen(user_in)+1); + user = emalloc(user_byte_len); + dst_user = user; + src_user = user_in; + for(i = 0 ; i < user_in_len ; i ++) + { + val_user = *src_user; + *dst_user = val_user; + dst_user ++; + src_user ++; + if(val_user == 0) + break; + } + + domain_byte_len=sizeof(smb_ucs2_t)*(strlen(domain_in)+1); + domain = emalloc(domain_byte_len); + dst_domain = domain; + src_domain = domain_in; + for(i = 0 ; i < domain_len ; i ++) + { + val_domain = *src_domain; + *dst_domain = val_domain; + + dst_domain ++; + src_domain ++; + if(val_domain == 0) + break; + } + + strupper_w(user); + strupper_w(domain); + + assert(user_byte_len >= 2); + assert(domain_byte_len >= 2); + + /* We don't want null termination */ + user_byte_len = user_byte_len - 2; + domain_byte_len = domain_byte_len - 2; + + kr_buf=emalloc(16); + + hmac_md5_init_limK_to_64(owf_in, 16, &ctx); + hmac_md5_update((const unsigned char *)user, user_byte_len, &ctx); + hmac_md5_update((const unsigned char *)domain, domain_byte_len, &ctx); + hmac_md5_final(kr_buf, &ctx); + + efree(&user); + efree(&domain); + + retc = alloc_tree_cell(0, NULL); + retc->type = CONST_DATA; + retc->size = 16; + retc->x.str_val = kr_buf; + + return retc; +} + +tree_cell * nasl_ntlmv2_hash(lex_ctxt * lexic) +{ + char * server_chal = get_str_var_by_name(lexic, "cryptkey"); + int sc_len = get_var_size_by_name(lexic, "cryptkey"); + char * ntlm_v2_hash = get_str_var_by_name(lexic, "passhash"); + int hash_len = get_var_size_by_name(lexic, "passhash"); + int client_chal_length = get_int_var_by_name(lexic, "length", -1); + tree_cell * retc; + unsigned char ntlmv2_response[16]; + unsigned char* ntlmv2_client_data=NULL; + unsigned char* final_response; + int i; + + if(sc_len<0 || server_chal == NULL || hash_len<0 || ntlm_v2_hash == NULL || client_chal_length<0) + { + nasl_perror(lexic, "Syntax : ntlmv2_hash(cryptkey:<c>, passhash:<p>, length:<l>)\n"); + return NULL; + } + + /* NTLMv2 */ + + /* We also get to specify some random data */ + ntlmv2_client_data = emalloc(client_chal_length); + for(i=0;i<client_chal_length;i++) + ntlmv2_client_data[i] = rand() % 256; + + + + assert(hash_len==16); + /* Given that data, and the challenge from the server, generate a response */ + SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, 8, ntlmv2_client_data, client_chal_length, ntlmv2_response); + + /* put it into nt_response, for the code below to put into the packet */ + final_response = emalloc(client_chal_length + sizeof(ntlmv2_response)); + memcpy(final_response, ntlmv2_response, sizeof(ntlmv2_response)); + /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */ + memcpy(final_response + sizeof(ntlmv2_response), ntlmv2_client_data, client_chal_length); + + efree(&ntlmv2_client_data); + + retc = alloc_tree_cell(0, NULL); + retc->type = CONST_DATA; + retc->size = client_chal_length + sizeof(ntlmv2_response); + retc->x.str_val = final_response; + + return retc; +} Index: nasl/nasl_crypto.h =================================================================== --- nasl/nasl_crypto.h (revision 2952) +++ nasl/nasl_crypto.h (working copy) @@ -20,12 +20,23 @@ #ifndef NASL_CRYPTO_H #define NASL_CRYPTO_H +#define MD4_DIGEST_LENGTH 16 + +tree_cell * nasl_md2(lex_ctxt *); tree_cell * nasl_md4(lex_ctxt *); tree_cell * nasl_md5(lex_ctxt *); +tree_cell * nasl_sha(lex_ctxt *); tree_cell * nasl_sha1(lex_ctxt *); tree_cell * nasl_ripemd160(lex_ctxt *); -tree_cell * nasl_hmac_md5(lex_ctxt * ); -tree_cell * nasl_hmac_sha1(lex_ctxt * ); +tree_cell * nasl_hmac_md2(lex_ctxt *); +tree_cell * nasl_hmac_md5(lex_ctxt *); +tree_cell * nasl_hmac_sha1(lex_ctxt *); +tree_cell * nasl_hmac_dss(lex_ctxt *); tree_cell * nasl_hmac_ripemd160(lex_ctxt *); +tree_cell * nasl_ntlmv1_hash(lex_ctxt *); +tree_cell * nasl_nt_owf_gen(lex_ctxt *); +tree_cell * nasl_lm_owf_gen(lex_ctxt *); +tree_cell * nasl_ntv2_owf_gen(lex_ctxt *); +tree_cell * nasl_ntlmv2_hash(lex_ctxt *); #endif Index: nasl/nasl_init.c =================================================================== --- nasl/nasl_init.c (revision 2952) +++ nasl/nasl_init.c (working copy) @@ -255,14 +255,22 @@ { "send_capture", nasl_send_capture, 1, { "data", "interface", "length", "option", "pcap_filter", "socket", "timeout", NULL} }, + { "MD2", nasl_md2, 1, { NULL } }, { "MD4", nasl_md4, 1, { NULL } }, { "MD5", nasl_md5, 1, { NULL } }, + /* BROKEN { "SHA", nasl_sha, 1, { NULL } }, */ { "SHA1", nasl_sha1, 1, { NULL } }, { "RIPEMD160", nasl_ripemd160, 1, { NULL } }, + { "HMAC_MD2", nasl_hmac_md2, 0, { "data", "key", NULL } }, { "HMAC_MD5", nasl_hmac_md5, 0, { "data", "key", NULL } }, { "HMAC_SHA1", nasl_hmac_sha1, 0, { "data", "key", NULL } }, - + /* BROKEN { "HMAC_DSS", nasl_hmac_dss, 0, { "data", "key", NULL } }, */ { "HMAC_RIPEMD160", nasl_hmac_ripemd160, 0, { "data", "key", NULL } }, + { "NTLMv1_HASH", nasl_ntlmv1_hash, 0, {"cryptkey", "passhash", NULL } }, + { "NTLMv2_HASH", nasl_ntlmv2_hash, 0, {"cryptkey", "length", "passhash", NULL } }, + { "nt_owf_gen", nasl_nt_owf_gen, 1, { NULL } }, + { "lm_owf_gen", nasl_lm_owf_gen, 1, { NULL } }, + { "ntv2_owf_gen", nasl_ntv2_owf_gen, 0, {"domain", "login", "owf", NULL } }, { "dh_generate_key", nasl_dh_generate_key, 0, { "g" , "p", "priv", NULL } }, { "bn_random", nasl_bn_random, 0, { "need", NULL } }, { "bn_cmp", nasl_bn_cmp, 0, { "key1", "key2", NULL } }, Index: nasl/smb_crypt2.c =================================================================== --- nasl/smb_crypt2.c (revision 0) +++ nasl/smb_crypt2.c (revision 0) @@ -0,0 +1,95 @@ +/* + Unix SMB/CIFS implementation. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1998 + Modified by Jeremy Allison 1995. + Copyright (C) Jeremy Allison 1995-2000. + Copyright (C) Luke Kennethc Casson Leighton 1996-2000. + Copyright (C) Andrew Bartlett <abart...@samba.org> 2002-2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <includes.h> +#include "hmacmd5.h" + + +/******************************************************************* + Convert a wchar to upper case. +********************************************************************/ + +smb_ucs2_t toupper_w(smb_ucs2_t val) +{ + return UCS2_CHAR(islower(val)?toupper(val):val); +} + +/******************************************************************* + Convert a string to upper case. + return True if any char is converted +********************************************************************/ +int strupper_w(smb_ucs2_t *s) +{ + int ret = 0; + while (*s) { + smb_ucs2_t v = toupper_w(*s); + if (v != *s) { + *s = v; + ret = 1; + } + s++; + } + return ret; +} + +/* Does the md5 encryption from the NT hash for NTLMv2. */ +void SMBOWFencrypt_ntv2(const uchar* kr, + const uchar* srv_chal_data, + int srv_chal_len, + const uchar* cli_chal_data, + int cli_chal_len, + uchar resp_buf[16]) +{ + HMACMD5Context ctx; + + hmac_md5_init_limK_to_64(kr, 16, &ctx); + hmac_md5_update(srv_chal_data, srv_chal_len, &ctx); + hmac_md5_update(cli_chal_data, cli_chal_len, &ctx); + hmac_md5_final(resp_buf, &ctx); +} + + + +/* Example: + +-smb_session_setup_NTLMv1() + +- if(pawword) +- { +- NT_H = nt_owf_gen(password); +- LM_H = lm_owf_gen(password); +- +- lm = NTLMv1_HASH(cryptkey:cs, passhash:LM_H); +- nt = NTLMv1_HASH(cryptkey:cs, passhash:NT_H); + ++smb_session_setup_NTLMv2() + ++ if(password) { ++ nt_hash = nt_owf_gen(password); ++ ntlm_v2_hash = ntv2_owf_gen(owf:nt_hash,login:login,domain:domain); ++ lm= NTLMv2_HASH(cryptkey:cs, passhash:ntlm_v2_hash, length:8); ++ nt= NTLMv2_HASH(cryptkey:cs, passhash:ntlm_v2_hash, length:64); ++ } + +*/ Index: nasl/smb_crypt.c =================================================================== --- nasl/smb_crypt.c (revision 0) +++ nasl/smb_crypt.c (revision 0) @@ -0,0 +1,419 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + + a partial implementation of DES designed for use in the + SMB authentication protocol + + Copyright (C) Andrew Tridgell 1998-2000 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* NOTES: + + This code makes no attempt to be fast! In fact, it is a very + slow implementation + + This code is NOT a complete DES implementation. It implements only + the minimum necessary for SMB authentication, as used by all SMB + products (including every copy of Microsoft Windows95 ever sold) + + In particular, it can only do a unchained forward DES pass. This + means it is not possible to use this code for encryption/decryption + of data, instead it is only useful as a "hash" algorithm. + + There is no entry point into this code that allows normal DES operation. + + I believe this means that this code does not come under ITAR + regulations but this is NOT a legal opinion. If you are concerned + about the applicability of ITAR regulations to this code then you + should confirm it for yourself (and maybe let me know if you come + up with a different answer to the one above) +*/ + + +#define uchar unsigned char + +static const uchar perm1[56] = {57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4}; + +static const uchar perm2[48] = {14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32}; + +static const uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7}; + +static const uchar perm4[48] = { 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1}; + +static const uchar perm5[32] = { 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25}; + + +static const uchar perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25}; + + +static const uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}; + +static const uchar sbox[8][4][16] = { + {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, + {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, + {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, + {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}}, + + {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, + {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, + {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, + {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}}, + + {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, + {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, + {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, + {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}}, + + {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, + {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, + {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, + {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}}, + + {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, + {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, + {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, + {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}}, + + {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, + {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, + {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, + {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}}, + + {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, + {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, + {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, + {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}}, + + {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, + {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, + {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, + {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}}; + +static void permute(char *out, char *in, const uchar *p, int n) +{ + int i; + for (i=0;i<n;i++) + out[i] = in[p[i]-1]; +} + +static void lshift(char *d, int count, int n) +{ + char out[64]; + int i; + for (i=0;i<n;i++) + out[i] = d[(i+count)%n]; + for (i=0;i<n;i++) + d[i] = out[i]; +} + +static void concat(char *out, char *in1, char *in2, int l1, int l2) +{ + while (l1--) + *out++ = *in1++; + while (l2--) + *out++ = *in2++; +} + +static void xor(char *out, char *in1, char *in2, int n) +{ + int i; + for (i=0;i<n;i++) + out[i] = in1[i] ^ in2[i]; +} + +static void dohash(char *out, char *in, char *key, int forw) +{ + int i, j, k; + char pk1[56]; + char c[28]; + char d[28]; + char cd[56]; + char ki[16][48]; + char pd1[64]; + char l[32], r[32]; + char rl[64]; + + permute(pk1, key, perm1, 56); + + for (i=0;i<28;i++) + c[i] = pk1[i]; + for (i=0;i<28;i++) + d[i] = pk1[i+28]; + + for (i=0;i<16;i++) { + lshift(c, sc[i], 28); + lshift(d, sc[i], 28); + + concat(cd, c, d, 28, 28); + permute(ki[i], cd, perm2, 48); + } + + permute(pd1, in, perm3, 64); + + for (j=0;j<32;j++) { + l[j] = pd1[j]; + r[j] = pd1[j+32]; + } + + for (i=0;i<16;i++) { + char er[48]; + char erk[48]; + char b[8][6]; + char cb[32]; + char pcb[32]; + char r2[32]; + + permute(er, r, perm4, 48); + + xor(erk, er, ki[forw ? i : 15 - i], 48); + + for (j=0;j<8;j++) + for (k=0;k<6;k++) + b[j][k] = erk[j*6 + k]; + + for (j=0;j<8;j++) { + int m, n; + m = (b[j][0]<<1) | b[j][5]; + + n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4]; + + for (k=0;k<4;k++) + b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0; + } + + for (j=0;j<8;j++) + for (k=0;k<4;k++) + cb[j*4+k] = b[j][k]; + permute(pcb, cb, perm5, 32); + + xor(r2, l, pcb, 32); + + for (j=0;j<32;j++) + l[j] = r[j]; + + for (j=0;j<32;j++) + r[j] = r2[j]; + } + + concat(rl, r, l, 32, 32); + + permute(out, rl, perm6, 64); +} + +static void str_to_key(const uchar *str, uchar *key) +{ + int i; + + key[0] = str[0]>>1; + key[1] = ((str[0]&0x01)<<6) | (str[1]>>2); + key[2] = ((str[1]&0x03)<<5) | (str[2]>>3); + key[3] = ((str[2]&0x07)<<4) | (str[3]>>4); + key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5); + key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6); + key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7); + key[7] = str[6]&0x7F; + for (i=0;i<8;i++) { + key[i] = (key[i]<<1); + } +} + + +void smbhash(uchar *out, const uchar *in, const uchar *key, int forw) +{ + int i; + char outb[64]; + char inb[64]; + char keyb[64]; + uchar key2[8]; + + str_to_key(key, key2); + + for (i=0;i<64;i++) { + inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0; + keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0; + outb[i] = 0; + } + + dohash(outb, inb, keyb, forw); + + for (i=0;i<8;i++) { + out[i] = 0; + } + + for (i=0;i<64;i++) { + if (outb[i]) + out[i/8] |= (1<<(7-(i%8))); + } +} + +void E_P16(uchar *p14,uchar *p16) +{ + uchar sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; + smbhash(p16, sp8, p14, 1); + smbhash(p16+8, sp8, p14+7, 1); +} + +void E_P24(const uchar *p21, const uchar *c8, uchar *p24) +{ + smbhash(p24, c8, p21, 1); + smbhash(p24+8, c8, p21+7, 1); + smbhash(p24+16, c8, p21+14, 1); +} + +void D_P16(const uchar *p14, const uchar *in, uchar *out) +{ + smbhash(out, in, p14, 0); + smbhash(out+8, in+8, p14+7, 0); +} + +void E_old_pw_hash( const uchar *p14, const uchar *in, uchar *out) +{ + smbhash(out, in, p14, 1); + smbhash(out+8, in+8, p14+7, 1); +} + +void cred_hash1(uchar *out, const uchar *in, const uchar *key) +{ + uchar buf[8]; + + smbhash(buf, in, key, 1); + smbhash(out, buf, key+9, 1); +} + +void cred_hash2(uchar *out,uchar *in,uchar *key) +{ + uchar buf[8]; + static uchar key2[8]; + + smbhash(buf, in, key, 1); + key2[0] = key[7]; + smbhash(out, buf, key2, 1); +} + +void cred_hash3(uchar *out, const uchar *in,uchar *key, int forw) +{ + static uchar key2[8]; + + smbhash(out, in, key, forw); + key2[0] = key[7]; + smbhash(out + 8, in + 8, key2, forw); +} + +void SamOEMhash( uchar *data, const uchar *key, int val) +{ + uchar hash[256]; + uchar index_i = 0; + uchar index_j = 0; + uchar j = 0; + int ind; + int len = 0; + if (val == 1) len = 516; + if (val == 0) len = 16; + if (val == 3) len = 8; + if (val == 2) len = 68; + if (val == 4) len = 32; + + if (val >= 8) + len = val; + + for (ind = 0; ind < 256; ind++) + { + hash[ind] = (uchar)ind; + } + + for( ind = 0; ind < 256; ind++) + { + uchar tc; + + j += (hash[ind] + key[ind%16]); + + tc = hash[ind]; + hash[ind] = hash[j]; + hash[j] = tc; + } + for( ind = 0; ind < len; ind++) + { + uchar tc; + uchar t; + + index_i++; + index_j += hash[index_i]; + + tc = hash[index_i]; + hash[index_i] = hash[index_j]; + hash[index_j] = tc; + + t = hash[index_i] + hash[index_j]; + data[ind] = data[ind] ^ hash[t]; + } +} + +void sam_pwd_hash(unsigned int rid, const uchar *in, uchar *out, int forw) +{ + uchar s[14]; + + s[0] = s[4] = s[8] = s[12] = (uchar)(rid & 0xFF); + s[1] = s[5] = s[9] = s[13] = (uchar)((rid >> 8) & 0xFF); + s[2] = s[6] = s[10] = (uchar)((rid >> 16) & 0xFF); + s[3] = s[7] = s[11] = (uchar)((rid >> 24) & 0xFF); + + smbhash(out, in, s, forw); + smbhash(out+8, in+8, s+7, forw); +}
_______________________________________________ Openvas-devel mailing list Openvas-devel@wald.intevation.org http://lists.wald.intevation.org/mailman/listinfo/openvas-devel