Parent

Class/Module Index [+]

Quicksearch

Rex::Proto::SMB::Client::NTLM_UTILS

Constants

CONST
CRYPT
XCEPT

Public Class Methods

asn1encode(str = '') click to toggle source

Prepends an ASN1 formatted length field to a piece of data

# File lib/rex/proto/ntlm/utils.rb, line 31
def self.asn1encode(str = '')
        res = ''

        # If the high bit of the first byte is 1, it contains the number of
        # length bytes that follow

        case str.length
                when 0 .. 0x7F
                        res = [str.length].pack('C') + str
                when 0x80 .. 0xFF
                        res = [0x81, str.length].pack('CC') + str
                when 0x100 .. 0xFFFF
                        res = [0x82, str.length].pack('Cn') + str
                when  0x10000 .. 0xffffff
                        res = [0x83, str.length >> 16, str.length & 0xFFFF].pack('CCn') + str
                when  0x1000000 .. 0xffffffff
                        res = [0x84, str.length].pack('CN') + str
                else
                        raise "ASN1 str too long"
        end
        return res
end
create_lm_ntlm_responses(user, pass, challenge_key, domain = '', default_name = '', default_domain = '', dns_host_name = '', dns_domain_name = '', chall_MsvAvTimestamp = nil, spnopt = {}, opt = {} ) click to toggle source

create lm/ntlm responses

