Skip to content

Commit

Permalink
Finish removing code from old work arounds
Browse files Browse the repository at this point in the history
  • Loading branch information
zeroSteiner committed Sep 13, 2024
1 parent dd6f303 commit e492eef
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 138 deletions.
1 change: 0 additions & 1 deletion lib/ruby_smb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
require 'openssl/cmac'
require 'windows_error'
require 'windows_error/nt_status'
require 'ruby_smb/ntlm/custom/string_encoder'
# A packet parsing and manipulation library for the SMB1 and SMB2 protocols
#
# [[MS-SMB] Server Message Block (SMB) Protocol Version 1](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
Expand Down
37 changes: 0 additions & 37 deletions lib/ruby_smb/ntlm.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require 'ruby_smb/ntlm/custom/string_encoder'

module RubySMB
module NTLM
# [[MS-NLMP] 2.2.2.5](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/99d90ff4-957f-4c8a-80e4-5bfe5a9a9832)
Expand Down Expand Up @@ -58,41 +56,6 @@ def to_s
"Version #{major}.#{minor} (Build #{build}); NTLM Current Revision #{ntlm_revision}"
end
end

class << self

# Generate a NTLMv2 Hash
# @param [String] user The username
# @param [String] password The password
# @param [String] target The domain or workstation to authenticate to
# @option opt :unicode (false) Unicode encode the domain
def ntlmv2_hash(user, password, target, opt={})
if Net::NTLM.is_ntlm_hash? password
decoded_password = Net::NTLM::EncodeUtil.decode_utf16le(password)
ntlmhash = [decoded_password.upcase[33,65]].pack('H32')
else
ntlmhash = Net::NTLM.ntlm_hash(password, opt)
end

if opt[:unicode]
# Uppercase operation on username containing non-ASCII characters
# after being unicode encoded with `EncodeUtil.encode_utf16le`
# doesn't play well. Upcase should be done before encoding.
user_upcase = Net::NTLM::EncodeUtil.decode_utf16le(user).upcase
user_upcase = Net::NTLM::EncodeUtil.encode_utf16le(user_upcase)
else
user_upcase = user.upcase
end
userdomain = user_upcase + target

unless opt[:unicode]
userdomain = Net::NTLM::EncodeUtil.encode_utf16le(userdomain)
end
OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, ntlmhash, userdomain)
end

end

end
end

Expand Down
77 changes: 3 additions & 74 deletions lib/ruby_smb/ntlm/client.rb
Original file line number Diff line number Diff line change
@@ -1,78 +1,7 @@
module RubySMB::NTLM
module Message
def deflag
security_buffers.inject(head_size) do |cur, a|
a[1].offset = cur
cur += a[1].data_size
has_flag?(:UNICODE) ? cur + cur % 2 : cur
end
end

def serialize
deflag
@alist.map { |n, f| f.serialize }.join + security_buffers.map { |n, f| f.value + (has_flag?(:UNICODE) ? "\x00".b * (f.value.length % 2) : '') }.join
end
end

class Client < Net::NTLM::Client
class Session < Net::NTLM::Client::Session
def authenticate!
calculate_user_session_key!
type3_opts = {
:lm_response => is_anonymous? ? "\x00".b : lmv2_resp,
:ntlm_response => is_anonymous? ? '' : ntlmv2_resp,
:domain => domain,
:user => username,
:workstation => workstation,
:flag => (challenge_message.flag & client.flags)
}
t3 = Net::NTLM::Message::Type3.create type3_opts
t3.extend(Message)
if negotiate_key_exchange?
t3.enable(:session_key)
rc4 = OpenSSL::Cipher.new("rc4")
rc4.encrypt
rc4.key = user_session_key
sk = rc4.update exported_session_key
sk << rc4.final
t3.session_key = sk
end
t3
end

def is_anonymous?
username == '' && password == ''
end

private

def use_oem_strings?
# @see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/99d90ff4-957f-4c8a-80e4-5bfe5a9a9832
!challenge_message.has_flag?(:UNICODE) && challenge_message.has_flag?(:OEM)
end

def ntlmv2_hash
@ntlmv2_hash ||= RubySMB::NTLM.ntlmv2_hash(username, password, domain, {:client_challenge => client_challenge, :unicode => !use_oem_strings?})
end

def calculate_user_session_key!
if is_anonymous?
# see MS-NLMP section 3.4
@user_session_key = "\x00".b * 16
else
@user_session_key = OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, ntlmv2_hash, nt_proof_str)
end
end
end

def init_context(resp = nil, channel_binding = nil)
if resp.nil?
@session = nil
type1_message
else
@session = Client::Session.new(self, Net::NTLM::Message.decode64(resp), channel_binding)
@session.authenticate!
end
end
# There was a bunch of code in here that was necessary in versions up to and including rubyntlm version 0.6.3.
# The class is kept because there are references to it that should be kept in place in case future alterations to
# rubyntlm are required.
end
end
22 changes: 0 additions & 22 deletions lib/ruby_smb/ntlm/custom/string_encoder.rb

This file was deleted.

13 changes: 10 additions & 3 deletions ruby_smb.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@ require 'ruby_smb/version'
Gem::Specification.new do |spec|
spec.name = 'ruby_smb'
spec.version = RubySMB::VERSION
spec.authors = ['Metasploit Hackers', 'David Maloney', 'James Lee', 'Dev Mohanty', 'Christophe De La Fuente']
spec.authors = [
'Metasploit Hackers',
'David Maloney',
'James Lee',
'Dev Mohanty',
'Christophe De La Fuente',
'Spencer McIntyre'
]
spec.email = ['[email protected]']
spec.summary = 'A pure Ruby implementation of the SMB Protocol Family'
spec.description = ''
spec.homepage = 'https://github.com/rapid7/ruby_smb'
spec.homepage = 'https://github.com/rapid7/ruby_smb'
spec.license = 'BSD-3-clause'

spec.files = `git ls-files -z`.split("\x0")
Expand All @@ -33,7 +40,7 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'rake'
spec.add_development_dependency 'yard'

spec.add_runtime_dependency 'rubyntlm'
spec.add_runtime_dependency 'rubyntlm', '>= 0.6.5'
spec.add_runtime_dependency 'windows_error', '>= 0.1.4'
spec.add_runtime_dependency 'bindata', '2.4.15'
spec.add_runtime_dependency 'openssl-ccm'
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/ruby_smb/ntlm/client/session_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

it 'returns a Type3 message' do
expect(session.authenticate!).to be_a Net::NTLM::Message::Type3
expect(session.authenticate!).to be_a RubySMB::NTLM::Message
expect(session.authenticate!).to be_a Net::NTLM::Message
end

context 'when it is anonymous' do
Expand Down

0 comments on commit e492eef

Please sign in to comment.