coercer.utils.smb

  1#!/usr/bin/env python3
  2# -*- coding: utf-8 -*-
  3# File name          : smbutils.py
  4# Author             : Podalirius (@podalirius_)
  5# Date created       : 6 Jul 2022
  6
  7
  8import sys
  9from impacket.dcerpc.v5 import transport
 10from impacket.uuid import uuidtup_to_bin
 11
 12
 13def connect_to_pipe(pipe, username, password, domain, lmhash, nthash, target, dcHost, doKerberos=False, targetIp=None, verbose=False):
 14    ncan_target = r'ncacn_np:%s[%s]' % (target, pipe)
 15    __rpctransport = transport.DCERPCTransportFactory(ncan_target)
 16
 17    if hasattr(__rpctransport, 'set_credentials'):
 18        __rpctransport.set_credentials(
 19            username=username,
 20            password=password,
 21            domain=domain,
 22            lmhash=lmhash,
 23            nthash=nthash
 24        )
 25
 26    if doKerberos:
 27        __rpctransport.set_kerberos(doKerberos, kdcHost=dcHost)
 28    if targetIp is not None:
 29        __rpctransport.setRemoteHost(targetIp)
 30
 31    dce = __rpctransport.get_dce_rpc()
 32    # dce.set_auth_type(RPC_C_AUTHN_WINNT)
 33    # dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
 34
 35    if verbose:
 36        print("         [>] Connecting to %s ... " % ncan_target, end="")
 37    sys.stdout.flush()
 38    try:
 39        dce.connect()
 40    except Exception as e:
 41        if verbose:
 42            print("\x1b[1;91mfail\x1b[0m")
 43            print("      [!] Something went wrong, check error status => %s" % str(e))
 44        return None
 45    else:
 46        if verbose:
 47            print("\x1b[1;92msuccess\x1b[0m")
 48        return dce
 49
 50
 51def can_bind_to_protocol(dce, uuid, version, verbose=False):
 52    if verbose:
 53        print("         [>] Binding to <uuid='%s', version='%s'> ... " % (uuid, version), end="")
 54    sys.stdout.flush()
 55    try:
 56        dce.bind(uuidtup_to_bin((uuid, version)))
 57    except Exception as e:
 58        if verbose:
 59            print("\x1b[1;91mfail\x1b[0m")
 60            print("         [!] Something went wrong, check error status => %s" % str(e))
 61        if "STATUS_PIPE_DISCONNECTED" in str(e):
 62            # SMB SessionError: STATUS_PIPE_DISCONNECTED()
 63            return False
 64        elif "STATUS_OBJECT_NAME_NOT_FOUND" in str(e):
 65            # SMB SessionError: STATUS_OBJECT_NAME_NOT_FOUND(The object name is not found.)
 66            return False
 67        elif "STATUS_ACCESS_DENIED" in str(e):
 68            # SMB SessionError: STATUS_ACCESS_DENIED({Access Denied} A process has requested access to an object but has not been granted those access rights.)
 69            return False
 70        elif "abstract_syntax_not_supported" in str(e):
 71            # Bind context 1 rejected: provider_rejection; abstract_syntax_not_supported (this usually means the interface isn't listening on the given endpoint)
 72            return False
 73        elif "Unknown DCE RPC packet type received" in str(e):
 74            # Unknown DCE RPC packet type received: 11
 75            return False
 76        elif "Authentication type not recognized" in str(e):
 77            # DCERPC Runtime Error: code: 0x8 - Authentication type not recognized
 78            return False
 79        else:
 80            return True
 81    else:
 82        if verbose:
 83            print("\x1b[1;92msuccess\x1b[0m")
 84        return True
 85
 86
 87def get_available_pipes_and_protocols(options, target, lmhash, nthash, all_pipes, available_protocols):
 88    for pipe in all_pipes:
 89        dce = connect_to_pipe(pipe=pipe, username=options.username, password=options.password, domain=options.domain, lmhash=lmhash, nthash=nthash, target=target, doKerberos=options.kerberos, dcHost=options.dc_ip, verbose=options.verbose)
 90        if dce is not None:
 91            print("   [>] Pipe '%s' is \x1b[1;92maccessible\x1b[0m!" % pipe)
 92            for protocol in available_protocols:
 93                if pipe in protocol.available_pipes:
 94                    dce = connect_to_pipe(pipe=pipe, username=options.username, password=options.password, domain=options.domain, lmhash=lmhash, nthash=nthash, target=options.target, doKerberos=options.kerberos, dcHost=options.dc_ip, targetIp=options.target_ip, verbose=options.verbose)
 95                    if dce is not None:
 96                        if can_bind_to_protocol(dce, protocol.uuid, protocol.version, verbose=options.verbose):
 97                            for method, opnum, comment in protocol.list_coerce_methods():
 98                                if comment is not None:
 99                                    print("      [>] %s (uuid=%s, version=%s) %s (opnum %d) | %s" % (protocol.shortname, protocol.uuid, protocol.version, method, opnum, comment))
