from impacket.dcerpc import transport from impacket import uuid, smb import random class DCERPCExploit: params = { # general options 'host': '192.168.1.1', 'pipe': 'browser', 'port': 139, 'proto': 1, # 0 UDP, 1 SMB # SMB options 'tree_connect': 0, # 0 = tree_connect, 1 = tree_connect_andx 'open': 0, # 0 = open, 1 = open_andx, 2 = nt_create_andx 'read': 0, # 0 = read, 1 = read_andx, 2 = read_raw, 3 = read_cycling 'write': 0, # 0 = write, 1 = write_andx, 2 = write_raw, 3 = write_cycling 'transport_frag': -1, # -1 = don't fragment, use TransactNamedPipe. 'random_offsets': 0, # randomize offset in write and read requests (when cycling) 'smb_user': '', 'smb_passwd': '', 'smb_lmhash': '', # lm_hash, first part of pwdump3 output, On of the hashes is enough 'smb_nthash': '', # nt_hash, second part of pwdump3 output # DCERPC options 'idempotent': 0, # 'dcerpc_frag': -1, # -1 - don't fragment 'alter_ctx': 0, # use alter_ctx instead of bind(). Will issue a bogus bind first 'bogus_binds': 0, # number of bogus UUIDs in bind() request 'bogus_alter': 0, # number of bogus UUIDs in alter_ctx(), implies alter_ctx 'endianness': '<', # < for little endian, > for big endian # When switching to big endian you also need to change the # endianness of the parameters to the function (in dce.call()) # Structure does not currently have decent support for this, # specially for the 'w' fields. } UUID = ('01010101-2323-4545-6767-898989898989','1.0') BOGUS_UUID = ('12341234-5678-5678-5678-1234567890ab','1.0') def __init__(self, argv): for arg in argv: args = arg.split('=',2) if len(args) != 2: self.usage() raise Exception, "Error parsing argument %r" % arg if len(args) == 1: continue self.params[args[0]] = args[1] self.WRITE_TYPE = 0 self.READ_TYPE = 0 protocols = ( 'ncadg_ip_udp:%(host)s[%(port)d]', 'ncacn_np:%(host)s[\\pipe\\%(pipe)s]', ) def run(self): self.setupConnection() self.attackRun() def open(self, *args): args = list(args) args[1] = r'\\pipe%s' % args[1] args.append(smb.SMB_O_CREAT) args.append(smb.SMB_ACCESS_WRITE | smb.SMB_ACCESS_READ) return self.smb.open(*args)[0] def open_andx(self, *args): args = list(args) args[1] = r'\\pipe%s' % args[1] args.append(smb.SMB_O_CREAT) args.append(smb.SMB_ACCESS_WRITE | smb.SMB_ACCESS_READ) return self.smb.open_andx(*args)[0] def write_cycling(self, *args, **kargs): w = (self.smb.write, self.smb.original_write_andx, self.smb.write_raw)[self.WRITE_TYPE] self.WRITE_TYPE += 1 self.WRITE_TYPE %= 3 if int(self.params['random_offsets']): kargs['offset'] = random.randint(0,65535) return w(*args, **kargs) def read_cycling(self, *args, **kargs): w = (self.smb.read, self.smb.original_read_andx, self.smb.read_raw)[self.READ_TYPE] self.READ_TYPE += 1 self.READ_TYPE %= 3 if int(self.params['random_offsets']): kargs['offset'] = random.randint(0,65535) return w(*args, **kargs) def setupConnection(self): proto = int(self.params['proto']) self.params['port'] = int(self.params['port']) stringbinding = self.protocols[proto] stringbinding %= self.params print "Using stringbinding: %r" % stringbinding self.trans = transport.DCERPCTransportFactory(stringbinding) self.trans.set_max_fragment_size(int(self.params['transport_frag'])) self.trans.set_dport(int(self.params['port'])) try: # SMB parameters handling self.trans.setup_smb_server() # force building the SMB object so we can change its methods self.smb = self.trans.get_smb_server() # select the right tree_connect arg = int(self.params['tree_connect']) if arg == 0: self.smb.tree_connect_andx = self.smb.tree_connect if arg == 1: self.smb.tree_connect_andx = self.smb.tree_connect_andx # open selection arg = int(self.params['open']) if arg == 0: self.smb.nt_create_andx = self.open elif arg == 1: self.smb.nt_create_andx = self.open_andx # read selection arg = int(self.params['read']) if arg == 0: self.smb.read_andx = self.smb.read elif arg == 1: self.smb.read_andx = self.smb.read_andx elif arg == 2: self.smb.read_andx = self.smb.read_raw elif arg == 3: self.smb.original_read_andx = self.smb.read_andx self.smb.read_andx = self.read_cycling # write selection arg = int(self.params['write']) if arg == 0: self.smb.write_andx = self.smb.write elif arg == 1: self.smb.write_andx = self.smb.write_andx elif arg == 2: self.smb.write_andx = self.smb.write_raw elif arg == 3: self.smb.original_write_andx = self.smb.write_andx self.smb.write_andx = self.write_cycling # smb credentials self.trans.set_credentials( self.params['smb_user'], self.params['smb_passwd'], lm_hash = self.params['smb_lmhash'], nt_hash = self.params['smb_nthash']) except Exception, e: pass self.trans.connect() self.dce = self.trans.DCERPC_class(self.trans) self.dce.endianness = self.params['endianness'] # DCERPC parameters handling self.dce.set_max_fragment_size(int(self.params['dcerpc_frag'])) self.dce.set_idempotent(int(self.params['idempotent'])) # alter_ctx alter = int(self.params['alter_ctx']) or int(self.params['bogus_alter']) if alter: _uuid = self.BOGUS_UUID else: _uuid = self.UUID # bogus_binds self.dce.bind(uuid.uuidtup_to_bin(_uuid), bogus_binds = int(self.params['bogus_binds'])) if proto and alter: self.dce = self.dce.alter_ctx(uuid.uuidtup_to_bin(self.UUID), bogus_binds = int(self.params['bogus_alter'])) def usage(self): print "Use: python example.py param1=value param2=value2 ..." print "see exploit.py to see al available parameters" print "for example:\n" print "$ python example.py host=192.168.1.1 transport_frag=10" def attackRun(self): pass