@@ -9,7 +9,6 @@ module Msf
9
9
module Exploit ::Remote ::MsSamr
10
10
11
11
include Msf ::Exploit ::Remote ::SMB ::Client ::Authenticated
12
- include Msf ::Auxiliary ::Report
13
12
14
13
class MsSamrError < StandardError ; end
15
14
class MsSamrConnectionError < MsSamrError ; end
@@ -19,147 +18,8 @@ class MsSamrUnexpectedReplyError < MsSamrError; end
19
18
class MsSamrUnknownError < MsSamrError ; end
20
19
class MsSamrBadConfigError < MsSamrError ; end
21
20
22
- ComputerInfo = Struct . new ( :name , :password )
23
21
SamrConnection = Struct . new ( :samr , :server_handle , :domain_handle , :domain_name )
24
22
25
- def initialize ( info = { } )
26
- super
27
-
28
- register_options ( [
29
- OptString . new ( 'COMPUTER_NAME' , [ false , 'The computer name' ] ) ,
30
- OptString . new ( 'COMPUTER_PASSWORD' , [ false , 'The password for the new computer' ] ) ,
31
- ] , Msf ::Exploit ::Remote ::MsSamr )
32
- end
33
-
34
- def add_computer ( opts = { } )
35
- tree = opts [ :tree ] || connect_ipc
36
-
37
- samr_con = connect_samr ( tree )
38
-
39
- computer_name = opts [ :computer_name ] || datastore [ 'COMPUTER_NAME' ]
40
- if computer_name . blank?
41
- computer_name = random_hostname
42
- 4 . downto ( 0 ) do |attempt |
43
- break if samr_con . samr . samr_lookup_names_in_domain (
44
- domain_handle : samr_con . domain_handle ,
45
- names : [ computer_name ]
46
- ) . nil?
47
-
48
- computer_name = random_hostname
49
- raise MsSamrBadConfigError , 'Could not find an unused computer name.' if attempt == 0
50
- end
51
- else
52
- if samr_con . samr . samr_lookup_names_in_domain ( domain_handle : samr_con . domain_handle , names : [ computer_name ] )
53
- raise MsSamrBadConfigError , 'The specified computer name already exists.'
54
- end
55
- end
56
-
57
- result = samr_con . samr . samr_create_user2_in_domain (
58
- domain_handle : samr_con . domain_handle ,
59
- name : computer_name ,
60
- account_type : RubySMB ::Dcerpc ::Samr ::USER_WORKSTATION_TRUST_ACCOUNT ,
61
- desired_access : RubySMB ::Dcerpc ::Samr ::USER_FORCE_PASSWORD_CHANGE | RubySMB ::Dcerpc ::Samr ::MAXIMUM_ALLOWED
62
- )
63
-
64
- user_handle = result [ :user_handle ]
65
- if datastore [ 'COMPUTER_PASSWORD' ] . blank?
66
- computer_password = Rex ::Text . rand_text_alphanumeric ( 32 )
67
- else
68
- computer_password = datastore [ 'COMPUTER_PASSWORD' ]
69
- end
70
-
71
- user_info = RubySMB ::Dcerpc ::Samr ::SamprUserInfoBuffer . new (
72
- tag : RubySMB ::Dcerpc ::Samr ::USER_INTERNAL4_INFORMATION_NEW ,
73
- member : RubySMB ::Dcerpc ::Samr ::SamprUserInternal4InformationNew . new (
74
- i1 : {
75
- password_expired : 1 ,
76
- which_fields : RubySMB ::Dcerpc ::Samr ::USER_ALL_NTPASSWORDPRESENT | RubySMB ::Dcerpc ::Samr ::USER_ALL_PASSWORDEXPIRED
77
- } ,
78
- user_password : {
79
- buffer : RubySMB ::Dcerpc ::Samr ::SamprEncryptedUserPasswordNew . encrypt_password (
80
- computer_password ,
81
- @simple . client . application_key
82
- )
83
- }
84
- )
85
- )
86
- samr_con [ :samr ] . samr_set_information_user2 (
87
- user_handle : user_handle ,
88
- user_info : user_info
89
- )
90
-
91
- user_info = RubySMB ::Dcerpc ::Samr ::SamprUserInfoBuffer . new (
92
- tag : RubySMB ::Dcerpc ::Samr ::USER_CONTROL_INFORMATION ,
93
- member : RubySMB ::Dcerpc ::Samr ::UserControlInformation . new (
94
- user_account_control : RubySMB ::Dcerpc ::Samr ::USER_WORKSTATION_TRUST_ACCOUNT
95
- )
96
- )
97
- samr_con . samr . samr_set_information_user2 (
98
- user_handle : user_handle ,
99
- user_info : user_info
100
- )
101
- print_good ( "Successfully created #{ samr_con . domain_name } \\ #{ computer_name } " )
102
- print_good ( " Password: #{ computer_password } " )
103
- print_good ( " SID: #{ get_computer_sid ( samr_con , computer_name ) } " )
104
- report_creds ( samr_con . domain_name , computer_name , computer_password )
105
-
106
- ComputerInfo . new ( computer_name , computer_password )
107
-
108
- rescue RubySMB ::Dcerpc ::Error ::SamrError => e
109
- raise MsSamrUnknownError , "A DCERPC SAMR error occurred: #{ e . message } "
110
- ensure
111
- if samr_con
112
- samr_con . samr . close_handle ( user_handle ) if user_handle
113
- samr_con . samr . close_handle ( samr_con . domain_handle ) if samr_con . domain_handle
114
- samr_con . samr . close_handle ( samr_con . server_handle ) if samr_con . server_handle
115
- end
116
- end
117
-
118
- def delete_computer ( opts = { } )
119
- tree = opts [ :tree ] || connect_ipc
120
-
121
- samr_con = connect_samr ( tree )
122
-
123
- computer_name = opts [ :computer_name ] || datastore [ 'COMPUTER_NAME' ]
124
- if computer_name . blank?
125
- raise MsSamrBadConfigError , 'Unable to delete the computer account since its name is unknown'
126
- end
127
-
128
- details = samr_con . samr . samr_lookup_names_in_domain ( domain_handle : samr_con . domain_handle , names : [ computer_name ] )
129
- raise MsSamrBadConfigError , 'The specified computer was not found.' if details . nil?
130
- details = details [ computer_name ]
131
-
132
- user_handle = samr_con . samr . samr_open_user ( domain_handle : samr_con . domain_handle , user_id : details [ :rid ] )
133
- samr_con . samr . samr_delete_user ( user_handle : user_handle )
134
- print_good ( 'The specified computer has been deleted.' )
135
- rescue RubySMB ::Dcerpc ::Error ::SamrError => e
136
- # `user_handle` only needs to be closed if an error occurs in `samr_delete_user`
137
- # If this method succeed, the server took care of closing the handle
138
- samr_con . samr . close_handle ( user_handle ) if user_handle
139
- raise MsSamrUnknownError , "Could not delete the computer #{ computer_name } : #{ e . message } "
140
- ensure
141
- samr_con . samr . close_handle ( samr_con . domain_handle ) if samr_con . domain_handle
142
- samr_con . samr . close_handle ( samr_con . server_handle ) if samr_con . server_handle
143
- end
144
-
145
- def lookup_computer ( opts = { } )
146
- tree = opts [ :tree ] || connect_ipc
147
-
148
- samr_con = connect_samr ( tree )
149
-
150
- computer_name = opts [ :computer_name ] || datastore [ 'COMPUTER_NAME' ]
151
- if computer_name . blank?
152
- raise MsSamrBadConfigError , 'Unable to lookup the computer account since its name is unknown'
153
- end
154
-
155
- sid = get_computer_sid ( samr_con , computer_name )
156
- print_good ( "Found #{ samr_con . domain_name } \\ #{ computer_name } (SID: #{ sid } )" )
157
- ensure
158
- samr_con . samr . close_handle ( samr_con . domain_handle ) if samr_con . domain_handle
159
- samr_con . samr . close_handle ( samr_con . server_handle ) if samr_con . server_handle
160
- end
161
-
162
-
163
23
module_function
164
24
165
25
def connect_ipc
@@ -204,7 +64,7 @@ def connect_samr(tree)
204
64
raise MsSamrUnexpectedReplyError , "Connection failed (DCERPC fault: #{ e . status_name } )"
205
65
end
206
66
207
- if datastore [ 'SMBDomain' ] . blank? || datastore [ 'SMBDomain' ] == '.'
67
+ if domain . blank? || domain == '.'
208
68
all_domains = samr . samr_enumerate_domains_in_sam_server ( server_handle : server_handle ) . map ( &:to_s ) . map ( &:encode )
209
69
all_domains . delete ( 'Builtin' )
210
70
if all_domains . empty?
@@ -217,7 +77,7 @@ def connect_samr(tree)
217
77
domain_name = all_domains . first
218
78
print_status ( "Using automatically identified domain: #{ domain_name } " )
219
79
else
220
- domain_name = datastore [ 'SMBDomain' ]
80
+ domain_name = domain
221
81
end
222
82
223
83
domain_sid = samr . samr_lookup_domain ( server_handle : server_handle , name : domain_name )
@@ -232,53 +92,5 @@ def connect_samr(tree)
232
92
elog ( e . message , error : e )
233
93
raise MsSamrUnknownError , e . message
234
94
end
235
-
236
- def random_hostname ( prefix : 'DESKTOP' )
237
- "#{ prefix } -#{ Rex ::Text . rand_base ( 8 , '' , ( 'A' ..'Z' ) . to_a + ( '0' ..'9' ) . to_a ) } $"
238
- end
239
-
240
- def report_creds ( domain , username , password )
241
- service_data = {
242
- address : datastore [ 'RHOST' ] ,
243
- port : datastore [ 'RPORT' ] ,
244
- service_name : 'smb' ,
245
- protocol : 'tcp' ,
246
- workspace_id : myworkspace_id
247
- }
248
-
249
- credential_data = {
250
- module_fullname : fullname ,
251
- origin_type : :service ,
252
- private_data : password ,
253
- private_type : :password ,
254
- username : username ,
255
- realm_key : Metasploit ::Model ::Realm ::Key ::ACTIVE_DIRECTORY_DOMAIN ,
256
- realm_value : domain
257
- } . merge ( service_data )
258
-
259
- credential_core = create_credential ( credential_data )
260
-
261
- login_data = {
262
- core : credential_core ,
263
- status : Metasploit ::Model ::Login ::Status ::UNTRIED
264
- } . merge ( service_data )
265
-
266
- create_credential_login ( login_data )
267
- end
268
-
269
- def get_computer_sid ( samr_con , computer_name )
270
- details = samr_con . samr . samr_lookup_names_in_domain (
271
- domain_handle : samr_con . domain_handle ,
272
- names : [ computer_name ]
273
- )
274
- raise MsSamrNotFoundError , 'The computer was not found.' if details . nil?
275
-
276
- details = details [ computer_name ]
277
- samr_con . samr . samr_rid_to_sid (
278
- object_handle : samr_con . domain_handle ,
279
- rid : details [ :rid ]
280
- ) . to_s
281
- end
282
-
283
95
end
284
96
end
0 commit comments