Penetration Testing mailing list archives
Re: pwdump 2 & 3
From: "Nicolas RUFF (lists)" <ruff.lists () edelweb fr>
Date: Sun, 30 Jan 2005 23:33:00 +0100
Your explanation is quite interesting, but I see a conflict with the information mentioned in:"Windows Passwords: Everything You Need To Know" http://202.181.238.2/hk/teched2004/ppt/Day_2_Rm402/WIN495(1500-1615).pptAccording to the above mentioned presentation, the information in the cache is:MD5(NTLM(password)+userID+Domain) Can you provide any feedback on that?
Well, I am afraid that Microsoft is wrong :-)To demonstrate this, I wrote the following utility in PERL (CACHE-COMPUTE.PL).
In short :- Go onto a Windows NT4 Workstation (it will not work against Windows 2000+, since a different password storage scheme is used).
- Use LSADUMP to dump NL$x entries.- Fill the "username" and "password" in CACHE-COMPUTE with data from a user that is in cache (for example, the currently logged in user).
- You should match one line of the LSADUMP output with CACHE-COMPUTE output. On my computer : - username = testuser - password = thisisatest - CACHE-COMPUTE output = 7a0420497cf92869352c51578c1945fc - LSADUMP = NL$8 72 F1 8D 6A 2A 4F E1 6C 7B 99 A7 02 2A 0E CD 40 r..j*O.l{...*..@ 7A 04 20 49 7C F9 28 69 35 2C 51 57 8C 19 45 FC z. I|.(i5,QW..E. 01 01 00 ... Regards, - Nicolas RUFF ----------------------------------- Security Consultant EdelWeb (http://www.edelweb.fr/) Mail: nicolas.ruff (at) edelweb.fr ----------------------------------- #!/usr/bin/perl # CACHE-COMPUTE.PL # A little utility to compute cache values for Windows NT4 # # I really don't like PERL ... # ... but it is hard to find a MD4 module for Python # (c) Nicolas RUFF / EdelWeb / released on Jan 2005 use Crypt::DES; use Digest::MD4; @odd_parity = ( 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254 ); # Shamelessly copied from Authen::NTLM-1.02 # Added des_set_odd_parity() from SSLEAY sub str_to_key { my ($str) = @_; my $i; my @key; my $out; my @str = map {ord($_)} split(//, $str); $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; foreach $i (0..7) { $key[$i] = 0xff&($key[$i]<<1); # des_set_odd_parity() $key[$i] = $odd_parity[ $key[$i] ]; } return \@key; } # -------------------------------------------------- # Input data # -------------------------------------------------- # username = "testuser" (Unicode) $username = "t\x00e\x00s\x00t\x00u\x00s\x00e\x00r\x00"; $password = "thisisatest"; # -------------------------------------------------- # Compute LM hash # In this sample : "8A6D8380CAC58F22 01FC5A6BE7BC6929" # -------------------------------------------------- $password = uc($password); $password_part1 = pack( "a7", substr($password, 0, 7) ); $key1 = str_to_key( $password_part1 ); $deskey1 = pack( "C8", @$key1 ); $password_part2 = pack( "a7", substr($password, 7, 7) ); $key2 = str_to_key( $password_part2 ); $deskey2 = pack( "C8", @$key2 ); # Magic string (see LM specs) $lmplaintext = pack( "H16", "4B47532140232425" ); $des1 = new Crypt::DES $deskey1; $lmhash1 = $des1->encrypt($lmplaintext); print "LM part1 : ", unpack("H16", $lmhash1), "\n"; $des2 = new Crypt::DES $deskey2; $lmhash2 = $des2->encrypt($lmplaintext); print "LM part2 : ", unpack("H16", $lmhash2), "\n"; # -------------------------------------------------- # Compute cache value # In this sample : NL$8 = # 72 F1 8D 6A 2A 4F E1 6C 7B 99 A7 02 2A 0E CD 40 # 7A 04 20 49 7C F9 28 69 35 2C 51 57 8C 19 45 FC [*] # 01 01 00 # -------------------------------------------------- $string = $lmhash1 . $lmhash2 . $username; $ctx = new Digest::MD4; $ctx->reset(); print "Output : ", Digest::MD4->hexhash($string), "\n";
Current thread:
- Re: pwdump 2 & 3 Geoffroy Raimbault (Jan 03)
- Re: pwdump 2 & 3 okrehel (Jan 03)
- <Possible follow-ups>
- Re: pwdump 2 & 3 Nicolas RUFF (listes) (Jan 05)
- Re: pwdump 2 & 3 miguel . dilaj (Jan 06)
- Re: pwdump 2 & 3 Nicolas RUFF (lists) (Jan 31)
- Re: pwdump 2 & 3 Arnaud Pilon (Jan 11)