100                                else:
101                                    print("      [>] %s (uuid=%s, version=%s) %s (opnum %d) " % (protocol.shortname, protocol.uuid, protocol.version, method, opnum))
102        else:
103            if options.verbose or options.analyze:
104                print("   [>] Pipe '%s' is \x1b[1;91mnot accessible\x1b[0m!" % pipe)
def connect_to_pipe( pipe, username, password, domain, lmhash, nthash, target, dcHost, doKerberos=False, targetIp=None, verbose=False):
14def connect_to_pipe(pipe, username, password, domain, lmhash, nthash, target, dcHost, doKerberos=False, targetIp=None, verbose=False):
15    ncan_target = r'ncacn_np:%s[%s]' % (target, pipe)
16    __rpctransport = transport.DCERPCTransportFactory(ncan_target)
17
18    if hasattr(__rpctransport, 'set_credentials'):
19        __rpctransport.set_credentials(
20            username=username,
21            password=password,
22            domain=domain,
23            lmhash=lmhash,
24            nthash=nthash
25        )
26
27    if doKerberos:
28        __rpctransport.set_kerberos(doKerberos, kdcHost=dcHost)
29    if targetIp is not None:
30        __rpctransport.setRemoteHost(targetIp)
31
32    dce = __rpctransport.get_dce_rpc()
33    # dce.set_auth_type(RPC_C_AUTHN_WINNT)
34    # dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
35
36    if verbose:
37        print("         [>] Connecting to %s ... " % ncan_target, end="")
38    sys.stdout.flush()
39    try:
40        dce.connect()
41    except Exception as e:
42        if verbose:
43            print("\x1b[1;91mfail\x1b[0m")
44            print("      [!] Something went wrong, check error status => %s" % str(e))
45        return None
46    else:
47        if verbose:
48            print("\x1b[1;92msuccess\x1b[0m")
49        return dce
def can_bind_to_protocol(dce, uuid, version, verbose=False):
52def can_bind_to_protocol(dce, uuid, version, verbose=False):
53    if verbose:
54        print("         [>] Binding to <uuid='%s', version='%s'> ... " % (uuid, version), end="")
55    sys.stdout.flush()
56    try:
57        dce.bind(uuidtup_to_bin((uuid, version)))
58    except Exception as e:
59        if verbose:
60            print("\x1b[1;91mfail\x1b[0m")
61            print("         [!] Something went wrong, check error status => %s" % str(e))
62        if "STATUS_PIPE_DISCONNECTED" in str(e):
63            # SMB SessionError: STATUS_PIPE_DISCONNECTED()
64            return False
65        elif "STATUS_OBJECT_NAME_NOT_FOUND" in str(e):
66            # SMB SessionError: STATUS_OBJECT_NAME_NOT_FOUND(The object name is not found.)
67            return False
68        elif "STATUS_ACCESS_DENIED" in str(e):
69            # SMB SessionError: STATUS_ACCESS_DENIED({Access Denied} A process has requested access to an object but has not been granted those access rights.)
70            return False
71        elif "abstract_syntax_not_supported" in str(e):
72            # Bind context 1 rejected: provider_rejection; abstract_syntax_not_supported (this usually means the interface isn't listening on the given endpoint)
73            return False
74        elif "Unknown DCE RPC packet type received" in str(e):
75            # Unknown DCE RPC packet type received: 11
76            return False
77        elif "Authentication type not recognized" in str(e):
78            # DCERPC Runtime Error: code: 0x8 - Authentication type not recognized
79            return False
80        else:
81            return True
82    else:
83        if verbose:
84            print("\x1b[1;92msuccess\x1b[0m")
85        return True
def get_available_pipes_and_protocols(options, target, lmhash, nthash, all_pipes, available_protocols):
 88def get_available_pipes_and_protocols(options, target, lmhash, nthash, all_pipes, available_protocols):
 89    for pipe in all_pipes:
 90        dce = connect_to_pipe(pipe=pipe, username=options.username, password=options.password, domain=options.domain, lmhash=lmhash, nthash=nthash, target=target, doKerberos=options.kerberos, dcHost=options.dc_ip, verbose=options.verbose)
 91        if dce is not None:
 92            print("   [>] Pipe '%s' is \x1b[1;92maccessible\x1b[0m!" % pipe)
 93            for protocol in available_protocols:
 94                if pipe in protocol.available_pipes:
 95                    dce = connect_to_pipe(pipe=pipe, username=options.username, password=options.password, domain=options.domain, lmhash=lmhash, nthash=nthash, target=options.target, doKerberos=options.kerberos, dcHost=options.dc_ip, targetIp=options.target_ip, verbose=options.verbose)
 96                    if dce is not None:
 97                        if can_bind_to_protocol(dce, protocol.uuid, protocol.version, verbose=options.verbose):
 98                            for method, opnum, comment in protocol.list_coerce_methods():
 99                                if comment is not None:
100                                    print("      [>] %s (uuid=%s, version=%s) %s (opnum %d) | %s" % (protocol.shortname, protocol.uuid, protocol.version, method, opnum, comment))
101                                else:
102                                    print("      [>] %s (uuid=%s, version=%s) %s (opnum %d) " % (protocol.shortname, protocol.uuid, protocol.version, method, opnum))
103        else:
104            if options.verbose or options.analyze:
105                print("   [>] Pipe '%s' is \x1b[1;91mnot accessible\x1b[0m!" % pipe)