# File lib/rex/proto/ntlm/utils.rb, line 478
def self.create_lm_ntlm_responses(user, pass, challenge_key, domain = '', default_name = '', default_domain = '',
                                dns_host_name = '', dns_domain_name = '', chall_MsvAvTimestamp = nil, spnopt = {}, opt = {} )

        usentlm2_session      = opt[:usentlm2_session]    != nil ? opt[:usentlm2_session] : true
        use_ntlmv2            = opt[:use_ntlmv2]               != nil ? opt[:use_ntlmv2] : false
        send_lm               = opt[:send_lm]             != nil ? opt[:send_lm] : true
        send_ntlm             = opt[:send_ntlm]                 != nil ? opt[:send_ntlm] : true

        #calculate the lm/ntlm response
        resp_lm = "\x00" * 24
        resp_ntlm = "\x00" * 24

        client_challenge = Rex::Text.rand_text(8)
        ntlm_cli_challenge = ''
        if send_ntlm  #should be default
                if usentlm2_session
                        if use_ntlmv2
                                ntlm_cli_challenge = self.make_ntlmv2_clientchallenge(default_domain, default_name, dns_domain_name,
                                                                                        dns_host_name,client_challenge ,
                                                                                        chall_MsvAvTimestamp, spnopt)
                                if self.is_pass_ntlm_hash?(pass)
                                        argntlm = {
                                                :ntlmv2_hash =>  CRYPT::ntlmv2_hash(
                                                                                        user,
                                                                                        [ pass.upcase()[33,65] ].pack('H32'),
                                                                                        domain,{:pass_is_hash => true}
                                                                                ),
                                                :challenge   => challenge_key
                                        }
                                else
                                        argntlm = {
                                                :ntlmv2_hash =>  CRYPT::ntlmv2_hash(user, pass, domain),
                                                :challenge   =>  challenge_key
                                        }
                                end

                                optntlm = { :nt_client_challenge => ntlm_cli_challenge}
                                ntlmv2_response = CRYPT::ntlmv2_response(argntlm,optntlm)
                                resp_ntlm = ntlmv2_response

                                if send_lm
                                        if self.is_pass_ntlm_hash?(pass)
                                                arglm = {
                                                        :ntlmv2_hash =>  CRYPT::ntlmv2_hash(
                                                                                                user,
                                                                                                [ pass.upcase()[33,65] ].pack('H32'),
                                                                                                domain,{:pass_is_hash => true}
                                                                                        ),
                                                        :challenge   => challenge_key
                                                }
                                        else
                                                arglm = {
                                                        :ntlmv2_hash =>  CRYPT::ntlmv2_hash(user,pass, domain),
                                                        :challenge   => challenge_key
                                                }
                                        end

                                        optlm = { :client_challenge => client_challenge }
                                        resp_lm = CRYPT::lmv2_response(arglm, optlm)
                                else
                                        resp_lm = "\x00" * 24
                                end

                        else # ntlm2_session
                                if self.is_pass_ntlm_hash?(pass)
                                        argntlm = {
                                                :ntlm_hash =>  [ pass.upcase()[33,65] ].pack('H32'),
                                                :challenge => challenge_key
                                        }
                                else
                                        argntlm = {
                                                :ntlm_hash =>  CRYPT::ntlm_hash(pass),
                                                :challenge => challenge_key
                                        }
                                end

                                optntlm = {        :client_challenge => client_challenge}
                                resp_ntlm = CRYPT::ntlm2_session(argntlm,optntlm).join[24,24]

                                # Generate the fake LANMAN hash
                                resp_lm = client_challenge + ("\x00" * 16)
                        end

                else # we use lmv1/ntlmv1
                        if self.is_pass_ntlm_hash?(pass)
                                argntlm = {
                                        :ntlm_hash =>  [ pass.upcase()[33,65] ].pack('H32'),
                                        :challenge =>  challenge_key
                                }
                        else
                                argntlm = {
                                        :ntlm_hash =>  CRYPT::ntlm_hash(pass),
                                        :challenge =>  challenge_key
                                }
                        end

                        resp_ntlm = CRYPT::ntlm_response(argntlm)
                        if send_lm
                                if self.is_pass_ntlm_hash?(pass)
                                        arglm = {
                                                :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
                                                :challenge =>  challenge_key
                                        }
                                else
                                        arglm = {
                                                :lm_hash => CRYPT::lm_hash(pass),
                                                :challenge =>  challenge_key
                                        }
                                end
                                resp_lm = CRYPT::lm_response(arglm)
                        else
                                #when windows does not send lm in ntlmv1 type response,
                                # it gives lm response the same value as ntlm response
                                resp_lm  = resp_ntlm
                        end
                end
        else #send_ntlm = false
                #lmv2
                if usentlm2_session && use_ntlmv2
                        if self.is_pass_ntlm_hash?(pass)
                                arglm = {
                                        :ntlmv2_hash =>  CRYPT::ntlmv2_hash(
                                                                                user,
                                                                                [ pass.upcase()[33,65] ].pack('H32'),
                                                                                domain,{:pass_is_hash => true}
                                                                        ),
                                        :challenge => challenge_key
                                }
                        else
                                arglm = {
                                        :ntlmv2_hash =>  CRYPT::ntlmv2_hash(user,pass, domain),
                                        :challenge => challenge_key
                                }
                        end
                        optlm = { :client_challenge => client_challenge }
                        resp_lm = CRYPT::lmv2_response(arglm, optlm)
                else
                        if self.is_pass_ntlm_hash?(pass)
                                arglm = {
                                        :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
                                        :challenge =>  challenge_key
                                }
                        else
                                arglm = {
                                        :lm_hash => CRYPT::lm_hash(pass),
                                        :challenge =>  challenge_key
                                }
                        end
                        resp_lm = CRYPT::lm_response(arglm)
                end
                resp_ntlm = ""
        end
        return resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge
end
create_session_key(ntlmssp_flags, server_ntlmssp_flags, user, pass, domain, challenge_key, client_challenge = '', ntlm_cli_challenge = '' , opt = {} ) click to toggle source

create the session key

