@@ -98,8 +98,8 @@ def getInterface(self, interface, resp):
9898 oxid = objRef ['std' ]['oxid' ], oid = objRef ['std' ]['oxid' ],
9999 target = interface .get_target ()))
100100
101- def run (self , addr ):
102- if self .__noOutput is False :
101+ def run (self , addr , silentCommand = False ):
102+ if self .__noOutput is False and silentCommand is False :
103103 smbConnection = SMBConnection (addr , addr )
104104 if self .__doKerberos is False :
105105 smbConnection .login (self .__username , self .__password , self .__domain , self .__lmhash , self .__nthash )
@@ -163,17 +163,21 @@ def run(self, addr):
163163
164164 iActiveView = IDispatch (self .getInterface (iMMC , resp ['pVarResult' ]['_varUnion' ]['pdispVal' ]['abData' ]))
165165 pExecuteShellCommand = iActiveView .GetIDsOfNames (('ExecuteShellCommand' ,))[0 ]
166- self .shell = RemoteShellMMC20 (self .__share , (iMMC , pQuit ), (iActiveView , pExecuteShellCommand ), smbConnection , self .__shell_type )
166+ self .shell = RemoteShellMMC20 (self .__share , (iMMC , pQuit ), (iActiveView , pExecuteShellCommand ), smbConnection , self .__shell_type , silentCommand )
167167 else :
168168 resp = iDocument .GetIDsOfNames (('Application' ,))
169169 resp = iDocument .Invoke (resp [0 ], 0x409 , DISPATCH_PROPERTYGET , dispParams , 0 , [], [])
170170
171171 iActiveView = IDispatch (self .getInterface (iMMC , resp ['pVarResult' ]['_varUnion' ]['pdispVal' ]['abData' ]))
172172 pExecuteShellCommand = iActiveView .GetIDsOfNames (('ShellExecute' ,))[0 ]
173- self .shell = RemoteShell (self .__share , (iMMC , pQuit ), (iActiveView , pExecuteShellCommand ), smbConnection , self .__shell_type )
173+ self .shell = RemoteShell (self .__share , (iMMC , pQuit ), (iActiveView , pExecuteShellCommand ), smbConnection , self .__shell_type , silentCommand )
174174
175175 if self .__command != ' ' :
176- self .shell .onecmd (self .__command )
176+ try :
177+ self .shell .onecmd (self .__command )
178+ except TypeError :
179+ if not silentCommand :
180+ raise
177181 if self .shell is not None :
178182 self .shell .do_exit ('' )
179183 else :
@@ -196,7 +200,7 @@ def run(self, addr):
196200 dcom .disconnect ()
197201
198202class RemoteShell (cmd .Cmd ):
199- def __init__ (self , share , quit , executeShellCommand , smbConnection , shell_type ):
203+ def __init__ (self , share , quit , executeShellCommand , smbConnection , shell_type , silentCommand = False ):
200204 cmd .Cmd .__init__ (self )
201205 self ._share = share
202206 self ._output = '\\ ' + OUTPUT_FILENAME
@@ -207,6 +211,7 @@ def __init__(self, share, quit, executeShellCommand, smbConnection, shell_type):
207211 self .__quit = quit
208212 self ._executeShellCommand = executeShellCommand
209213 self .__transferClient = smbConnection
214+ self ._silentCommand = silentCommand
210215 self ._pwd = 'C:\\ windows\\ system32'
211216 self ._noOutput = False
212217 self .intro = '[!] Launching semi-interactive shell - Careful what you execute\n [!] Press help for extra shell commands'
@@ -365,11 +370,15 @@ def output_callback(data):
365370 self .__transferClient .deleteFile (self ._share , self ._output )
366371
367372 def execute_remote (self , data , shell_type = 'cmd' ):
368- if shell_type == 'powershell' :
369- data = '$ProgressPreference="SilentlyContinue";' + data
370- data = self .__pwsh + b64encode (data .encode ('utf-16le' )).decode ()
373+ if self ._silentCommand is True :
374+ self ._shell = data .split ()[0 ]
375+ command = ' ' .join (data .split ()[1 :])
376+ else :
377+ if shell_type == 'powershell' :
378+ data = '$ProgressPreference="SilentlyContinue";' + data
379+ data = self .__pwsh + b64encode (data .encode ('utf-16le' )).decode ()
380+ command = '/Q /c ' + data
371381
372- command = '/Q /c ' + data
373382 if self ._noOutput is False :
374383 command += ' 1> ' + '\\ \\ 127.0.0.1\\ %s' % self ._share + self ._output + ' 2>&1'
375384
@@ -430,11 +439,15 @@ def send_data(self, data):
430439
431440class RemoteShellMMC20 (RemoteShell ):
432441 def execute_remote (self , data , shell_type = 'cmd' ):
433- if shell_type == 'powershell' :
434- data = '$ProgressPreference="SilentlyContinue";' + data
435- data = self ._RemoteShell__pwsh + b64encode (data .encode ('utf-16le' )).decode ()
442+ if self ._silentCommand is True :
443+ self ._shell = data .split ()[0 ]
444+ command = ' ' .join (data .split ()[1 :])
445+ else :
446+ if shell_type == 'powershell' :
447+ data = '$ProgressPreference="SilentlyContinue";' + data
448+ data = self ._RemoteShell__pwsh + b64encode (data .encode ('utf-16le' )).decode ()
449+ command = '/Q /c ' + data
436450
437- command = '/Q /c ' + data
438451 if self ._noOutput is False :
439452 command += ' 1> ' + '\\ \\ 127.0.0.1\\ %s' % self ._share + self ._output + ' 2>&1'
440453
@@ -532,6 +545,7 @@ def load_smbclient_auth_file(path):
532545
533546 parser = argparse .ArgumentParser (add_help = True , description = "Executes a semi-interactive shell using the "
534547 "ShellBrowserWindow DCOM object." )
548+
535549 parser .add_argument ('target' , action = 'store' , help = '[[domain/]username[:password]@]<targetName or address>' )
536550 parser .add_argument ('-share' , action = 'store' , default = 'ADMIN$' , help = 'share where the output will be grabbed from '
537551 '(default ADMIN$)' )
@@ -548,12 +562,12 @@ def load_smbclient_auth_file(path):
548562 help = 'DCOM object to be used to execute the shell command (default=ShellWindows)' )
549563 parser .add_argument ('-com-version' , action = 'store' , metavar = "MAJOR_VERSION:MINOR_VERSION" , help = 'DCOM version, '
550564 'format is MAJOR_VERSION:MINOR_VERSION e.g. 5.7' )
551-
552565 parser .add_argument ('-shell-type' , action = 'store' , default = 'cmd' , choices = ['cmd' , 'powershell' ], help = 'choose '
553566 'a command processor for the semi-interactive shell' )
554-
555567 parser .add_argument ('command' , nargs = '*' , default = ' ' , help = 'command to execute at the target. If empty it will '
556568 'launch a semi-interactive shell' )
569+ parser .add_argument ('-silentcommand' , action = 'store_true' , default = False ,
570+ help = 'does not execute cmd.exe to run given command (no output, cannot run dir/cd/etc.)' )
557571
558572 group = parser .add_argument_group ('authentication' )
559573
@@ -588,6 +602,9 @@ def load_smbclient_auth_file(path):
588602 if ' ' .join (options .command ) == ' ' and options .nooutput is True :
589603 logging .error ("-nooutput switch and interactive shell not supported" )
590604 sys .exit (1 )
605+ if options .silentcommand and options .command == ' ' :
606+ logging .error ("-silentcommand switch and interactive shell not supported" )
607+ sys .exit (1 )
591608
592609 if options .debug is True :
593610 logging .getLogger ().setLevel (logging .DEBUG )
@@ -627,7 +644,7 @@ def load_smbclient_auth_file(path):
627644
628645 executer = DCOMEXEC (' ' .join (options .command ), username , password , domain , options .hashes , options .aesKey ,
629646 options .share , options .nooutput , options .k , options .dc_ip , options .object , options .shell_type )
630- executer .run (address )
647+ executer .run (address , options . silentcommand )
631648 except (Exception , KeyboardInterrupt ) as e :
632649 if logging .getLogger ().level == logging .DEBUG :
633650 import traceback
0 commit comments