From 65419ad206cbae95f9c83d386ecc447ab3159809 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 22 Oct 2008 22:42:52 +0000 Subject: [PATCH] Adds routines/tools for cracking the NTLM hash from the plaintext case-insensive LANMAN password git-svn-id: file:///home/svn/framework3/trunk@5779 4d416f70-5f16-0410-b530-b9f4589650da --- lib/rex/proto/smb/constants.rb | 14 ++++++++ lib/rex/proto/smb/crypt.rb | 15 +++++++-- tools/lm2ntcrack.rb | 59 ++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100755 tools/lm2ntcrack.rb diff --git a/lib/rex/proto/smb/constants.rb b/lib/rex/proto/smb/constants.rb index c16f78250a..a5319b45f9 100644 --- a/lib/rex/proto/smb/constants.rb +++ b/lib/rex/proto/smb/constants.rb @@ -1017,6 +1017,20 @@ SMB_READ_RES_HDR_PKT = Rex::Struct2::CStructTemplate.new( ) SMB_READ_RES_PKT = self.make_nbs(SMB_READ_RES_HDR_PKT) + + +# A SMB template for SMB Search requests +SMB_SEARCH_HDR_PKT = Rex::Struct2::CStructTemplate.new( + [ 'template', 'SMB', SMB_HDR ], + [ 'uint16v', 'MaxCount', 0 ], + [ 'uint16v', 'Attributes', 0 ], + [ 'uint16v', 'ByteCount', 0 ], + [ 'string', 'Payload', nil, '' ] +).create_restraints( + [ 'Payload', 'ByteCount', nil, true ] +) +SMB_SEARCH_PKT = self.make_nbs(SMB_SEARCH_HDR_PKT) + # NTLMSSP Message Flags NEGOTIATE_UNICODE = 0x00000001 # Only set if Type 1 contains it - this or oem, not both NEGOTIATE_OEM = 0x00000002 # Only set if Type 1 contains it - this or unicode, not both diff --git a/lib/rex/proto/smb/crypt.rb b/lib/rex/proto/smb/crypt.rb index 9e49354360..7da1b0ffbd 100644 --- a/lib/rex/proto/smb/crypt.rb +++ b/lib/rex/proto/smb/crypt.rb @@ -51,7 +51,18 @@ begin def self.md5_hash(data) digest = OpenSSL::Digest::Digest.digest('md5', data) - end + end + + def self.lm2nt(pass, ntlm) + res = nil + Rex::Text.permute_case( pass.upcase ).each do |word| + if(md4_hash(Rex::Text.to_unicode(word)) == ntlm) + res = word + break + end + end + res + end rescue LoadError end @@ -59,4 +70,4 @@ end end end end -end \ No newline at end of file +end diff --git a/tools/lm2ntcrack.rb b/tools/lm2ntcrack.rb new file mode 100755 index 0000000000..daa9094b4a --- /dev/null +++ b/tools/lm2ntcrack.rb @@ -0,0 +1,59 @@ +#!/usr/bin/env ruby +# +# This script cracks a NTLM hash based on the case-insensitive LANMAN password +# Credit to Yannick Hamon for the idea/perl code +# + +msfbase = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__ +$:.unshift(File.join(File.dirname(msfbase), '..', 'lib')) + +require 'rex' + +def usage + $stderr.puts("\n" + " Usage: #{$0} \n" + $args.usage) + exit +end + + +ntlm = pass = nil + +$args = Rex::Parser::Arguments.new( + "-n" => [ true, "The encypted NTLM hash to crack" ], + "-p" => [ true, "The decrypted LANMAN password" ], + "-h" => [ false, "Display this help information" ]) + + +$args.parse(ARGV) { |opt, idx, val| + case opt + when "-n" + ntlm = val + when "-p" + pass = val + when "-h" + usage + else + usage + end +} + +if (not (ntlm and pass)) + usage +end + +if(ntlm.length != 32) + $stderr.puts "[*] NTLM should be exactly 32 bytes of hexadecimal" + exit +end + +if(pass.length > 14) + $stderr.puts "[*] LANMAN password should be between 1 and 14 characters" + exit +end + +done = Rex::Proto::SMB::Crypt.lm2nt(pass, [ntlm].pack("H*")) + +if(done) + puts "[*] Cracked: LANMAN=#{pass} NTLM=#{done}" +else + puts "[*] Failed to crack password (incorrect input)" +end