# File lib/rex/proto/ntlm/utils.rb, line 634
def self.create_session_key(ntlmssp_flags, server_ntlmssp_flags, user, pass, domain, challenge_key,
                                client_challenge = '', ntlm_cli_challenge = '' , opt = {} )

        usentlm2_session      = opt[:usentlm2_session]    != nil ? opt[:usentlm2_session] : true
        use_ntlmv2            = opt[:use_ntlmv2]               != nil ? opt[:use_ntlmv2] : false
        send_lm               = opt[:send_lm]             != nil ? opt[:send_lm] : true
        send_ntlm             = opt[:send_ntlm]                 != nil ? opt[:send_ntlm] : true
        use_lanman_key                = opt[:use_lanman_key]               != nil ? opt[:use_lanman_key] : false

        # Create the sessionkey (aka signing key, aka mackey) and encrypted session key
        # Server will decide for key_size and key_exchange
        enc_session_key = ''
        signing_key = ''

        # Set default key size and key exchange values
        key_size = 40
        key_exchange = false
        # Remove ntlmssp.negotiate56
        ntlmssp_flags &= 0x7fffffff
        # Remove ntlmssp.negotiatekeyexch
        ntlmssp_flags &= 0xbfffffff
        # Remove ntlmssp.negotiate128
        ntlmssp_flags &= 0xdfffffff
        # Check the keyexchange
        if server_ntlmssp_flags & CONST::NEGOTIATE_KEY_EXCH != 0 then
                key_exchange = true
                ntlmssp_flags |= CONST::NEGOTIATE_KEY_EXCH
        end
        # Check 128bits
        if server_ntlmssp_flags & CONST::NEGOTIATE_128 != 0 then
                key_size = 128
                ntlmssp_flags |= CONST::NEGOTIATE_128
                ntlmssp_flags |= CONST::NEGOTIATE_56
        # Check 56bits
        else
                if server_ntlmssp_flags & CONST::NEGOTIATE_56 != 0 then
                        key_size = 56
                        ntlmssp_flags |= CONST::NEGOTIATE_56
                end
        end
        # Generate the user session key
        lanman_weak = false
        if send_ntlm  # Should be default
                if usentlm2_session
                        if use_ntlmv2
                                if self.is_pass_ntlm_hash?(pass)
                                        user_session_key = CRYPT::ntlmv2_user_session_key(user,
                                                                                        [ pass.upcase()[33,65] ].pack('H32'),
                                                                                        domain,
                                                                                        challenge_key, ntlm_cli_challenge,
                                                                                        {:pass_is_hash => true})
                                else
                                        user_session_key = CRYPT::ntlmv2_user_session_key(user, pass, domain,
                                                                                challenge_key, ntlm_cli_challenge)
                                end
                        else
                                if self.is_pass_ntlm_hash?(pass)
                                        user_session_key = CRYPT::ntlm2_session_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
                                                                                                        challenge_key,
                                                                                                        client_challenge,
                                                                                                        {:pass_is_hash => true})
                                else
                                        user_session_key = CRYPT::ntlm2_session_user_session_key(pass, challenge_key,
                                                                                                        client_challenge)
                                end
                        end
                else # lmv1/ntlmv1
                        # lanman_key may also be used without ntlm response but it is not so much used
                        # so we don't care about this feature
                        if send_lm && use_lanman_key
                                if self.is_pass_ntlm_hash?(pass)
                                        user_session_key = CRYPT::lanman_session_key([ pass.upcase()[0,32] ].pack('H32'),
                                                                                        challenge_key,
                                                                                        {:pass_is_hash => true})
                                else
                                        user_session_key = CRYPT::lanman_session_key(pass, challenge_key)
                                end
                                lanman_weak = true


                        else
                                if self.is_pass_ntlm_hash?(pass)
                                        user_session_key = CRYPT::ntlmv1_user_session_key([ pass.upcase()[33,65] ].pack('H32'),
                                                                                                {:pass_is_hash => true})
                                else
                                        user_session_key = CRYPT::ntlmv1_user_session_key(pass)
                                end
                        end
                end
        else
                        if usentlm2_session && use_ntlmv2
                                if self.is_pass_ntlm_hash?(pass)
                                        user_session_key = CRYPT::lmv2_user_session_key(user, [ pass.upcase()[33,65] ].pack('H32'),
                                                                                        domain,
                                                                                        challenge_key, client_challenge,
                                                                                        {:pass_is_hash => true})
                                else
                                        user_session_key = CRYPT::lmv2_user_session_key(user, pass, domain,
                                                                                        challenge_key, client_challenge)
                                end
                        else
                                if self.is_pass_ntlm_hash?(pass)
                                        user_session_key = CRYPT::lmv1_user_session_key([ pass.upcase()[0,32] ].pack('H32'),
                                                                                                {:pass_is_hash => true})
                                else
                                        user_session_key = CRYPT::lmv1_user_session_key(pass)
                                end
                        end
        end

        user_session_key = CRYPT::make_weak_sessionkey(user_session_key,key_size, lanman_weak)

        # Sessionkey and encrypted session key
        if key_exchange
                signing_key = Rex::Text.rand_text(16)
                enc_session_key = CRYPT::encrypt_sessionkey(signing_key, user_session_key)
        else
                signing_key = user_session_key
        end

        return signing_key, enc_session_key, ntlmssp_flags


