1
1
##
2
- # ## This file is part of the Metasploit Framework and may be subject to
2
+ # This file is part of the Metasploit Framework and may be subject to
3
3
# redistribution and commercial restrictions. Please see the Metasploit
4
4
# Framework web site for more information on licensing and terms of use.
5
- # http://metasploit.com/framework/
5
+ # http://metasploit.com/framework/
6
6
##
7
7
8
+
8
9
require 'msf/core'
9
10
require 'rex'
10
11
require 'msf/core/post/common'
@@ -17,35 +18,42 @@ class Metasploit3 < Msf::Post
17
18
include Msf ::Post ::Common
18
19
19
20
def initialize ( info = { } )
20
- super (
21
- 'Name' => 'Windows Local Admin Search' ,
21
+ super ( update_info ( info ,
22
+ 'Name' => 'Windows Gather Local Admin Search' ,
22
23
'Description' => %q{
23
- This module will identify systems in a given range that the
24
+ This module will identify systems in a given range that the
24
25
supplied domain user (should migrate into a user pid) has administrative
25
- access to by using the windows api OpenSCManagerA to establishing a handle
26
+ access to by using the Windows API OpenSCManagerA to establishing a handle
26
27
to the remote host. Additionally it can enumerate logged in users and group
27
- membership via windows api NetWkstaUserEnum and NetUserGetGroups.
28
- } ,
28
+ membership via Windows API NetWkstaUserEnum and NetUserGetGroups.
29
+ } ,
29
30
'License' => MSF_LICENSE ,
30
- 'Version' => '$Revision: 14767 $' ,
31
- 'Author' => [ 'Brandon McCann "zeknox" <bmccann [at] accuvant.com>' , 'Thomas McCarthy "smilingraccoon" <smilingraccoon [at] gmail.com>' , 'Royce Davis "r3dy" <rdavis [at] accuvant.com>' ] ,
31
+ 'Author' =>
32
+ [
33
+ 'Brandon McCann "zeknox" <bmccann[at]accuvant.com>' ,
34
+ 'Thomas McCarthy "smilingraccoon" <smilingraccoon[at]gmail.com>' ,
35
+ 'Royce Davis "r3dy" <rdavis[at]accuvant.com>'
36
+ ] ,
32
37
'Platform' => [ 'windows' ] ,
33
38
'SessionTypes' => [ 'meterpreter' ]
34
- )
39
+ ) )
35
40
36
41
register_options (
37
42
[
38
43
OptBool . new ( 'ENUM_USERS' , [ true , 'Enumerates logged on users.' , true ] ) ,
39
44
OptBool . new ( 'ENUM_GROUPS' , [ false , 'Enumerates groups for identified users.' , true ] ) ,
40
- OptString . new ( 'DOMAIN' , [ false , 'Domain to enumerate user\'s groups for' , nil ] ) ,
41
- OptString . new ( 'DOMAIN_CONTROLLER' , [ false , 'Domain Controller to query groups' , nil ] )
42
-
45
+ OptString . new ( 'DOMAIN' , [ false , 'Domain to enumerate user\'s groups for' ] ) ,
46
+ OptString . new ( 'DOMAIN_CONTROLLER' , [ false , 'Domain Controller to query groups' ] )
43
47
] , self . class )
44
48
end
45
49
46
50
def setup
47
51
super
48
52
53
+ # This datastore option can be modified during runtime.
54
+ # Saving it here so the modified value remains with this module.
55
+ @domain_controller = datastore [ 'DOMAIN_CONTROLLER' ]
56
+
49
57
if is_system?
50
58
# running as SYSTEM and will not pass any network credentials
51
59
print_error "Running as SYSTEM, module should be run with USER level rights"
@@ -59,7 +67,7 @@ def setup
59
67
datastore [ 'DOMAIN' ] = user . split ( '\\' ) [ 0 ]
60
68
end
61
69
62
- if datastore [ 'DOMAIN_CONTROLLER' ] . nil? and datastore [ 'ENUM_GROUPS' ]
70
+ if @domain_controll . nil? and datastore [ 'ENUM_GROUPS' ]
63
71
@dc_error = false
64
72
65
73
# Uses DC which applied policy since it would be a DC this device normally talks to
@@ -72,7 +80,7 @@ def setup
72
80
73
81
# Check if RSOP data exists, if not disable group check
74
82
unless res =~ /does not have RSOP data./
75
- datastore [ 'DOMAIN_CONTROLLER' ] = /Group Policy was applied from:\s *(.*)\s */ . match ( res ) [ 1 ] . chomp
83
+ @domain_controller = /Group Policy was applied from:\s *(.*)\s */ . match ( res ) [ 1 ] . chomp
76
84
else
77
85
@dc_error = true
78
86
print_error ( "User never logged into device, will not enumerate groups or manually specify DC." )
@@ -89,13 +97,19 @@ def run_host(ip)
89
97
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa370669(v=vs.85).aspx
90
98
# enumerate logged in users
91
99
def enum_users ( host )
100
+ userlist = Array . new
101
+
92
102
begin
93
103
# Connect to host and enumerate logged in users
94
104
winsessions = client . railgun . netapi32 . NetWkstaUserEnum ( "\\ \\ #{ host } " , 1 , 4 , -1 , 4 , 4 , nil )
95
105
rescue ::Exception => e
96
106
print_error ( "Issue enumerating users on #{ host } " )
97
- print_error ( e . backtrace ) if datastore [ 'VERBOSE' ]
107
+ vprint_error ( e . backtrace )
108
+ return userlist
98
109
end
110
+
111
+ return userlist if winsessions . nil?
112
+
99
113
count = winsessions [ 'totalentries' ] * 2
100
114
startmem = winsessions [ 'bufptr' ]
101
115
@@ -105,7 +119,8 @@ def enum_users(host)
105
119
mem = client . railgun . memread ( startmem , 8 *count )
106
120
rescue ::Exception => e
107
121
print_error ( "Issue reading memory for #{ host } " )
108
- print_error ( e . backtrace ) if datastore [ 'VERBOSE' ]
122
+ vprint_error ( e . backtrace )
123
+ return userlist
109
124
end
110
125
# For each entry returned, get domain and name of logged in user
111
126
begin
@@ -137,7 +152,7 @@ def enum_users(host)
137
152
}
138
153
rescue ::Exception => e
139
154
print_error ( "Issue enumerating users on #{ host } " )
140
- print_error ( e . backtrace ) if datastore [ 'VERBOSE' ]
155
+ vprint_error ( e . backtrace )
141
156
end
142
157
return userlist
143
158
end
@@ -154,7 +169,8 @@ def enum_groups(user)
154
169
155
170
rescue ::Exception => e
156
171
print_error ( "Issue connecting to DC, try manually setting domain and DC" )
157
- print_error ( e . backtrace ) if datastore [ 'VERBOSE' ]
172
+ vprint_error ( e . backtrace )
173
+ return grouplist
158
174
end
159
175
160
176
count = usergroups [ 'totalentries' ]
@@ -165,7 +181,8 @@ def enum_groups(user)
165
181
mem = client . railgun . memread ( startmem , 8 *count )
166
182
rescue ::Exception => e
167
183
print_error ( "Issue reading memory for groups for user #{ user } " )
168
- print_error ( e . backtrace ) if datastore [ 'VERBOSE' ]
184
+ vprint_error ( e . backtrace )
185
+ return grouplist
169
186
end
170
187
171
188
begin
@@ -185,7 +202,8 @@ def enum_groups(user)
185
202
186
203
rescue ::Exception => e
187
204
print_error("Issue enumerating groups for user #{ user } , check domain")
188
- print_error(e.backtrace) if datastore['VERBOSE']
205
+ vprint_error(e.backtrace)
206
+ return grouplist
189
207
end
190
208
191
209
return grouplist.chomp("\n\t- ")
@@ -226,21 +244,17 @@ def connect(host)
226
244
227
245
# Write to notes database
228
246
def db_note(host, data, type)
229
- if db
230
- report_note(
231
- :type => type,
232
- :data => data,
233
- :host => host,
234
- :update => :unique_data
235
- )
236
- end
247
+ report_note(
248
+ :type => type,
249
+ :data => data,
250
+ :host => host,
251
+ :update => :unique_data
252
+ )
237
253
end
238
254
239
255
# Write to loot database
240
256
def db_loot(host, user, type)
241
- if db
242
- p = store_loot(type, 'text/plain', host, "#{ host } :#{ user } ", 'hosts_localadmin.txt', user)
243
- print_status("User data stored in: #{ p } ") if datastore['VERBOSE']
244
- end
257
+ p = store_loot(type, 'text/plain', host, "#{ host } :#{ user } ", 'hosts_localadmin.txt', user)
258
+ vprint_status("User data stored in: #{ p } ")
245
259
end
246
260
end
0 commit comments