mirror of
https://github.com/XiaoliChan/wmiexec-Pro.git
synced 2026-10-21 00:37:59 +08:00
d2cf35384f
Signed-off-by: XiaoliChan <2209553467@qq.com>
221 lines
11 KiB
Python
221 lines
11 KiB
Python
import uuid
|
|
import time
|
|
import base64
|
|
import os
|
|
import sys
|
|
import time
|
|
import datetime
|
|
import cmd
|
|
import re
|
|
|
|
from lib.methods.classMethodEx import class_MethodEx
|
|
from lib.methods.executeVBS import executeVBS_Toolkit
|
|
from impacket.dcerpc.v5.dtypes import NULL
|
|
|
|
|
|
class EXEC_COMMAND():
|
|
def __init__(self, iWbemLevel1Login, codec):
|
|
self.iWbemLevel1Login = iWbemLevel1Login
|
|
self.codec = codec
|
|
|
|
def save_ToFile(self, hostname, content):
|
|
path = 'save/'+hostname
|
|
save_FileName = str(int(time.time())) + ".txt"
|
|
if os.path.exists(path) == False:
|
|
os.makedirs(path, exist_ok=True)
|
|
|
|
with open("{}/{}".format(path, save_FileName), 'w') as f: f.write(content)
|
|
print("[+] Save command result to: {}/{}".format(path, save_FileName))
|
|
|
|
# For system under NT6, like windows server 2003
|
|
# Timer for countdown Win32_ScheduledJob, scheduled task in "Win32_ScheduledJob" only will be trigger every per minute.
|
|
def timer_For_UnderNT6(self, iWbemServices=None, return_iWbemServices=False):
|
|
if iWbemServices is None:
|
|
iWbemServices = self.iWbemLevel1Login.NTLMLogin('//./root/Cimv2', NULL, NULL)
|
|
self.iWbemLevel1Login.RemRelease()
|
|
|
|
iEnumWbemClassObject = iWbemServices.ExecQuery("SELECT * FROM Win32_LocalTime")
|
|
LocalTime = iEnumWbemClassObject.Next(0xffffffff,1)[0]
|
|
LocalTime = dict(LocalTime.getProperties())
|
|
|
|
# Get remaining seconds until the next minute.
|
|
for i in range((65-int(LocalTime['Second']['value'])),0,-1):
|
|
print(f"[+] Waiting {i}s for command execution.", end="\r", flush=True)
|
|
time.sleep(1)
|
|
|
|
print("\r\n[+] Command executed!")
|
|
|
|
# Return cimv2
|
|
if return_iWbemServices is True:
|
|
return iWbemServices
|
|
else:
|
|
iWbemServices.RemRelease()
|
|
|
|
# For system under NT6, like windows server 2003
|
|
def exec_command_silent_For_UnderNT6(self, command=None):
|
|
iWbemServices = self.iWbemLevel1Login.NTLMLogin('//./root/Cimv2', NULL, NULL)
|
|
self.iWbemLevel1Login.RemRelease()
|
|
|
|
sql1 = "SELECT * FROM Win32_LocalTime"
|
|
sql2 = "SELECT * FROM Win32_TimeZone"
|
|
|
|
iEnumWbemClassObject = iWbemServices.ExecQuery(sql1)
|
|
Win32_LocalTime = iEnumWbemClassObject.Next(0xffffffff, 1)[0]
|
|
|
|
Machine_Date = datetime.datetime(100, 1, 1, int(Win32_LocalTime.Hour), int(Win32_LocalTime.Minute), 00)
|
|
execute_time = Machine_Date + datetime.timedelta(0, 60) # Delay one miniute for command execution
|
|
execute_time=execute_time.time()
|
|
|
|
iEnumWbemClassObject = iWbemServices.ExecQuery(sql2)
|
|
Win32_TimeZone = iEnumWbemClassObject.Next(0xffffffff, 1)[0]
|
|
|
|
executeTime = "********" + str(execute_time).replace(":", '') + ".000000+" + str(Win32_TimeZone.Bias)
|
|
command=r'C:\Windows\System32\cmd.exe /c %s'%command
|
|
Win32_ScheduledJob,resp=iWbemServices.GetObject("Win32_ScheduledJob")
|
|
result = Win32_ScheduledJob.Create(command, executeTime, 0, 0, 0, 1)
|
|
if int(result.ReturnValue) == 0:
|
|
print("[+] Create schedule job for command execution successfully.")
|
|
else:
|
|
print("[-] Create schedule job for command execution error, code: %s" %str(result.ReturnValue))
|
|
|
|
self.timer_For_UnderNT6(iWbemServices)
|
|
|
|
iWbemServices.RemRelease()
|
|
|
|
def exec_command_silent(self, command, old=False):
|
|
if "'" in command: command = command.replace("'",r'"')
|
|
if old == False:
|
|
executer = executeVBS_Toolkit(self.iWbemLevel1Login)
|
|
|
|
random_TaskName = str(uuid.uuid4())
|
|
|
|
print("[+] Executing command...(Sometime it will take a long time, please wait)")
|
|
|
|
with open('./lib/vbscripts/Exec-Command-Silent.vbs') as f: vbs = f.read()
|
|
vbs = vbs.replace('REPLACE_WITH_COMMAND', base64.b64encode(command.encode('utf-8')).decode('utf-8')).replace('REPLACE_WITH_TASK',random_TaskName)
|
|
|
|
# Experimental: use timer instead of filter query
|
|
tag = executer.ExecuteVBS(vbs_content=vbs, returnTag=True)
|
|
#filer_Query = r"SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
|
|
#tag = executer.ExecuteVBS(vbs_content=vbs, filer_Query=filer_Query, returnTag=True)
|
|
|
|
# Wait 5 seconds for next step.
|
|
for i in range(5,0,-1):
|
|
print(f"[+] Waiting {i}s for next step.", end="\r", flush=True)
|
|
time.sleep(1)
|
|
|
|
executer.remove_Event(tag)
|
|
else:
|
|
# Windows will auto remove job after schedule job executed.
|
|
self.exec_command_silent_For_UnderNT6(command)
|
|
|
|
def exec_command_WithOutput(self, command, ClassName_StoreOutput=None, save_Result=False, hostname=None, old=False):
|
|
executer = executeVBS_Toolkit(self.iWbemLevel1Login)
|
|
if ClassName_StoreOutput == None: ClassName_StoreOutput = "Win32_OSRecoveryConfigurationDataBackup"
|
|
|
|
FileName = str(uuid.uuid4()) + ".log"
|
|
CMD_instanceID = str(uuid.uuid4())
|
|
random_TaskName = str(uuid.uuid4())
|
|
|
|
if "'" in command: command = command.replace("'",r'"')
|
|
|
|
# Reuse cimv2 namespace to avoid dcom limition
|
|
class_Method = class_MethodEx(self.iWbemLevel1Login)
|
|
iWbemServices_Reuse_cimv2 = class_Method.check_ClassStatus(ClassName=ClassName_StoreOutput, return_iWbemServices=True)
|
|
|
|
print("[+] Executing command...(Sometime it will take a long time, please wait)")
|
|
if old == False:
|
|
# Experimental: use timer instead of filter query
|
|
with open('./lib/vbscripts/Exec-Command-WithOutput.vbs') as f: vbs = f.read()
|
|
vbs = vbs.replace('REPLACE_WITH_COMMAND', base64.b64encode(command.encode('utf-8')).decode('utf-8')).replace('REPLACE_WITH_FILENAME', FileName).replace('REPLACE_WITH_CLASSNAME',ClassName_StoreOutput).replace('RELEACE_WITH_UUID',CMD_instanceID).replace('REPLACE_WITH_TASK',random_TaskName)
|
|
tag = executer.ExecuteVBS(vbs_content=vbs, returnTag=True)
|
|
#filer_Query = r"SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
|
|
#tag = executer.ExecuteVBS(vbs_content=vbs, filer_Query=filer_Query, returnTag=True)
|
|
|
|
# Wait 5 seconds for next step.
|
|
for i in range(5,0,-1):
|
|
print(f"[+] Waiting {i}s for next step.", end="\r", flush=True)
|
|
time.sleep(1)
|
|
else:
|
|
# Experimental: use timer instead of filter query
|
|
with open('./lib/vbscripts/Exec-Command-WithOutput-UnderNT6.vbs') as f: vbs = f.read()
|
|
vbs = vbs.replace('REPLACE_WITH_COMMAND', base64.b64encode(command.encode('utf-8')).decode('utf-8')).replace('REPLACE_WITH_FILENAME', FileName).replace('REPLACE_WITH_CLASSNAME',ClassName_StoreOutput).replace('RELEACE_WITH_UUID',CMD_instanceID)
|
|
tag = executer.ExecuteVBS(vbs_content=vbs, returnTag=True)
|
|
|
|
# Reuse cimv2
|
|
iWbemServices_Reuse_cimv2 = self.timer_For_UnderNT6(iWbemServices=iWbemServices_Reuse_cimv2, return_iWbemServices=True)
|
|
|
|
executer.remove_Event(tag)
|
|
|
|
print("\r\n[+] Getting command results...")
|
|
command_ResultObject, resp = iWbemServices_Reuse_cimv2.GetObject('{}.CreationClassName="{}"'.format(ClassName_StoreOutput, CMD_instanceID))
|
|
record = dict(command_ResultObject.getProperties())
|
|
result = base64.b64decode(record['DebugOptions']['value']).decode(self.codec, errors='replace')
|
|
print(result)
|
|
|
|
if save_Result == True and hostname != None:
|
|
self.save_ToFile(hostname, result)
|
|
|
|
def clear(self, ClassName_StoreOutput=None):
|
|
if ClassName_StoreOutput == None: ClassName_StoreOutput = "Win32_OSRecoveryConfigurationDataBackup"
|
|
|
|
class_Method = class_MethodEx(self.iWbemLevel1Login)
|
|
class_Method.remove_Class(ClassName=ClassName_StoreOutput, return_iWbemServices=False)
|
|
|
|
class EXEC_COMMAND_SHELL(cmd.Cmd):
|
|
def __init__(self, iWbemLevel1Login, dcom, codec):
|
|
cmd.Cmd.__init__(self)
|
|
self.codec = codec
|
|
self.dcom = dcom
|
|
self.cwd = 'C:\Windows\System32'
|
|
self.prompt = "%s>" %self.cwd
|
|
self.intro = '[!] Launching semi-interactive shell - Careful what you execute'
|
|
self.iWbemLevel1Login = iWbemLevel1Login
|
|
self.executer = executeVBS_Toolkit(self.iWbemLevel1Login)
|
|
self.ClassName_StoreOutput = "Win32_OSRecoveryConfigurationDataBackup"
|
|
|
|
# Reuse cimv2 namespace to avoid dcom limition
|
|
class_Method = class_MethodEx(self.iWbemLevel1Login)
|
|
self.iWbemServices_Reuse_cimv2 = class_Method.check_ClassStatus(self.ClassName_StoreOutput, return_iWbemServices=True)
|
|
self.iWbemServices_Reuse_subscription = None
|
|
|
|
def do_exit(self, line):
|
|
self.dcom.disconnect()
|
|
sys.exit(1)
|
|
|
|
def process_Result(self, result):
|
|
tmp_list = re.split(r'\[COMMAND\]|\[PATH\]',result)
|
|
self.cwd = tmp_list[2].strip('\r\n').lstrip()
|
|
cmd_Result = tmp_list[1].strip('\r\n').lstrip()
|
|
self.prompt = "%s>" %self.cwd
|
|
print(cmd_Result + "\r\n")
|
|
|
|
def default(self, line):
|
|
FileName = str(uuid.uuid4()) + ".log"
|
|
CMD_instanceID = str(uuid.uuid4())
|
|
random_TaskName = str(uuid.uuid4())
|
|
|
|
command = line
|
|
if "'" in command: command = command.replace("'",r'"')
|
|
|
|
with open('./lib/vbscripts/Exec-Command-WithOutput-Shell.vbs') as f: vbs = f.read()
|
|
vbs = vbs.replace('REPLACE_WITH_CWD', base64.b64encode(self.cwd.encode('utf-8')).decode('utf-8')).replace('REPLACE_WITH_COMMAND', base64.b64encode(command.encode('utf-8')).decode('utf-8')).replace('REPLACE_WITH_FILENAME', FileName).replace('REPLACE_WITH_CLASSNAME', self.ClassName_StoreOutput).replace('RELEACE_WITH_UUID',CMD_instanceID).replace('REPLACE_WITH_TASK',random_TaskName)
|
|
# Reuse subscription namespace to avoid dcom limition
|
|
if self.iWbemServices_Reuse_subscription is None:
|
|
tag, self.iWbemServices_Reuse_subscription = self.executer.ExecuteVBS(vbs_content=vbs, returnTag=True, BlockVerbose=True, return_iWbemServices=True)
|
|
else:
|
|
tag, self.iWbemServices_Reuse_subscription = self.executer.ExecuteVBS(vbs_content=vbs, returnTag=True, BlockVerbose=True, iWbemServices=self.iWbemServices_Reuse_subscription ,return_iWbemServices=True)
|
|
|
|
# Wait 5 seconds for next step.
|
|
for i in range(5,0,-1):
|
|
print(f"[+] Waiting {i}s for next step.", end="\r", flush=True)
|
|
time.sleep(1)
|
|
print("\r\n[+] Results: \r\n")
|
|
|
|
self.executer.remove_Event(tag, BlockVerbose=True, iWbemServices=self.iWbemServices_Reuse_subscription)
|
|
|
|
command_ResultObject, resp = self.iWbemServices_Reuse_cimv2.GetObject('{}.CreationClassName="{}"'.format(self.ClassName_StoreOutput, CMD_instanceID))
|
|
record = dict(command_ResultObject.getProperties())
|
|
result = base64.b64decode(record['DebugOptions']['value']).decode(self.codec, errors='replace')
|
|
self.process_Result(result)
|
|
|