end
is_pass_ntlm_hash?(str) click to toggle source

Determine whether the password is a known hash format

# File lib/rex/proto/ntlm/utils.rb, line 24
def self.is_pass_ntlm_hash?(str)
        str.downcase =~ /^[0-9a-f]{32}:[0-9a-f]{32}$/
end
make_negotiate_secblob_resp(account, domain) click to toggle source

GSS BLOB usefull for SMB_NEGOCIATE_RESPONSE message mechTypes: 4 items :

MechType: 1.2.840.48018.1.2.2 (MS KRB5 - Microsoft Kerberos 5)
MechType: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
MechType: 1.2.840.113554.1.2.2.3 (KRB5 - Kerberos 5 - User to User)
MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)

mechListMIC:

principal: account@domain
# File lib/rex/proto/ntlm/utils.rb, line 92
def self.make_negotiate_secblob_resp(account, domain)
        blob =
        "\x60" + self.asn1encode(
                "\x06" + self.asn1encode(
                        "\x2b\x06\x01\x05\x05\x02"
                ) +
                "\xa0" + self.asn1encode(
                        "\x30" + self.asn1encode(
                                "\xa0" + self.asn1encode(
                                        "\x30" + self.asn1encode(
                                                "\x06" + self.asn1encode(
                                                        "\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"
                                                ) +
                                                "\x06" + self.asn1encode(
                                                        "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
                                                ) +
                                                "\x06" + self.asn1encode(
                                                        "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"
                                                ) +
                                                "\x06" + self.asn1encode(
                                                        "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
                                                )
                                        )
                                ) +
                                "\xa3" + self.asn1encode(
                                        "\x30" + self.asn1encode(
                                                "\xa0" + self.asn1encode(
                                                        "\x1b" + self.asn1encode(
                                                                account + '@' + domain
                                                        )
                                                )
                                        )
                                )
                        )
                )
        )

        return blob
end
make_ntlm_flags(opt = {}) click to toggle source

Return the correct ntlmflags upon the configuration

# File lib/rex/proto/ntlm/utils.rb, line 336
def self.make_ntlm_flags(opt = {})

        signing               = opt[:signing]             != nil ? opt[:signing] : false
        usentlm2_session      = opt[:usentlm2_session]    != nil ? opt[:usentlm2_session] : true
        use_ntlmv2            = opt[:use_ntlmv2]               != nil ? opt[:use_ntlmv2] : false
        send_lm               = opt[:send_lm]             != nil ? opt[:send_lm] : true
        send_ntlm             = opt[:send_ntlm]                 != nil ? opt[:send_ntlm] : true
        use_lanman_key                = opt[:use_lanman_key]               != nil ? opt[:use_lanman_key] : false

        if signing
                ntlmssp_flags = 0xe2088215
        else

                ntlmssp_flags = 0xa2080205
        end

        if usentlm2_session
                if use_ntlmv2
                        #set Negotiate Target Info
                        ntlmssp_flags |= CONST::NEGOTIATE_TARGET_INFO
                end

        else
                #remove the ntlm2_session flag
                ntlmssp_flags &= 0xfff7ffff
                #set lanmanflag only when lm and ntlm are sent
                if send_lm
                        ntlmssp_flags |= CONST::NEGOTIATE_LMKEY if use_lanman_key
                end
        end

        #we can also downgrade ntlm2_session when we send only lmv1
        ntlmssp_flags &= 0xfff7ffff if usentlm2_session && (not use_ntlmv2) && (not send_ntlm)

        return ntlmssp_flags
end
make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201) click to toggle source

