Skip to content

Commit e192f3c

Browse files
committed
Split result output into 16KB chunks because that is the max value for registry keys
1 parent 188ef13 commit e192f3c

1 file changed

Lines changed: 34 additions & 8 deletions

File tree

nxc/protocols/wmi/wmiexec.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,32 +76,58 @@ def execute_WithOutput(self, command):
7676
self.__registry_Path = f"Software\\Classes\\{gen_random_string(6)}"
7777

7878
commands = [
79-
f"{self.__shell} {command} 1> {result_output} 2>&1",
79+
# 1. Run the command and write output to file
80+
f'{self.__shell} {command} 1> "{result_output}" 2>&1',
81+
82+
# 2. Base64 encode the file using PowerShell
8083
f'{self.__shell} powershell -Command "[Convert]::ToBase64String([IO.File]::ReadAllBytes(\'{result_output}\')) | Out-File -Encoding ASCII \'{result_output_b64}\'"',
81-
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',
82-
f"{self.__shell} del /q /f /s {result_output} {result_output_b64}",
84+
85+
# 3. Use PowerShell to split base64 content into 16KB chunks and store in registry
86+
f'{self.__shell} powershell -Command "$b64 = Get-Content -Raw \'{result_output_b64}\'; '
87+
f'$chunksize = 16000; '
88+
f'$count = [math]::Ceiling($b64.Length / $chunksize); '
89+
f'for ($i = 0; $i -lt $count; $i++) {{ '
90+
f' $chunk = $b64.Substring($i * $chunksize, [math]::Min($chunksize, $b64.Length - ($i * $chunksize))); '
91+
f' $name = \\"{keyName}_chunk_$i\\"; '
92+
f' reg add \\"HKLM\\{self.__registry_Path}\\" /v $name /t REG_SZ /d $chunk /f }}; '
93+
f'reg add \\"HKLM\\{self.__registry_Path}\\" /v \\"{keyName}\\" /t REG_DWORD /d $count /f"',
94+
95+
# 4. Delete temporary files
96+
f'{self.__shell} del /q /f "{result_output}" "{result_output_b64}"'
8397
]
8498

8599
for cmd in commands:
86100
self.execute_remote(cmd)
87101
time.sleep(0.5)
88-
self.logger.info(f"Waiting {self.__exec_timeout}s for command completely executed.")
102+
103+
self.logger.info(f"Waiting {self.__exec_timeout}s for command to complete.")
89104
time.sleep(self.__exec_timeout)
90105

91106
self.queryRegistry(keyName)
92107

93108
def queryRegistry(self, keyName):
94109
try:
95-
self.logger.debug(f"Querying registry key: HKLM\\{self.__registry_Path}")
110+
# Spawn an instance of StdRegProv to access the registry
111+
self.logger.debug(f"Retrieving output from: HKLM\\{self.__registry_Path}")
96112
descriptor, _ = self.__iWbemServices.GetObject("StdRegProv")
97113
descriptor = descriptor.SpawnInstance()
98-
retVal = descriptor.GetStringValue(0x80000002, self.__registry_Path, keyName)
99-
self.__outputBuffer = base64.b64decode(retVal.sValue).decode(self.__codec, errors="replace").rstrip("\r\n")
114+
115+
# Get the number of chunks stored in the registry
116+
num_chunks = descriptor.GetDWORDValue(0x80000002, self.__registry_Path, keyName).uValue
117+
self.logger.debug(f"Number of chunks: {num_chunks}")
118+
119+
# Retrieve each chunk and decode the base64 content
120+
outputBuffer_b64 = ""
121+
for i in range(num_chunks):
122+
chunk_name = f"{keyName}_chunk_{i}"
123+
self.logger.debug(f"Retrieving chunk: {chunk_name}")
124+
outputBuffer_b64 += descriptor.GetStringValue(0x80000002, self.__registry_Path, chunk_name).sValue
125+
self.__outputBuffer = base64.b64decode(outputBuffer_b64).decode(self.__codec, errors="replace").rstrip("\r\n")
100126
except Exception:
101127
self.logger.fail("WMIEXEC: Could not retrieve output file, it may have been detected by AV. Please try increasing the timeout with the '--exec-timeout' option. If it is still failing, try the 'smb' protocol or another exec method")
102128

103129
try:
104130
self.logger.debug(f"Removing temporary registry path: HKLM\\{self.__registry_Path}")
105-
retVal = descriptor.DeleteKey(0x80000002, self.__registry_Path)
131+
descriptor.DeleteKey(0x80000002, self.__registry_Path)
106132
except Exception as e:
107133
self.logger.debug(f"Target: {self.__target} removing temporary registry path error: {e!s}")

0 commit comments

Comments
 (0)