Skip to content

Commit

Permalink
Merge 344d04f into 93bed5e
Browse files Browse the repository at this point in the history
  • Loading branch information
zeroSteiner committed Sep 18, 2020
2 parents 93bed5e + 344d04f commit eb58e07
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 7 deletions.
4 changes: 3 additions & 1 deletion lib/ruby_smb/dcerpc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ module Dcerpc
require 'ruby_smb/dcerpc/rpc_security_attributes'
require 'ruby_smb/dcerpc/pdu_header'
require 'ruby_smb/dcerpc/srvsvc'
require 'ruby_smb/dcerpc/winreg'
require 'ruby_smb/dcerpc/svcctl'
require 'ruby_smb/dcerpc/winreg'
require 'ruby_smb/dcerpc/netlogon'
require 'ruby_smb/dcerpc/request'
require 'ruby_smb/dcerpc/response'
require 'ruby_smb/dcerpc/bind'
require 'ruby_smb/dcerpc/bind_ack'



# Bind to the remote server interface endpoint.
#
# @param options [Hash] the options to pass to the Bind request packet. At least, :endpoint must but provided with an existing Dcerpc class
Expand Down
82 changes: 82 additions & 0 deletions lib/ruby_smb/dcerpc/ndr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ module Ndr
VER_MAJOR = 2
VER_MINOR = 0

# An NDR Enum type as defined in
# [Transfer Syntax NDR - Enumerated Types](https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_02_05_01)
class NdrEnum < BinData::Int16le; end

# An NDR Conformant and Varying String representation as defined in
# [Transfer Syntax NDR - Conformant and Varying Strings](http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_04_02)
Expand Down Expand Up @@ -92,6 +95,85 @@ def set(v)
end
end

# An NDR Uni-dimensional Fixed Array of bytes representation as defined in:
# [Transfer Syntax NDR - NDR Constructed Types](https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_03_01)
class NdrFixedByteArray < BinData::BasePrimitive
optional_parameters :length, :pad_byte, :pad_front
default_parameters pad_byte: 0
mutually_exclusive_parameters :length, :value

def assign(val)
super(fixed_byte_array(val))
end

def snapshot
clamp_to_length(super)
end

class << self
def arg_processor
NdrFixedByteArrayArgProcessor.new
end
end

private

def clamp_to_length(val)
val = fixed_byte_array(val)
len = eval_parameter(:length) || val.length
if val.length > len
val = val.first(len)
elsif val.length < len
pad = eval_parameter(:pad_byte)
if get_parameter(:pad_front)
val = val.insert(0, *Array.new(len - val.length, pad))
else
val = val.fill(pad, val.length...len)
end
end

val
end

def fixed_byte_array(val)
val = val.bytes if val.is_a? String
val.to_ary
end

def read_and_return_value(io)
len = eval_parameter(:length) || 0
io.readbytes(len)
end

def sensible_default
[ ]
end

def value_to_binary_string(val)
clamp_to_length(val).pack('C*')
end

class NdrFixedByteArrayArgProcessor < BinData::BaseArgProcessor
def sanitize_parameters!(obj_class, obj_params)
obj_params.must_be_integer(:length, :pad_byte)
obj_params.sanitize(:pad_byte) { |byte| sanitized_pad_byte(byte) }
end

private

def sanitized_pad_byte(byte)
if byte.is_a?(String)
raise ArgumentError, ':pad_byte must not contain more than 1 byte' if byte.bytesize > 1

byte = byte.ord
end
raise ArgumentError, ':pad_byte must be within the range of 0 - 255' unless ((byte >= 0) && (byte <= 255))

byte
end
end
end

# An NDR Context Handle representation as defined in
# [IDL Data Type Declarations - Basic Type Declarations](http://pubs.opengroup.org/onlinepubs/9629399/apdxn.htm#tagcjh_34_01)
class NdrContextHandle < BinData::Primitive
Expand Down
85 changes: 85 additions & 0 deletions lib/ruby_smb/dcerpc/netlogon.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module RubySMB
module Dcerpc
module Netlogon

# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/592edbc8-f6f1-40c0-9ab3-fe6725ac6d7e
UUID = '12345678-1234-abcd-ef00-01234567cffb'
VER_MAJOR = 1
VER_MINOR = 0

# Operation numbers
NETR_SERVER_REQ_CHALLENGE = 4
NETR_SERVER_AUTHENTICATE3 = 26
NETR_SERVER_PASSWORD_SET2 = 30

# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/3b224201-b531-43e2-8c79-b61f6dea8640
class LogonsrvHandle < Ndr::NdrLpStr; end

# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/d55e2632-7163-4f6c-b662-4b870e8cc1cd
class NetlogonCredential < Ndr::NdrFixedByteArray
default_parameters length: 8
end

# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/76c93227-942a-4687-ab9d-9d972ffabdab
class NetlogonAuthenticator < BinData::Record
endian :little

netlogon_credential :credential
uint32 :timestamp
end

# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/4d1235e3-2c96-4e9f-a147-3cb338a0d09f
class NetlogonSecureChannelType < Ndr::NdrEnum
# enum example from dmendel/bindata#38 https://github.com/dmendel/bindata/issues/38#issuecomment-46397163
ALL = {
0 => :NullSecureChannel,
1 => :MsvApSecureChannel,
2 => :WorkstationSecureChannel,
3 => :TrustedDnsDomainSecureChannel,
4 => :TrustedDomainSecureChannel,
5 => :UasServerSecureChannel,
6 => :ServerSecureChannel,
7 => :CdcServerSecureChannel
}
ALL.each_pair { |val,sym| const_set(sym.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').upcase, val) }
default_parameter assert: -> { ALL.keys.include? value }

def as_enum
ALL[value]
end

def assign(val)
if val.is_a? Symbol
val = ALL.key(val)
raise ArgumentError, 'invalid value name' if val.nil?
end

super
end
end

require 'ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request'
require 'ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response'
require 'ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request'
require 'ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response'

# Calculate the netlogon session key from the provided shared secret and
# challenges. The shared secret is an NTLM hash.
#
# @param shared_secret [String] the share secret between the client and the server
# @param client_challenge [String] the client challenge portion of the negotiation
# @param server_challenge [String] the server challenge portion of the negotiation
# @return [String] the session key for encryption
def self.calculate_session_key(shared_secret, client_challenge, server_challenge)
client_challenge = client_challenge.to_binary_s if client_challenge.is_a? NetlogonCredential
server_challenge = server_challenge.to_binary_s if server_challenge.is_a? NetlogonCredential

hmac = OpenSSL::HMAC.new(shared_secret, OpenSSL::Digest::SHA256.new)
hmac << client_challenge
hmac << server_challenge
hmac.digest.first(16)
end

end
end
end
28 changes: 28 additions & 0 deletions lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'ruby_smb/dcerpc/ndr'

module RubySMB
module Dcerpc
module Netlogon

# [3.5.4.4.2 NetrServerAuthenticate3 (Opnum 26)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/3a9ed16f-8014-45ae-80af-c0ecb06e2db9)
class NetrServerAuthenticate3Request < BinData::Record
attr_reader :opnum

endian :little

logonsrv_handle :primary_name
ndr_string :account_name
netlogon_secure_channel_type :secure_channel_type
ndr_string :computer_name
netlogon_credential :client_credential
uint32 :flags

def initialize_instance
super
@opnum = NETR_SERVER_AUTHENTICATE3
end

end
end
end
end
26 changes: 26 additions & 0 deletions lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require 'ruby_smb/dcerpc/ndr'

module RubySMB
module Dcerpc
module Netlogon

# [3.5.4.4.2 NetrServerAuthenticate3 (Opnum 26)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/3a9ed16f-8014-45ae-80af-c0ecb06e2db9)
class NetrServerAuthenticate3Response < BinData::Record
attr_reader :opnum

endian :little

netlogon_credential :server_credential
uint32 :negotiate_flags
uint32 :account_rid
uint32 :error_status

def initialize_instance
super
@opnum = NETR_SERVER_AUTHENTICATE3
end

end
end
end
end
25 changes: 25 additions & 0 deletions lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'ruby_smb/dcerpc/ndr'

module RubySMB
module Dcerpc
module Netlogon

# [3.5.4.4.1 NetrServerReqChallenge (Opnum 4)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/5ad9db9f-7441-4ce5-8c7b-7b771e243d32)
class NetrServerReqChallengeRequest < BinData::Record
attr_reader :opnum

endian :little

logonsrv_handle :primary_name
ndr_string :computer_name
netlogon_credential :client_challenge

def initialize_instance
super
@opnum = NETR_SERVER_REQ_CHALLENGE
end

end
end
end
end
24 changes: 24 additions & 0 deletions lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'ruby_smb/dcerpc/ndr'

module RubySMB
module Dcerpc
module Netlogon

# [3.5.4.4.1 NetrServerReqChallenge (Opnum 4)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/5ad9db9f-7441-4ce5-8c7b-7b771e243d32)
class NetrServerReqChallengeResponse < BinData::Record
attr_reader :opnum

endian :little

netlogon_credential :server_challenge
uint32 :error_status

def initialize_instance
super
@opnum = NETR_SERVER_REQ_CHALLENGE
end

end
end
end
end
5 changes: 5 additions & 0 deletions lib/ruby_smb/dcerpc/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class Request < BinData::Record
save_key_request RubySMB::Dcerpc::Winreg::REG_SAVE_KEY
string :default
end
choice 'Netlogon', selection: -> { opnum } do
netr_server_authenticate3_request RubySMB::Dcerpc::Netlogon::NETR_SERVER_AUTHENTICATE3
netr_server_req_challenge_request RubySMB::Dcerpc::Netlogon::NETR_SERVER_REQ_CHALLENGE
string :default
end
choice 'Srvsvc', selection: -> { opnum } do
net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host rescue '' }
string :default
Expand Down
6 changes: 4 additions & 2 deletions lib/ruby_smb/smb1/pipe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ class Pipe < File
def initialize(tree:, response:, name:)
raise ArgumentError, 'No Name Provided' if name.nil?
case name
when 'netlogon', '\\netlogon'
extend RubySMB::Dcerpc::Netlogon
when 'srvsvc', '\\srvsvc'
extend RubySMB::Dcerpc::Srvsvc
when 'winreg', '\\winreg'
extend RubySMB::Dcerpc::Winreg
when 'svcctl', '\\svcctl'
extend RubySMB::Dcerpc::Svcctl
when 'winreg', '\\winreg'
extend RubySMB::Dcerpc::Winreg
end
super(tree: tree, response: response, name: name)
end
Expand Down
10 changes: 6 additions & 4 deletions lib/ruby_smb/smb2/pipe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ class Pipe < File
def initialize(tree:, response:, name:)
raise ArgumentError, 'No Name Provided' if name.nil?
case name
when 'srvsvc'
when 'netlogon', '\\netlogon'
extend RubySMB::Dcerpc::Netlogon
when 'srvsvc', '\\srvsvc'
extend RubySMB::Dcerpc::Srvsvc
when 'winreg'
extend RubySMB::Dcerpc::Winreg
when 'svcctl'
when 'svcctl', '\\svcctl'
extend RubySMB::Dcerpc::Svcctl
when 'winreg', '\\winreg'
extend RubySMB::Dcerpc::Winreg
end
super(tree: tree, response: response, name: name)
end
Expand Down

0 comments on commit eb58e07

Please sign in to comment.