coercer.network.smb

  1#!/usr/bin/env python3
  2# -*- coding: utf-8 -*-
  3# File name          : smb.py
  4# Author             : Podalirius (@podalirius_)
  5# Date created       : 17 Sep 2022
  6
  7
  8import sys
  9from impacket.dcerpc.v5 import transport
 10from impacket.uuid import uuidtup_to_bin
 11from impacket.smbconnection import SMBConnection, SMB2_DIALECT_002, SMB2_DIALECT_21, SMB_DIALECT, SessionError
 12
 13
 14def init_smb_session(args, domain, username, password, address, lmhash, nthash, verbose=False):
 15    smbClient = SMBConnection(address, args.target_ip, sess_port=int(args.port))
 16    dialect = smbClient.getDialect()
 17    if dialect == SMB_DIALECT:
 18        if verbose:
 19            print("[debug] SMBv1 dialect used")
 20    elif dialect == SMB2_DIALECT_002:
 21        if verbose:
 22            print("[debug] SMBv2.0 dialect used")
 23    elif dialect == SMB2_DIALECT_21:
 24        if verbose:
 25            print("[debug] SMBv2.1 dialect used")
 26    else:
 27        if verbose:
 28            print("[debug] SMBv3.0 dialect used")
 29    if args.k is True:
 30        smbClient.kerberosLogin(username, password, domain, lmhash, nthash, args.aesKey, args.dc_ip)
 31    else:
 32        smbClient.login(username, password, domain, lmhash, nthash)
 33    if smbClient.isGuestSession() > 0:
 34        if verbose:
 35            print("[debug] GUEST Session Granted")
 36    else:
 37        if verbose:
 38            print("[debug] USER Session Granted")
 39    return smbClient
 40
 41
 42def try_login(credentials, target, port=445, verbose=False):
 43    """Documentation for try_login"""
 44    # Checking credentials if any
 45    if not credentials.is_anonymous():
 46        try:
 47            smbClient = SMBConnection(
 48                remoteName=target,
 49                remoteHost=target,
 50                sess_port=int(port)
 51            )
 52            smbClient.login(
 53                user=credentials.username,
 54                password=credentials.password,
 55                domain=credentials.domain,
 56                lmhash=credentials.lmhash,
 57                nthash=credentials.nthash
 58            )
 59        except Exception as e:
 60            print("[!] Could not login as '%s' with these credentials on '%s'." % (credentials.username, target))
 61            print("  | Error: %s" % str(e))
 62            return False
 63        else:
 64            return True
 65    else:
 66        return True
 67
 68
 69def list_remote_pipes(target, credentials, share='IPC$', maxdepth=-1, debug=False):
 70    """
 71    Function list_remote_pipes(target, credentials, share='IPC$', maxdepth=-1, debug=False)
 72    """
 73    pipes = []
 74    try:
 75        smbClient = SMBConnection(target, target, sess_port=int(445))
 76        dialect = smbClient.getDialect()
 77        if credentials.doKerberos is True:
 78            smbClient.kerberosLogin(credentials.username, credentials.password, credentials.domain, credentials.lmhash, credentials.nthash, credentials.aesKey, credentials.dc_ip)
 79        else:
 80            smbClient.login(credentials.username, credentials.password, credentials.domain, credentials.lmhash, credentials.nthash)
 81        if smbClient.isGuestSession() > 0:
 82            if debug:
 83                print("[>] GUEST Session Granted")
 84        else:
 85            if debug:
 86                print("[>] USER Session Granted")
 87    except Exception as e:
 88        if debug:
 89            print(e)
 90        return pipes
 91
 92    # Breadth-first search algorithm to recursively find .extension files
 93    searchdirs = [""]
 94    depth = 0
 95    while len(searchdirs) != 0 and ((depth <= maxdepth) or (maxdepth == -1)):
 96        depth += 1
 97        next_dirs = []
 98        for sdir in searchdirs:
 99            if debug:
