From ad43a641f82bc560213c14017f1b794d6a0d4981 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Thu, 27 Dec 2007 17:42:32 +0000 Subject: [PATCH] Patch from grutz (see #169). Added constants for SMB2 git-svn-id: file:///home/svn/framework3/trunk@5226 4d416f70-5f16-0410-b530-b9f4589650da --- lib/rex/proto/smb/constants.rb | 53 +++++++++++++++++++++++++++ lib/rex/proto/smb/utils.rb | 65 ++++++++++++++++++++++++++++++---- 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/lib/rex/proto/smb/constants.rb b/lib/rex/proto/smb/constants.rb index 2b76897237..791f27fa93 100644 --- a/lib/rex/proto/smb/constants.rb +++ b/lib/rex/proto/smb/constants.rb @@ -80,6 +80,29 @@ SMB_COM_READ_BULK = 0xd8 SMB_COM_WRITE_BULK = 0xd9 SMB_COM_NO_ANDX_COMMAND = 0xff + +# SMB Version 2 Commands +SMB2_OP_NEGPROT = 0x00 +SMB2_OP_SESSSETUP = 0x01 +SMB2_OP_LOGOFF = 0x02 +SMB2_OP_TCON = 0x03 +SMB2_OP_TDIS = 0x04 +SMB2_OP_CREATE = 0x05 +SMB2_OP_CLOSE = 0x06 +SMB2_OP_FLUSH = 0x07 +SMB2_OP_READ = 0x08 +SMB2_OP_WRITE = 0x09 +SMB2_OP_LOCK = 0x0a +SMB2_OP_IOCTL = 0x0b +SMB2_OP_CANCEL = 0x0c +SMB2_OP_KEEPALIVE = 0x0d +SMB2_OP_FIND = 0x0e +SMB2_OP_NOTIFY = 0x0f +SMB2_OP_GETINFO = 0x10 +SMB2_OP_SETINFO = 0x11 +SMB2_OP_BREAK = 0x12 + + # SMB_COM_NT_TRANSACT Subcommands NT_TRANSACT_CREATE = 1 # File open/create NT_TRANSACT_IOCTL = 2 # Device IOCTL @@ -356,6 +379,36 @@ SMB_HDR = Rex::Struct2::CStructTemplate.new( ) +# The SMB2 header template +SMB2_HDR = Rex::Struct2::CStructTemplate.new( + [ 'uint32n', 'Magic', 0xfe534d42 ], + [ 'uint16v', 'HeaderLen', 64 ], + [ 'uint16v', 'Reserved0', 0 ], + [ 'uint32v', 'NTStatus', 0 ], + + [ 'uint16v', 'Opcode', 0 ], + [ 'uint16v', 'Reserved1', 0 ], + + [ 'uint16v', 'Flags1', 0 ], + [ 'uint16v', 'Flags2', 0 ], + + [ 'uint32v', 'ChainOffset', 0 ], + + [ 'uint32v', 'SequenceHigh', 0 ], + [ 'uint32v', 'SequenceLow', 0 ], + + [ 'uint32v', 'ProcessID', 0 ], + [ 'uint32v', 'TreeID', 0 ], + [ 'uint32v', 'UserIDHigh', 0 ], + [ 'uint32v', 'UserIDLow', 0 ], + + [ 'uint32v', 'SignatureA', 0 ], + [ 'uint32v', 'SignatureB', 0 ], + [ 'uint32v', 'SignatureC', 0 ], + [ 'uint32v', 'SignatureD', 0 ], + [ 'string', 'Payload', nil, ''] +) + # A basic SMB template to read all responses SMB_BASE_HDR_PKT = Rex::Struct2::CStructTemplate.new( [ 'template', 'SMB', SMB_HDR ], diff --git a/lib/rex/proto/smb/utils.rb b/lib/rex/proto/smb/utils.rb index bf094c4deb..419e05784b 100644 --- a/lib/rex/proto/smb/utils.rb +++ b/lib/rex/proto/smb/utils.rb @@ -378,7 +378,7 @@ CONST = Rex::Proto::SMB::Constants # Process Type 1 NTLM Messages, return a Base64 Type 2 Message # def self.process_type1_message(message, nonce = "\x11\x22\x33\x44\x55\x66\x77\x88", win_domain = 'DOMAIN', - win_name = 'SERVER', dns_name = 'server', dns_domain = 'example.com') + win_name = 'SERVER', dns_name = 'server', dns_domain = 'example.com', downgrade = true) dns_name = Rex::Text.to_unicode(dns_name + "." + dns_domain) win_domain = Rex::Text.to_unicode(win_domain) @@ -386,8 +386,6 @@ CONST = Rex::Proto::SMB::Constants win_name = Rex::Text.to_unicode(win_name) decode = Rex::Text.decode_base64(message.strip) - puts "dns_name = #{dns_name}, dns_domain = #{dns_domain}" - type = decode[8] if (type == 1) @@ -397,9 +395,18 @@ CONST = Rex::Proto::SMB::Constants reqflags = Integer("0x" + reqflags.unpack("h8").to_s.reverse) if (reqflags & CONST::REQUEST_TARGET) == CONST::REQUEST_TARGET - # At this time NTLMv2 and signing requirements are not supported - #flags = CONST::NEGOTIATE_UNICODE | CONST::NEGOTIATE_NTLM | CONST::NEGOTIATE_TARGET_INFO | CONST::TARGET_TYPE_DOMAIN | CONST::TARGET_TYPE_SERVER - flags = 0x00810201 + + if (downgrade) + # At this time NTLMv2 and signing requirements are not supported + if (reqflags & CONST::NEGOTIATE_NTLM2_KEY) == CONST::NEGOTIATE_NTLM2_KEY + reqflags = reqflags - CONST::NEGOTIATE_NTLM2_KEY + end + if (reqflags & CONST::NEGOTIATE_ALWAYS_SIGN) == CONST::NEGOTIATE_ALWAYS_SIGN + reqflags = reqflags - CONST::NEGOTIATE_ALWAYS_SIGN + end + end + + flags = reqflags + CONST::TARGET_TYPE_DOMAIN + CONST::TARGET_TYPE_SERVER tid = true tidoffset = 48 + win_domain.length @@ -417,7 +424,7 @@ CONST = Rex::Proto::SMB::Constants [dns_name.length].pack('v') + dns_name else - flags = CONST::NEGOTIATE_UNICODE | CONST::NEGOTIATE_NTLM + flags = CONST::NEGOTIATE_UNICODE + CONST::NEGOTIATE_NTLM tid = false end @@ -457,6 +464,50 @@ CONST = Rex::Proto::SMB::Constants return type2msg end + # + # Downgrading Type messages to LMv1/NTLMv1 and removing signing + # + def self.downgrade_type_message(message) + decode = Rex::Text.decode_base64(message.strip) + + type = decode[8] + + if (type > 0 and type < 4) + reqflags = decode[12..15] if (type == 1 or type == 3) + reqflags = decode[20..23] if (type == 2) + reqflags = Integer("0x" + reqflags.unpack("h8").to_s.reverse) + + # Remove NEGOTIATE_NTLMV2_KEY and NEGOTIATE_ALWAYS_SIGN, this lowers the negotiation + # down to LMv1/NTLMv1. + if (reqflags & CONST::NEGOTIATE_NTLM2_KEY) == CONST::NEGOTIATE_NTLM2_KEY + reqflags = reqflags - CONST::NEGOTIATE_NTLM2_KEY + end + if (reqflags & CONST::NEGOTIATE_ALWAYS_SIGN) == CONST::NEGOTIATE_ALWAYS_SIGN + reqflags = reqflags - CONST::NEGOTIATE_ALWAYS_SIGN + end + + # Return the flags back to the decode so we can base64 it again + flags = reqflags.to_s(16) + 0.upto(8) do |idx| + if (idx > flags.length) + flags.insert(0, "0") + end + end + + idx = 0 + 0.upto(3) do |cnt| + if (type == 2) + decode[23-cnt] = Integer("0x" + flags[idx .. idx + 1]) + else + decode[15-cnt] = Integer("0x" + flags[idx .. idx + 1]) + end + idx += 2 + end + + end + return Rex::Text.encode_base64(decode).delete("\n") # base64 encode and remove the returns + end + end end end