Command-Line Detections
Beacon commands work by running a new process, usually started by the CreateProcessA API
BOOL CreateProcessA(
[in, optional] LPCSTR lpApplicationName,
[in, out, optional] LPSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCSTR lpCurrentDirectory,
[in] LPSTARTUPINFOA lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
The API accepts 2 string parameters: lpApplicationName and lpCommandLine . Lets look at how theyre used with some commands
shell- lpApplicationName is NULL
- lpCommandLine is C:\Windows\System32\cmd.exe /C <your command>
run- lpApplicationName is NULL
- lpCommandLine is <your command>
powershell- lpApplicationName is NULL
- lpCommandLine is powershell -nop -exec bypass -EncodedCommand <your command as a b64 string>
fork & run (spawn)- lpApplicationName is NULL
- lpCommandLine is <the current spawnto>
pth
- Beacon's built-in
pth(pass-the-hash) command is a wrapper around Mimikatz'ssekurlsa::pthmodule - pth is a means of impersonating a user by way of their NTLM hash
- the output below shows even though
beacon> getuid
[*] Tasked beacon to get userid
[*] You are NT AUTHORITY\SYSTEM (admin)
beacon> pth CONTOSO\rsteel FC525C9683E8FE067095BA2DDC971889
[*] Tasked beacon to run mimikatz's sekurlsa::pth /user:"rsteel" /domain:"CONTOSO" /ntlm:FC525C9683E8FE067095BA2DDC971889 /run:"%COMSPEC% /c echo 3653adf6614 > \\.\pipe\c0b81c" command
[+] [job 0] received output:
user : rsteel
domain : CONTOSO
program : C:\Windows\system32\cmd.exe /c echo 3653adf6614 > \\.\pipe\c0b81c
impers. : no
NTLM : fc525c9683e8fe067095ba2ddc971889
ERROR kuhl_m_sekurlsa_pth ; CreateProcessWithLogonW (0x00000005)
beacon> windows_error_code 5
ERROR_ACCESS_DENIED
- also tells us mimikatz tried to run C:\Windows\system32\cmd.exe /c echo 3653adf6614 > \\.\pipe\c0b81c using
CreateProcessWithLogonW, a named pipe impersonation technique- so the acces denied error was in response to this API
uac-schtasks
- UAC bypass technique thats provided by CS's Elevate Kit.
- Purpose is to elevate from a medium-integrity session to high-integrity session
beacon> elevate uac-schtasks tcp-local
[*] Tasked Beacon to run windows/beacon_bind_tcp (127.0.0.1:1337) in a high integrity context
[+] [job 0] received output:
ERROR: Start-Process : This command cannot be run due to the error: Access is denied.
ERROR: At line:77 char:21
ERROR: + ... $Process = Start-Process -FilePath $schtasksPath -ArgumentList '/Run ...
ERROR: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ERROR: + CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
ERROR: + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcess
ERROR: Command
ERROR:
- we also get an access denied error here
- the main cause of detection can be traced to whats happening underneathe the hood here
beacon_exploit_registerfunction is used to add exploits to theelevatecommand- the interesting function here is
schtasks_exploit - which imports a PS script called
Invoke-EnvBypass.ps1, generates a PowerShell one-liner payload and then runs it via the Invoke-EnvBypass cmdlet - the PS script calls
Start-Processin order to run the nativeschtasks.exetool with the cmdline arguments /Run /TN \Microsoft\Windows\DiskCleanup\SilentCleanup /I.
Why Access Denied?
We get an access denied error because the Windows Defender driver has kernel routings that allow drivers to register a callback routing when events of interest occur, such as a process being started
The driver is able to inspect ImageFileName and CommandLine callbacks
If it sees something it doesnt like, it can set CreationStatus to a non-success value, typically STATUS_ACCESS_DENIED, to prevent the process from being started.
The Solution
The only thing you can do unless you find a kernel vulnerability is to a different procedure that achieves teh same outcome
For example instead of running schtasks.exe with 'SilentCleanup' on the command line, you can use a different API or COM object that can be used to trigger the task instead