100                print("[>] Searching in %s " % sdir)
101            try:
102                for sharedfile in smbClient.listPath(share, sdir + "*", password=None):
103                    if sharedfile.get_longname() not in [".", ".."]:
104                        if sharedfile.is_directory():
105                            if debug:
106                                print("[>] Found directory %s/" % sharedfile.get_longname())
107                            next_dirs.append(sdir + sharedfile.get_longname() + "/")
108                        else:
109                            if debug:
110                                print("[>] Found file %s" % sharedfile.get_longname())
111                            full_path = sdir + sharedfile.get_longname()
112                            pipes.append(full_path)
113            except SessionError as e:
114                if debug:
115                    print("[error] %s " % e)
116        searchdirs = next_dirs
117        if debug:
118            print("[>] Next iteration with %d folders." % len(next_dirs))
119    pipes = sorted(list(set(["\\PIPE\\" + f for f in pipes])), key=lambda x:x.lower())
120    return pipes
121
122
123
124def can_connect_to_pipe(target, pipe, credentials, targetIp=None, verbose=False):
125    """
126    Function can_connect_to_pipe(target, pipe, credentials, targetIp=None, verbose=False)
127    """
128    ncan_target = r'ncacn_np:%s[%s]' % (target, pipe)
129    __rpctransport = transport.DCERPCTransportFactory(ncan_target)
130
131    if hasattr(__rpctransport, 'set_credentials'):
132        __rpctransport.set_credentials(
133            username=credentials.username,
134            password=credentials.password,
135            domain=credentials.domain,
136            lmhash=credentials.lmhash,
137            nthash=credentials.nthash
138        )
139
140    if credentials.doKerberos:
141        __rpctransport.set_kerberos(credentials.doKerberos, kdcHost=credentials.kdcHost)
142    if targetIp is not None:
143        __rpctransport.setRemoteHost(targetIp)
144
145    dce = __rpctransport.get_dce_rpc()
146    # dce.set_auth_type(RPC_C_AUTHN_WINNT)
147    # dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
148
149    if verbose:
150        print("         [>] Connecting to %s ... " % ncan_target, end="")
151    sys.stdout.flush()
152    try:
153        dce.connect()
154    except Exception as e:
155        if verbose:
156            print("\x1b[1;91mfail\x1b[0m")
157            print("      [!] Something went wrong, check error status => %s" % str(e))
158        return None
159    else:
160        if verbose:
161            print("\x1b[1;92msuccess\x1b[0m")
162        return dce
163
164
165def can_bind_to_interface(target, pipe, credentials, uuid, version, targetIp=None, verbose=False):
166    """
167    Function can_bind_to_interface(target, pipe, credentials, uuid, version, targetIp=None, verbose=False)
168    """
169    ncan_target = r'ncacn_np:%s[%s]' % (target, pipe)
170    __rpctransport = transport.DCERPCTransportFactory(ncan_target)
171
172    if hasattr(__rpctransport, 'set_credentials'):
173        __rpctransport.set_credentials(
174            username=credentials.username,
175            password=credentials.password,
176            domain=credentials.domain,
177            lmhash=credentials.lmhash,
178            nthash=credentials.nthash
179        )
180
181    if credentials.doKerberos:
182        __rpctransport.set_kerberos(credentials.doKerberos, kdcHost=credentials.kdcHost)
183    if targetIp is not None:
184        __rpctransport.setRemoteHost(targetIp)
185
186    dce = __rpctransport.get_dce_rpc()
187    # dce.set_auth_type(RPC_C_AUTHN_WINNT)
188    # dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
189
190    if verbose:
191        print("         [>] Connecting to %s ... " % ncan_target, end="")
192    sys.stdout.flush()
193    try:
194        dce.connect()
195    except Exception as e:
196        if verbose:
197            print("\x1b[1;91mfail\x1b[0m")
198            print("      [!] Something went wrong, check error status => %s" % str(e))
199        return False
200
201    if verbose:
202        print("         [>] Binding to <uuid='%s', version='%s'> ... " % (uuid, version), end="")
203    sys.stdout.flush()
204    try:
205        dce.bind(uuidtup_to_bin((uuid, version)))
206    except Exception as e:
207        if verbose:
208            print("\x1b[1;91mfail\x1b[0m")
209            print("         [!] Something went wrong, check error status => %s" % str(e))
210        if "STATUS_PIPE_DISCONNECTED" in str(e):
211            # SMB SessionError: STATUS_PIPE_DISCONNECTED()
212            return False
213        elif "STATUS_OBJECT_NAME_NOT_FOUND" in str(e):
214            # SMB SessionError: STATUS_OBJECT_NAME_NOT_FOUND(The object name is not found.)
215            return False
216        elif "STATUS_ACCESS_DENIED" in str(e):
217            # SMB SessionError: STATUS_ACCESS_DENIED({Access Denied} A process has requested access to an object but has not been granted those access rights.)
218            return False
219        elif "abstract_syntax_not_supported" in str(e):
220            # Bind context 1 rejected: provider_rejection; abstract_syntax_not_supported (this usually means the interface isn't listening on the given endpoint)
221            return False
222        elif "Unknown DCE RPC packet type received" in str(e):
223            # Unknown DCE RPC packet type received: 11
224            return False
225        elif "Authentication type not recognized" in str(e):
226            # DCERPC Runtime Error: code: 0x8 - Authentication type not recognized
227            return False
228        else:
229            return True
230    else:
231        if verbose:
232            print("\x1b[1;92msuccess\x1b[0m")
233        return True
def init_smb_session( args, domain, username, password, address, lmhash, nthash, verbose=False):
15def init_smb_session(args, domain, username, password, address, lmhash, nthash, verbose=False):
16    smbClient = SMBConnection(address, args.target_ip, sess_port=int(args.port))
17    dialect = smbClient.getDialect()
18    if dialect == SMB_DIALECT:
19        if verbose:
20            print("[debug] SMBv1 dialect used")
21    elif dialect == SMB2_DIALECT_002:
22        if verbose:
23            print("[debug] SMBv2.0 dialect used")
24    elif dialect == SMB2_DIALECT_21:
25        if verbose:
26            print("[debug] SMBv2.1 dialect used")
27    else:
28        if verbose:
29            print("[debug] SMBv3.0 dialect used")
30    if args.k is True:
31        smbClient.kerberosLogin(username, password, domain, lmhash, nthash, args.aesKey, args.dc_ip)
32    else:
33        smbClient.login(username, password, domain, lmhash, nthash)
34    if smbClient.isGuestSession() > 0:
35        if verbose:
36            print("[debug] GUEST Session Granted")
37    else:
38        if verbose:
39            print("[debug] USER Session Granted")
40    return smbClient
def try_login(credentials, target, port=445, verbose=False):
43def try_login(credentials, target, port=445, verbose=False):
44    """Documentation for try_login"""
45    # Checking credentials if any
46    if not credentials.is_anonymous():
47        try:
48            smbClient = SMBConnection(
49                remoteName=target,
50                remoteHost=target,
51                sess_port=int(port)
52            )
53            smbClient.login(
54                user=credentials.username,
55                password=credentials.password,
56                domain=credentials.domain,
57                lmhash=credentials.lmhash,
58                nthash=credentials.nthash
59            )
60        except Exception as e:
61            print("[!] Could not login as '%s' with these credentials on '%s'." % (credentials.username, target))
62            print("  | Error: %s" % str(e))
63            return False
64        else:
65            return True
66    else:
67        return True