BLOB without GSS Usefull for ntlmssp type 3 message

# File lib/rex/proto/ntlm/utils.rb, line 241
def self.make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
        lm ||= "\x00" * 24
        ntlm ||= "\x00" * 24

        domain_uni = Rex::Text.to_unicode(domain)
        user_uni   = Rex::Text.to_unicode(user)
        name_uni   = Rex::Text.to_unicode(name)
        session    = enc_session_key

        ptr  = 64

        blob = "NTLMSSP\x00" +
                [ 3 ].pack('V') +

                [    # Lan Manager Response
                        lm.length,
                        lm.length,
                        (ptr)
                ].pack('vvV') +

                [    # NTLM Manager Response
                        ntlm.length,
                        ntlm.length,
                        (ptr += lm.length)
                ].pack('vvV') +

                [    # Domain Name
                        domain_uni.length,
                        domain_uni.length,
                        (ptr += ntlm.length)
                ].pack('vvV') +

                [    # Username
                        user_uni.length,
                        user_uni.length,
                        (ptr += domain_uni.length)
                ].pack('vvV') +

                [    # Hostname
                        name_uni.length,
                        name_uni.length,
                        (ptr += user_uni.length)
                ].pack('vvV') +

                [    # Session Key (none)
                        session.length,
                        session.length,
                        (ptr += name_uni.length)
                ].pack('vvV') +

                [ flags ].pack('V') +

                lm +
                ntlm +
                domain_uni +
                user_uni +
                name_uni +
                session + "\x00"
        return blob

end
make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags) click to toggle source

BLOB without GSS usefull for ntlm type 2 message

# File lib/rex/proto/ntlm/utils.rb, line 183
def self.make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)

        addr_list  = ''
        addr_list  << [2, win_domain.length].pack('vv') + win_domain
        addr_list  << [1, win_name.length].pack('vv') + win_name
        addr_list  << [4, dns_domain.length].pack('vv') + dns_domain
        addr_list  << [3, dns_name.length].pack('vv') + dns_name
        addr_list  << [0, 0].pack('vv')

        ptr  = 0
        blob =        "NTLMSSP\x00" +
                        [2].pack('V') +
                        [
                                win_domain.length,  # length
                                win_domain.length,  # max length
                                (ptr += 48) # offset
                        ].pack('vvV') +
                        [ flags ].pack('V') +
                        chall +
                        "\x00\x00\x00\x00\x00\x00\x00\x00" +
                        [
                                addr_list.length,  # length
                                addr_list.length,  # max length
                                (ptr += win_domain.length)
                        ].pack('vvV') +
                        win_domain +
                        addr_list
        return blob
end
make_ntlmssp_blob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201) click to toggle source

BLOB without GSS usefull for ntlmssp type 1 message

# File lib/rex/proto/ntlm/utils.rb, line 133
def self.make_ntlmssp_blob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
        blob =        "NTLMSSP\x00" +
                [1, flags].pack('VV') +

                [
                        domain.length,  #length
                        domain.length,  #max length
                        32
                ].pack('vvV') +

                [
                        name.length,        #length
                        name.length,        #max length
                        domain.length + 32
                ].pack('vvV') +

                domain + name
        return blob
end
make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201) click to toggle source

GSS BLOB Usefull for ntlmssp type 3 message

# File lib/rex/proto/ntlm/utils.rb, line 304
def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)

        blob =
                "\xa1" + self.asn1encode(
                        "\x30" + self.asn1encode(
                                "\xa2" + self.asn1encode(
                                        "\x04" + self.asn1encode(
                                        make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags )
                                )
                        )
                )
        )
        return blob
end
make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags) click to toggle source

GSS BLOB usefull for ntlmssp type 2 message

# File lib/rex/proto/ntlm/utils.rb, line 214
def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)

        blob =
                "\xa1" + self.asn1encode(
                        "\x30" + self.asn1encode(
                                "\xa0" + self.asn1encode(
                                        "\x0a" + self.asn1encode(
                                                "\x01"
                                        )
                                ) +
                                "\xa1" + self.asn1encode(
                                        "\x06" + self.asn1encode(
                                                "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
                                        )
                                ) +
                                "\xa2" + self.asn1encode(
                                        "\x04" + self.asn1encode(
                                                make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
                                        )
                                )
                        )
                )

        return blob
