Skip to content

Commit 39b3515

Browse files
committed
Update module to support ruby_smb3.3.9 and support DB connection
1 parent 5c7b375 commit 39b3515

File tree

1 file changed

+49
-30
lines changed

1 file changed

+49
-30
lines changed

modules/auxiliary/scanner/dcerpc/nrpc_enumusers.rb

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
##
55

66
class MetasploitModule < Msf::Auxiliary
7+
include Msf::Auxiliary::Report
78
include Msf::Auxiliary::Scanner
89
include Msf::Exploit::Remote::DCERPC
910
Netlogon = RubySMB::Dcerpc::Netlogon
11+
@@dport = nil
1012

1113
def initialize(info = {})
1214
super(
@@ -35,50 +37,64 @@ def initialize(info = {})
3537
register_options(
3638
[
3739
OptPort.new('RPORT', [false, 'The netlogon RPC port']),
38-
OptPath.new('USER_FILE', [true, 'Path to the file containing the list of usernames to enumerate'])
40+
OptPath.new('USER_FILE', [true, 'Path to the file containing the list of usernames to enumerate']),
41+
OptBool.new('DB_ALL_USERS', [ false, "Add all enumerated usernames to the database", false ])
3942
]
4043
)
4144
end
4245

43-
class DsrGetDCNameEx2Request < BinData::Record
44-
attr_reader :opnum
45-
46-
endian :little
47-
48-
uint32 :computer_name, initial_value: 0x00000000
49-
logonsrv_handle :account_name
50-
ndr_uint32 :allowable_account_control_bits, initial_value: 0x200
51-
uint32 :domain_name, initial_value: 0x00000000
52-
uint32 :guid, initial_value: 0x00000000
53-
uint32 :site_name, initial_value: 0x00000000
54-
uint32 :flags, initial_value: 0x00000000
55-
56-
def initialize_instance
57-
super
58-
@opnum = 34
59-
end
60-
end
61-
6246
def bind_to_netlogon_service
63-
@dport = datastore['RPORT']
64-
if @dport.nil? || @dport == 0
65-
@dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], Netlogon::UUID, '1.0', 'ncacn_ip_tcp')
66-
fail_with(Failure::NotFound, 'Could not determine the RPC port used by the Microsoft Netlogon Server') unless @dport
47+
@@dport = datastore['RPORT']
48+
if @@dport.nil? || @@dport == 0
49+
@@dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], Netlogon::UUID, '1.0', 'ncacn_ip_tcp')
50+
fail_with(Failure::NotFound, 'Could not determine the RPC port used by the Microsoft Netlogon Server') unless @@dport
6751
end
68-
handle = dcerpc_handle(Netlogon::UUID, '1.0', 'ncacn_ip_tcp', [@dport])
52+
handle = dcerpc_handle(Netlogon::UUID, '1.0', 'ncacn_ip_tcp', [@@dport])
6953
print_status("Binding to #{handle}...")
7054
dcerpc_bind(handle)
7155
end
7256

7357
def dsr_get_dc_name_ex2(username)
74-
request = DsrGetDCNameEx2Request.new(account_name: username)
75-
58+
request = Netlogon.const_get("DsrGetDcNameEx2Request").new(
59+
computer_name: nil,
60+
account_name: username,
61+
allowable_account_control_bits: 0x200,
62+
domain_name: nil,
63+
domain_guid: nil,
64+
site_name: nil,
65+
flags: 0x00000000
66+
)
7667
begin
7768
raw_response = dcerpc.call(request.opnum, request.to_binary_s)
7869
rescue Rex::Proto::DCERPC::Exceptions::Fault
7970
fail_with(Failure::UnexpectedReply, "The Netlogon RPC request failed for username: #{username}")
8071
end
81-
raw_response
72+
Netlogon.const_get("DsrGetDcNameEx2Response").read(raw_response)
73+
end
74+
75+
def report_username(domain, username)
76+
service_data = {
77+
address: datastore['RHOST'],
78+
port: @@dport,
79+
service_name: 'netlogon',
80+
protocol: 'tcp',
81+
workspace_id: myworkspace_id
82+
}
83+
84+
credential_data = {
85+
origin_type: :service,
86+
module_fullname: fullname,
87+
username: username,
88+
realm_key: Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN,
89+
realm_value: domain,
90+
}.merge(service_data)
91+
92+
login_data = {
93+
core: create_credential(credential_data),
94+
status: Metasploit::Model::Login::Status::UNTRIED
95+
}.merge(service_data)
96+
97+
create_credential_login(login_data)
8298
end
8399

84100
def run_host(_ip)
@@ -106,8 +122,11 @@ def load_usernames(file_path)
106122

107123
def enumerate_user(username)
108124
response = dsr_get_dc_name_ex2(username)
109-
if response[-4, 4] == "\x00\x00\x00\x00"
110-
print_good("#{username} exists")
125+
if response.error_status == 0
126+
print_good("#{username} exists -> DC: #{response.domain_controller_info.domain_controller_name.encode('UTF-8')}")
127+
if datastore['DB_ALL_USERS']
128+
report_username(response.domain_controller_info.domain_name.encode('UTF-8'), username)
129+
end
111130
else
112131
print_error("#{username} does not exist")
113132
end

0 commit comments

Comments
 (0)