Documentation for try_login

def list_remote_pipes(target, credentials, share='IPC$', maxdepth=-1, debug=False):
 70def list_remote_pipes(target, credentials, share='IPC$', maxdepth=-1, debug=False):
 71    """
 72    Function list_remote_pipes(target, credentials, share='IPC$', maxdepth=-1, debug=False)
 73    """
 74    pipes = []
 75    try:
 76        smbClient = SMBConnection(target, target, sess_port=int(445))
 77        dialect = smbClient.getDialect()
 78        if credentials.doKerberos is True:
 79            smbClient.kerberosLogin(credentials.username, credentials.password, credentials.domain, credentials.lmhash, credentials.nthash, credentials.aesKey, credentials.dc_ip)
 80        else:
 81            smbClient.login(credentials.username, credentials.password, credentials.domain, credentials.lmhash, credentials.nthash)
 82        if smbClient.isGuestSession() > 0:
 83            if debug:
 84                print("[>] GUEST Session Granted")
 85        else:
 86            if debug:
 87                print("[>] USER Session Granted")
 88    except Exception as e:
 89        if debug:
 90            print(e)
 91        return pipes
 92
 93    # Breadth-first search algorithm to recursively find .extension files
 94    searchdirs = [""]
 95    depth = 0
 96    while len(searchdirs) != 0 and ((depth <= maxdepth) or (maxdepth == -1)):
 97        depth += 1
 98        next_dirs = []
 99        for sdir in searchdirs:
100            if debug:
101                print("[>] Searching in %s " % sdir)
102            try:
103                for sharedfile in smbClient.listPath(share, sdir + "*", password=None):
104                    if sharedfile.get_longname() not in [".", ".."]:
105                        if sharedfile.is_directory():
106                            if debug:
107                                print("[>] Found directory %s/" % sharedfile.get_longname())
108                            next_dirs.append(sdir + sharedfile.get_longname() + "/")
109                        else:
110                            if debug:
111                                print("[>] Found file %s" % sharedfile.get_longname())
112                            full_path = sdir + sharedfile.get_longname()
113                            pipes.append(full_path)
114            except SessionError as e:
115                if debug:
116                    print("[error] %s " % e)
117        searchdirs = next_dirs
118        if debug:
119            print("[>] Next iteration with %d folders." % len(next_dirs))
120    pipes = sorted(list(set(["\\PIPE\\" + f for f in pipes])), key=lambda x:x.lower())
121    return pipes

Function list_remote_pipes(target, credentials, share='IPC$', maxdepth=-1, debug=False)

