github.com/n00py/Slackor@v0.0.0-20200610224921-d007fcea1740/impacket/examples/mimikatz.py (about) 1 #!/usr/bin/env python 2 # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 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: Mini shell to control a remote mimikatz RPC server developed by @gentilkiwi 9 # 10 # Author: 11 # Alberto Solino (@agsolino) 12 # 13 # Reference for: 14 # SMB DCE/RPC 15 # 16 from __future__ import division 17 from __future__ import print_function 18 import argparse 19 import cmd 20 import logging 21 import os 22 import sys 23 24 from impacket import version 25 from impacket.dcerpc.v5 import epm, mimilib 26 from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_GSS_NEGOTIATE 27 from impacket.dcerpc.v5.transport import DCERPCTransportFactory 28 from impacket.examples import logger 29 30 try: 31 from Cryptodome.Cipher import ARC4 32 except Exception: 33 logging.critical("Warning: You don't have any crypto installed. You need pycryptodomex") 34 logging.critical("See https://pypi.org/project/pycryptodomex/") 35 36 # If you wanna have readline like functionality in Windows, install pyreadline 37 try: 38 import pyreadline as readline 39 except ImportError: 40 import readline 41 42 class MimikatzShell(cmd.Cmd): 43 def __init__(self, dce): 44 cmd.Cmd.__init__(self) 45 self.shell = None 46 47 self.prompt = 'mimikatz # ' 48 self.tid = None 49 self.intro = '' \ 50 ' .#####. mimikatz RPC interface\n'\ 51 ' .## ^ ##. "A La Vie, A L\' Amour "\n'\ 52 ' ## / \ ## /* * *\n'\ 53 ' ## \ / ## Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )\n'\ 54 ' \'## v ##\' http://blog.gentilkiwi.com/mimikatz (oe.eo)\n'\ 55 ' \'#####\' Impacket client by Alberto Solino (@agsolino) * * */\n\n'\ 56 'Type help for list of commands' 57 self.pwd = '' 58 self.share = None 59 self.loggedIn = True 60 self.last_output = None 61 62 self.dce = dce 63 64 dh = mimilib.MimiDiffeH() 65 blob = mimilib.PUBLICKEYBLOB() 66 blob['y'] = dh.genPublicKey()[::-1] 67 publicKey = mimilib.MIMI_PUBLICKEY() 68 publicKey['sessionType'] = mimilib.CALG_RC4 69 publicKey['cbPublicKey'] = 144 70 publicKey['pbPublicKey'] = blob.getData() 71 resp = mimilib.hMimiBind(self.dce, publicKey) 72 blob = mimilib.PUBLICKEYBLOB(b''.join(resp['serverPublicKey']['pbPublicKey'])) 73 74 self.key = dh.getSharedSecret(blob['y'][::-1])[-16:][::-1] 75 self.pHandle = resp['phMimi'] 76 77 def emptyline(self): 78 pass 79 80 def precmd(self,line): 81 # switch to unicode 82 #return line.encode('utf-8') 83 return line 84 85 def default(self, line): 86 if line.startswith('*'): 87 line = line[1:] 88 command = (line.strip('\n')+'\x00').encode('utf-16le') 89 command = ARC4.new(self.key).encrypt(command) 90 resp = mimilib.hMimiCommand(self.dce, self.pHandle, command) 91 cipherText = b''.join(resp['encResult']) 92 cipher = ARC4.new(self.key) 93 print(cipher.decrypt(cipherText).decode('utf-16le')) 94 95 def onecmd(self,s): 96 retVal = False 97 try: 98 retVal = cmd.Cmd.onecmd(self,s) 99 except Exception as e: 100 logging.debug("Exception:", exc_info=True) 101 logging.error(e) 102 103 return retVal 104 105 def do_exit(self,line): 106 if self.shell is not None: 107 self.shell.close() 108 return True 109 110 def do_shell(self, line): 111 output = os.popen(line).read() 112 print(output) 113 self.last_output = output 114 115 def do_help(self,line): 116 self.default('::') 117 118 def main(): 119 # Init the example's logger theme 120 logger.init() 121 print(version.BANNER) 122 parser = argparse.ArgumentParser(add_help = True, description = "SMB client implementation.") 123 124 parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>') 125 parser.add_argument('-file', type=argparse.FileType('r'), help='input file with commands to execute in the mini shell') 126 parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') 127 128 group = parser.add_argument_group('authentication') 129 130 group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') 131 group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') 132 group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' 133 '(KRB5CCNAME) based on target parameters. If valid credentials ' 134 'cannot be found, it will use the ones specified in the command ' 135 'line') 136 group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication ' 137 '(128 or 256 bits)') 138 139 group = parser.add_argument_group('connection') 140 141 group.add_argument('-dc-ip', action='store', metavar="ip address", 142 help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in ' 143 'the target parameter') 144 group.add_argument('-target-ip', action='store', metavar="ip address", 145 help='IP Address of the target machine. If omitted it will use whatever was specified as target. ' 146 'This is useful when target is the NetBIOS name and you cannot resolve it') 147 148 if len(sys.argv)==1: 149 parser.print_help() 150 sys.exit(1) 151 152 options = parser.parse_args() 153 154 if options.debug is True: 155 logging.getLogger().setLevel(logging.DEBUG) 156 else: 157 logging.getLogger().setLevel(logging.INFO) 158 159 import re 160 domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match( 161 options.target).groups('') 162 163 #In case the password contains '@' 164 if '@' in address: 165 password = password + '@' + address.rpartition('@')[0] 166 address = address.rpartition('@')[2] 167 168 if options.target_ip is None: 169 options.target_ip = address 170 171 if domain is None: 172 domain = '' 173 174 if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: 175 from getpass import getpass 176 password = getpass("Password:") 177 178 if options.aesKey is not None: 179 options.k = True 180 181 if options.hashes is not None: 182 lmhash, nthash = options.hashes.split(':') 183 else: 184 lmhash = '' 185 nthash = '' 186 187 bound = False 188 189 try: 190 if username != '': 191 try: 192 # Let's try to do everything through SMB. If we'e lucky it might get everything encrypted 193 rpctransport = DCERPCTransportFactory(r'ncacn_np:%s[\pipe\epmapper]'%address) 194 rpctransport.set_credentials(username, password, domain, lmhash, nthash, options.aesKey) 195 dce = rpctransport.get_dce_rpc() 196 if options.k: 197 rpctransport.set_kerberos(True, options.dc_ip) 198 dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) 199 dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 200 dce.connect() 201 # Give me the endpoint please! 202 stringBinding = epm.hept_map(address, mimilib.MSRPC_UUID_MIMIKATZ, protocol = 'ncacn_np', dce=dce) 203 204 # Thanks, let's now use the same SMB Connection to bind to mimi 205 rpctransport2 = DCERPCTransportFactory(stringBinding) 206 rpctransport2.set_smb_connection(rpctransport.get_smb_connection()) 207 dce = rpctransport2.get_dce_rpc() 208 if options.k: 209 dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) 210 dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 211 dce.connect() 212 dce.bind(mimilib.MSRPC_UUID_MIMIKATZ) 213 bound = True 214 except Exception as e: 215 if str(e).find('ept_s_not_registered') >=0: 216 # Let's try ncacn_ip_tcp 217 stringBinding = epm.hept_map(address, mimilib.MSRPC_UUID_MIMIKATZ, protocol = 'ncacn_ip_tcp') 218 else: 219 raise 220 221 else: 222 stringBinding = epm.hept_map(address, mimilib.MSRPC_UUID_MIMIKATZ, protocol = 'ncacn_ip_tcp') 223 224 if bound is False: 225 rpctransport = DCERPCTransportFactory(stringBinding) 226 rpctransport.set_credentials(username, password, domain, lmhash, nthash, options.aesKey) 227 dce = rpctransport.get_dce_rpc() 228 if options.k is True: 229 rpctransport.set_kerberos(True, options.dc_ip) 230 dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) 231 rpctransport.set_credentials(username, password, domain, lmhash, nthash) 232 dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 233 dce.connect() 234 dce.bind(mimilib.MSRPC_UUID_MIMIKATZ) 235 236 shell = MimikatzShell(dce) 237 238 if options.file is not None: 239 logging.info("Executing commands from %s" % options.file.name) 240 for line in options.file.readlines(): 241 if line[0] != '#': 242 print("# %s" % line, end=' ') 243 shell.onecmd(line) 244 else: 245 print(line, end=' ') 246 else: 247 shell.cmdloop() 248 except Exception as e: 249 logging.debug("Exception:", exc_info=True) 250 logging.error(str(e)) 251 252 if __name__ == "__main__": 253 main()