Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
1N3
GitHub Repository: 1N3/Sn1per
Path: blob/master/bin/samrdump.py
2960 views
1
#!/usr/bin/python
2
# Copyright (c) 2003-2015 CORE Security Technologies
3
#
4
# This software is provided under under a slightly modified version
5
# of the Apache Software License. See the accompanying LICENSE file
6
# for more information.
7
#
8
# Description: DCE/RPC SAMR dumper.
9
#
10
# Author:
11
# Javier Kohen <[email protected]>
12
# Alberto Solino (@agsolino)
13
#
14
# Reference for:
15
# DCE/RPC for SAMR
16
17
import sys
18
import logging
19
import argparse
20
21
from impacket.examples import logger
22
from impacket import version
23
from impacket.nt_errors import STATUS_MORE_ENTRIES
24
from impacket.dcerpc.v5 import transport, samr
25
from impacket.dcerpc.v5.rpcrt import DCERPCException
26
27
28
class ListUsersException(Exception):
29
pass
30
31
class SAMRDump:
32
KNOWN_PROTOCOLS = {
33
'139/SMB': (r'ncacn_np:%s[\pipe\samr]', 139),
34
'445/SMB': (r'ncacn_np:%s[\pipe\samr]', 445),
35
}
36
37
38
def __init__(self, protocols = None,
39
username = '', password = '', domain = '', hashes = None, aesKey=None, doKerberos = False):
40
if not protocols:
41
self.__protocols = SAMRDump.KNOWN_PROTOCOLS.keys()
42
else:
43
self.__protocols = [protocols]
44
45
self.__username = username
46
self.__password = password
47
self.__domain = domain
48
self.__lmhash = ''
49
self.__nthash = ''
50
self.__aesKey = aesKey
51
self.__doKerberos = doKerberos
52
if hashes is not None:
53
self.__lmhash, self.__nthash = hashes.split(':')
54
55
56
def dump(self, addr):
57
"""Dumps the list of users and shares registered present at
58
addr. Addr is a valid host name or IP address.
59
"""
60
61
logging.info('Retrieving endpoint list from %s' % addr)
62
63
# Try all requested protocols until one works.
64
entries = []
65
for protocol in self.__protocols:
66
protodef = SAMRDump.KNOWN_PROTOCOLS[protocol]
67
port = protodef[1]
68
69
logging.info("Trying protocol %s..." % protocol)
70
rpctransport = transport.SMBTransport(addr, port, r'\samr', self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, doKerberos = self.__doKerberos)
71
72
try:
73
entries = self.__fetchList(rpctransport)
74
except Exception, e:
75
logging.critical(str(e))
76
else:
77
# Got a response. No need for further iterations.
78
break
79
80
# Display results.
81
82
for entry in entries:
83
(username, uid, user) = entry
84
base = "%s (%d)" % (username, uid)
85
print base + '/FullName:', user['FullName']
86
print base + '/UserComment:', user['UserComment']
87
print base + '/PrimaryGroupId:', user['PrimaryGroupId']
88
print base + '/BadPasswordCount:', user['BadPasswordCount']
89
print base + '/LogonCount:', user['LogonCount']
90
91
if entries:
92
num = len(entries)
93
if 1 == num:
94
logging.info('Received one entry.')
95
else:
96
logging.info('Received %d entries.' % num)
97
else:
98
logging.info('No entries received.')
99
100
101
def __fetchList(self, rpctransport):
102
dce = rpctransport.get_dce_rpc()
103
104
entries = []
105
106
dce.connect()
107
dce.bind(samr.MSRPC_UUID_SAMR)
108
109
try:
110
resp = samr.hSamrConnect(dce)
111
serverHandle = resp['ServerHandle']
112
113
resp = samr.hSamrEnumerateDomainsInSamServer(dce, serverHandle)
114
domains = resp['Buffer']['Buffer']
115
116
print 'Found domain(s):'
117
for domain in domains:
118
print " . %s" % domain['Name']
119
120
logging.info("Looking up users in domain %s" % domains[0]['Name'])
121
122
resp = samr.hSamrLookupDomainInSamServer(dce, serverHandle,domains[0]['Name'] )
123
124
resp = samr.hSamrOpenDomain(dce, serverHandle = serverHandle, domainId = resp['DomainId'])
125
domainHandle = resp['DomainHandle']
126
127
status = STATUS_MORE_ENTRIES
128
enumerationContext = 0
129
while status == STATUS_MORE_ENTRIES:
130
try:
131
resp = samr.hSamrEnumerateUsersInDomain(dce, domainHandle, enumerationContext = enumerationContext)
132
except DCERPCException, e:
133
if str(e).find('STATUS_MORE_ENTRIES') < 0:
134
raise
135
resp = e.get_packet()
136
137
for user in resp['Buffer']['Buffer']:
138
r = samr.hSamrOpenUser(dce, domainHandle, samr.MAXIMUM_ALLOWED, user['RelativeId'])
139
print "Found user: %s, uid = %d" % (user['Name'], user['RelativeId'] )
140
info = samr.hSamrQueryInformationUser2(dce, r['UserHandle'],samr.USER_INFORMATION_CLASS.UserAllInformation)
141
entry = (user['Name'], user['RelativeId'], info['Buffer']['All'])
142
entries.append(entry)
143
samr.hSamrCloseHandle(dce, r['UserHandle'])
144
145
enumerationContext = resp['EnumerationContext']
146
status = resp['ErrorCode']
147
148
except ListUsersException, e:
149
logging.critical("Error listing users: %s" % e)
150
151
dce.disconnect()
152
153
return entries
154
155
156
# Process command-line arguments.
157
if __name__ == '__main__':
158
# Init the example's logger theme
159
logger.init()
160
print version.BANNER
161
162
parser = argparse.ArgumentParser(add_help = True, description = "This script downloads the list of users for the target system.")
163
164
parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>')
165
parser.add_argument('protocol', choices=SAMRDump.KNOWN_PROTOCOLS.keys(), nargs='?', default='445/SMB', help='transport protocol (default 445/SMB)')
166
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
167
168
group = parser.add_argument_group('authentication')
169
170
group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
171
group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)')
172
group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line')
173
group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication (128 or 256 bits)')
174
175
if len(sys.argv)==1:
176
parser.print_help()
177
sys.exit(1)
178
179
options = parser.parse_args()
180
181
if options.debug is True:
182
logging.getLogger().setLevel(logging.DEBUG)
183
else:
184
logging.getLogger().setLevel(logging.INFO)
185
186
import re
187
188
domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(options.target).groups('')
189
190
if domain is None:
191
domain = ''
192
193
if options.aesKey is not None:
194
options.k = True
195
196
if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None:
197
from getpass import getpass
198
password = getpass("Password:")
199
200
dumper = SAMRDump(options.protocol, username, password, domain, options.hashes, options.aesKey, options.k)
201
dumper.dump(address)
202
203