end
make_ntlmssp_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201) click to toggle source

GSS BLOB usefull for ntlmssp type 1 message

# File lib/rex/proto/ntlm/utils.rb, line 154
def self.make_ntlmssp_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
        blob =
        "\x60" + self.asn1encode(
                "\x06" + self.asn1encode(
                        "\x2b\x06\x01\x05\x05\x02"
                ) +
                "\xa0" + self.asn1encode(
                        "\x30" + self.asn1encode(
                                "\xa0" + self.asn1encode(
                                        "\x30" + self.asn1encode(
                                                "\x06" + self.asn1encode(
                                                        "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
                                                )
                                        )
                                ) +
                                "\xa2" + self.asn1encode(
                                        "\x04" + self.asn1encode(
                                                make_ntlmssp_blob_init(domain, name, flags)
                                        )
                                )
                        )
                )
        )

        return blob
end
make_ntlmv2_clientchallenge(win_domain, win_name, dns_domain, dns_name, client_challenge = nil, chall_MsvAvTimestamp = nil, spnopt = {}) click to toggle source

This function return an ntlmv2 client challenge This is a partial implementation, full description is in [MS-NLMP].pdf around 3.1.5.2.1 :-/

# File lib/rex/proto/ntlm/utils.rb, line 429
def self.make_ntlmv2_clientchallenge(win_domain, win_name, dns_domain, dns_name,
                                        client_challenge = nil, chall_MsvAvTimestamp = nil, spnopt = {})

        client_challenge ||= Rex::Text.rand_text(8)
        # We have to set the timestamps here to the one in the challenge message from server if present
        # If we don't do that, recent server like Seven/2008 will send a STATUS_INVALID_PARAMETER error packet
        timestamp = chall_MsvAvTimestamp != '' ? chall_MsvAvTimestamp : self.time_unix_to_smb(Time.now.to_i).reverse.pack("VV")
        # Make those values unicode as requested
        win_domain = Rex::Text.to_unicode(win_domain)
        win_name = Rex::Text.to_unicode(win_name)
        dns_domain = Rex::Text.to_unicode(dns_domain)
        dns_name = Rex::Text.to_unicode(dns_name)
        # Make the AV_PAIRs
        addr_list  = ''
        addr_list  << [2, win_domain.length].pack('vv') + win_domain
        addr_list  << [1, win_name.length].pack('vv') + win_name
        addr_list  << [4, dns_domain.length].pack('vv') + dns_domain
        addr_list  << [3, dns_name.length].pack('vv') + dns_name
        addr_list  << [7, 8].pack('vv') + timestamp

        # Windows Seven / 2008r2 Request this type if in local security policies,
        # Microsoft network server : Server SPN target name validation level is set to <Required from client>
        # otherwise it send an STATUS_ACCESS_DENIED packet
        if spnopt[:use_spn]
                spn= Rex::Text.to_unicode("cifs/#{spnopt[:name] || 'unknow'}")
                addr_list  << [9, spn.length].pack('vv') + spn
        end

        # MAY BE USEFUL FOR FUTURE
        # Seven (client) add at least one more av that is of type MsAvRestrictions (8)
        # maybe this will be usefull with future windows OSs but has no use at all for the moment afaik
        # restriction_encoding =      [48,0,0,0].pack("VVV") + # Size, Z4, IntegrityLevel, SubjectIntegrityLevel
        #                     Rex::Text.rand_text(32)   # MachineId generated on startup on win7 and above
        # addr_list  << [8, restriction_encoding.length].pack('vv') + restriction_encoding

        # Seven (client) and maybe others versions also add an av of type MsvChannelBindings (10) but the hash is "\x00" * 16
        # addr_list  << [10, 16].pack('vv') + "\x00" * 16


        addr_list  << [0, 0].pack('vv')
        ntlm_clientchallenge =        [1,1,0,0].pack("CCvV") + #RespType, HiRespType, Reserved1, Reserved2
                                timestamp + #Timestamp
                                client_challenge +         #clientchallenge
                                [0].pack("V")  +   #Reserved3
                                addr_list + "\x00" * 4