def can_connect_to_pipe(target, pipe, credentials, targetIp=None, verbose=False):
125def can_connect_to_pipe(target, pipe, credentials, targetIp=None, verbose=False):
126    """
127    Function can_connect_to_pipe(target, pipe, credentials, targetIp=None, verbose=False)
128    """
129    ncan_target = r'ncacn_np:%s[%s]' % (target, pipe)
130    __rpctransport = transport.DCERPCTransportFactory(ncan_target)
131
132    if hasattr(__rpctransport, 'set_credentials'):
133        __rpctransport.set_credentials(
134            username=credentials.username,
135            password=credentials.password,
136            domain=credentials.domain,
137            lmhash=credentials.lmhash,
138            nthash=credentials.nthash
139        )
140
141    if credentials.doKerberos:
142        __rpctransport.set_kerberos(credentials.doKerberos, kdcHost=credentials.kdcHost)
143    if targetIp is not None:
144        __rpctransport.setRemoteHost(targetIp)
145
146    dce = __rpctransport.get_dce_rpc()
147    # dce.set_auth_type(RPC_C_AUTHN_WINNT)
148    # dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
149
150    if verbose:
151        print("         [>] Connecting to %s ... " % ncan_target, end="")
152    sys.stdout.flush()
153    try:
154        dce.connect()
155    except Exception as e:
156        if verbose:
157            print("\x1b[1;91mfail\x1b[0m")
158            print("      [!] Something went wrong, check error status => %s" % str(e))
159        return None
160    else:
161        if verbose:
162            print("\x1b[1;92msuccess\x1b[0m")
163        return dce

Function can_connect_to_pipe(target, pipe, credentials, targetIp=None, verbose=False)

def can_bind_to_interface( target, pipe, credentials, uuid, version, targetIp=None, verbose=False):
166def can_bind_to_interface(target, pipe, credentials, uuid, version, targetIp=None, verbose=False):
167    """
168    Function can_bind_to_interface(target, pipe, credentials, uuid, version, targetIp=None, verbose=False)
169    """
170    ncan_target = r'ncacn_np:%s[%s]' % (target, pipe)
171    __rpctransport = transport.DCERPCTransportFactory(ncan_target)
172
173    if hasattr(__rpctransport, 'set_credentials'):
174        __rpctransport.set_credentials(
175            username=credentials.username,
176            password=credentials.password,
177            domain=credentials.domain,
178            lmhash=credentials.lmhash,
179            nthash=credentials.nthash
180        )
181
182    if credentials.doKerberos:
183        __rpctransport.set_kerberos(credentials.doKerberos, kdcHost=credentials.kdcHost)
184    if targetIp is not None:
185        __rpctransport.setRemoteHost(targetIp)
186
187    dce = __rpctransport.get_dce_rpc()
188    # dce.set_auth_type(RPC_C_AUTHN_WINNT)
189    # dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
190
191    if verbose:
192        print("         [>] Connecting to %s ... " % ncan_target, end="")
193    sys.stdout.flush()
194    try:
195        dce.connect()
196    except Exception as e:
197        if verbose:
198            print("\x1b[1;91mfail\x1b[0m")
199            print("      [!] Something went wrong, check error status => %s" % str(e))
200        return False
201
202    if verbose:
203        print("         [>] Binding to <uuid='%s', version='%s'> ... " % (uuid, version), end="")
204    sys.stdout.flush()
205    try:
206        dce.bind(uuidtup_to_bin((uuid, version)))
207    except Exception as e:
208        if verbose:
209            print("\x1b[1;91mfail\x1b[0m")
210            print("         [!] Something went wrong, check error status => %s" % str(e))
211        if "STATUS_PIPE_DISCONNECTED" in str(e):
212            # SMB SessionError: STATUS_PIPE_DISCONNECTED()
213            return False
214        elif "STATUS_OBJECT_NAME_NOT_FOUND" in str(e):
215            # SMB SessionError: STATUS_OBJECT_NAME_NOT_FOUND(The object name is not found.)
216            return False
217        elif "STATUS_ACCESS_DENIED" in str(e):
218            # SMB SessionError: STATUS_ACCESS_DENIED({Access Denied} A process has requested access to an object but has not been granted those access rights.)
219            return False
220        elif "abstract_syntax_not_supported" in str(e):
221            # Bind context 1 rejected: provider_rejection; abstract_syntax_not_supported (this usually means the interface isn't listening on the given endpoint)
222            return False
223        elif "Unknown DCE RPC packet type received" in str(e):
224            # Unknown DCE RPC packet type received: 11
225            return False
226        elif "Authentication type not recognized" in str(e):
227            # DCERPC Runtime Error: code: 0x8 - Authentication type not recognized
228            return False
229        else:
230            return True
231    else:
232        if verbose:
233            print("\x1b[1;92msuccess\x1b[0m")
234        return True

Function can_bind_to_interface(target, pipe, credentials, uuid, version, targetIp=None, verbose=False)