@@ -51,9 +51,17 @@ def __init__(self, target, username, password, domain, lmhash, nthash, doKerbero
5151 iWbemLevel1Login .RemRelease ()
5252 self .__win32Process , _ = self .__iWbemServices .GetObject ("Win32_Process" )
5353
54- def execute (self , command , output = False ):
54+ def execute (self , command , output = False , use_powershell = False ):
55+ """Execute a command on the remote host using WMI.
56+ Options:
57+ - No output
58+ - Output with bash (limited to ~1MB)
59+ - Output with PowerShell (recommended for larger outputs)
60+ """
5561 if output :
5662 self .execute_WithOutput (command )
63+ elif output and use_powershell :
64+ self .execute_WithOutput_psh (command )
5765 else :
5866 command = self .__shell + command
5967 self .execute_remote (command )
@@ -80,13 +88,54 @@ def execute_WithOutput(self, command):
8088 self .logger .info (f"Waiting { self .__exec_timeout } s for command to complete." )
8189 time .sleep (self .__exec_timeout )
8290
91+ # 2. Base64 encode the file
92+ self .execute_remote (f"{ self .__shell } certutil -encodehex -f { result_output } { result_output_b64 } 0x40000001" )
93+ time .sleep (0.5 )
94+
95+ # 3. Store content in registry
96+ self .execute_remote (f'{ self .__shell } for /F "usebackq" %G in ("{ result_output_b64 } ") do reg add HKLM\\ { self .__registry_Path } /v { keyName } /t REG_SZ /d "%G" /f' )
97+ time .sleep (0.1 )
98+
99+ self .queryRegistry (keyName )
100+ self .clean_up (result_output , result_output_b64 )
101+
102+ def queryRegistry (self , keyName ):
103+ try :
104+ # Spawn an instance of StdRegProv to access the registry
105+ self .logger .debug (f"Retrieving output from: HKLM\\ { self .__registry_Path } " )
106+ descriptor , _ = self .__iWbemServices .GetObject ("StdRegProv" )
107+ descriptor = descriptor .SpawnInstance ()
108+
109+ # Retrieve the base64 content from the registry
110+ for _ in range (10 ):
111+ self .logger .debug (f"Retrieving key: { keyName } " )
112+ outputBuffer_b64 = descriptor .GetStringValue (0x80000002 , self .__registry_Path , keyName ).sValue
113+ if outputBuffer_b64 is not None :
114+ break
115+ time .sleep (1 )
116+ self .__outputBuffer = base64 .b64decode (outputBuffer_b64 ).decode (self .__codec , errors = "replace" ).rstrip ("\r \n " )
117+ except Exception :
118+ self .logger .fail ("WMIEXEC: Could not retrieve output file! Either command timed out or AV killed the process. Please try increasing the timeout: '--exec-timeout 10'" )
119+
120+ def execute_WithOutput_psh (self , command ):
121+ """Same functionality as execute_WithOutput, but uses PowerShell to handle larger outputs by splitting the base64 content into chunks and storing it in the registry."""
122+ result_output = f"C:\\ windows\\ temp\\ { uuid .uuid4 ()!s} .txt"
123+ result_output_b64 = f"C:\\ windows\\ temp\\ { uuid .uuid4 ()!s} .txt"
124+ keyName = str (uuid .uuid4 ())
125+ self .__registry_Path = f"Software\\ Classes\\ test_nxc_{ gen_random_string (6 )} "
126+
127+ # 1. Run the command and write output to file
128+ self .execute_remote (f'powershell { command } 1> "{ result_output } " 2>&1' )
129+ self .logger .info (f"Waiting { self .__exec_timeout } s for command to complete." )
130+ time .sleep (self .__exec_timeout )
131+
83132 # 2. Base64 encode the file using PowerShell
84- self .execute_remote (f'{ self . __shell } powershell -Command "[Convert]::ToBase64String([IO.File]::ReadAllBytes(\' { result_output } \' )) | Out-File -Encoding ASCII \' { result_output_b64 } \' "' )
133+ self .execute_remote (f'powershell -Command "[Convert]::ToBase64String([IO.File]::ReadAllBytes(\' { result_output } \' )) | Out-File -Encoding ASCII \' { result_output_b64 } \' "' )
85134 time .sleep (0.5 )
86135
87136 # 3. Use PowerShell to split base64 content into 16KB chunks and store in registry
88137 self .execute_remote (
89- f'{ self . __shell } powershell -Command "$b64 = Get-Content -Raw \' { result_output_b64 } \' ; '
138+ f'powershell -Command "$b64 = Get-Content -Raw \' { result_output_b64 } \' ; '
90139 f'$chunksize = 16000; '
91140 f'$count = [math]::Ceiling($b64.Length / $chunksize); '
92141 f'for ($i = 0; $i -lt $count; $i++) {{ '
@@ -97,10 +146,10 @@ def execute_WithOutput(self, command):
97146 )
98147 time .sleep (0.1 )
99148
100- self .queryRegistry (keyName )
149+ self .queryRegistry_psh (keyName )
101150 self .clean_up (result_output , result_output_b64 )
102151
103- def queryRegistry (self , keyName ):
152+ def queryRegistry_psh (self , keyName ):
104153 try :
105154 # Spawn an instance of StdRegProv to access the registry
106155 self .logger .debug (f"Retrieving output from: HKLM\\ { self .__registry_Path } " )
0 commit comments