end
make_ntlmv2_secblob_success() click to toggle source

GSS BLOB Usefull for SMB Success

# File lib/rex/proto/ntlm/utils.rb, line 321
def self.make_ntlmv2_secblob_success
        blob =
                "\xa1" + self.asn1encode(
                        "\x30" + self.asn1encode(
                                "\xa0" + self.asn1encode(
                                        "\x0a" + self.asn1encode(
                                                "\x00"
                                        )
                                )
                        )
                )
        return blob
end
make_simple_negotiate_secblob_resp() click to toggle source

GSS BLOB usefull for SMB_NEGOCIATE_RESPONSE message mechTypes: 2 items :

-MechType: 1.3.6.1.4.1.311.2.2.30 (SNMPv2-SMI::enterprises.311.2.2.30)
-MechType: 1.3.6.1.4.1.311.2.2.10 (NTLMSSP - Microsoft NTLM Security Support Provider)

this is the default on Win7

# File lib/rex/proto/ntlm/utils.rb, line 62
def self.make_simple_negotiate_secblob_resp
        blob =
        "\x60" + self.asn1encode(
                "\x06" + self.asn1encode(
                        "\x2b\x06\x01\x05\x05\x02"
                ) +
                "\xa0" + self.asn1encode(
                        "\x30" + self.asn1encode(
                                "\xa0" + self.asn1encode(
                                        "\x30" + self.asn1encode(
                                                "\x06" + self.asn1encode(
                                                        "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
                                                )
                                        )
                                )
                        )
                )
        )

        return blob
end
parse_ntlm_type_2_blob(blob) click to toggle source

Parse an ntlm type 2 challenge blob and return usefull data

# File lib/rex/proto/ntlm/utils.rb, line 375
def self.parse_ntlm_type_2_blob(blob)
        data = {}
        # Extract the NTLM challenge key the lazy way
        cidx = blob.index("NTLMSSP\x00\x02\x00\x00\x00")

        if not cidx
                raise XCEPT::NTLMMissingChallenge
        end

        data[:challenge_key] = blob[cidx + 24, 8]

        data[:server_ntlmssp_flags] = blob[cidx + 20, 4].unpack("V")[0]

        # Extract the address list from the blob
        alist_len,alist_mlen,alist_off = blob[cidx + 40, 8].unpack("vvV")
        alist_buf = blob[cidx + alist_off, alist_len]

        while(alist_buf.length > 0)
                atype, alen = alist_buf.slice!(0,4).unpack('vv')
                break if atype == 0x00
                addr = alist_buf.slice!(0, alen)
                case atype
                when 1
                        #netbios name
                        data[:default_name] =  addr.gsub("\x00", '')
                when 2
                        #netbios domain
                        data[:default_domain] = addr.gsub("\x00", '')
                when 3
                        #dns name
                        data[:dns_host_name] =  addr.gsub("\x00", '')
                when 4
                        #dns domain
                        data[:dns_domain_name] =  addr.gsub("\x00", '')
                when 5
                        #The FQDN of the forest.
                when 6
                        #A 32-bit value indicating server or client configuration
                when 7
                        #Client time
                        data[:chall_MsvAvTimestamp] = addr
                when 8
                        #A Restriction_Encoding structure
                when 9
                        #The SPN of the target server.
                when 10
                        #A channel bindings hash.
                end
        end
        return data
end
time_unix_to_smb(unix_time) click to toggle source

duplicate from lib/rex/proto/smb/utils cause we only need this fonction from Rex::Proto::SMB::Utils

Convert a unix timestamp to a 64-bit signed server time
# File lib/rex/proto/ntlm/utils.rb, line 16
def self.time_unix_to_smb(unix_time)
        t64 = (unix_time + 11644473600) * 10000000
        thi = (t64 & 0xffffffff00000000) >> 32
        tlo = (t64 & 0x00000000ffffffff)
        return [thi, tlo]
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.