
Azure Virtual Machine Execution Techniques
Details five ways to execute code on an Azure VM beyond RDP/SSH: the Run Command agent, Custom Script Extension, Desired State Configuration (DSC) extension abuse, VM Application Definitions, and Hybrid Worker Groups — all running as SYSTEM/root by default. For each technique the author gives the exact PowerShell/Az cmdlets (including PowerZure's Invoke-AzureRunProgram and Invoke-AzureVMCustomScriptExtension), on-disk artifact paths, and the specific Azure Activity Log events (e.g. 'Run Command on Virtual machine', 'Create or Update Virtual Machine Extension') defenders should correlate on.
What it is
A hausec writeup of four ways to run code on an Azure VM as SYSTEM/root without RDP/SSH: Run Command, Custom Script Extension (CSE), DesiredStateConfiguration (DSC), and (cut off) VM Application Definitions. The summary names the techniques and logs; what it can't carry is the on-disk forensic paths, the DSC "failure-but-executed" quirk, and the detection-tuning nuances below.
How it works
Each technique drops its payload on disk, which is where a responder must go since logs omit command contents:
- Run Command uses the auto-installed VM agent (not an extension). Scripts land at
C:\Packages\Plugins\Microsoft.CPlat.Core.RunCommandWindows\1.1.11\Downloads. Callable via portal,Invoke-AzVMRunCommand(Az), REST API, or Azure CLI. PowerZure'sInvoke-AzureRunProgramcan ferry an entire binary over. The author calls this the loudest option — "cmd.exe /c level of noisy-ness." - CSE uploads a script deployed to the VM, stored at
C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.10.12\Downloads\. It is one-way (no return channel); output is retrieved by querying extension status. PowerZure exposesInvoke-AzureVMCustomScriptExtension. - DSC abuses the DSC extension via
Publish-AzvmdscConfiguration, packaging a.PS1function in a.zip. Stored atC:\Packages\Plugins\Microsoft.Compute.DesiredStateConfiguration.
What to do (defender)
- Run Command → alert on the
Run Command on Virtual machinelog, then pull the.PS1from the Downloads path to triage. If the script is missing, treat it as adversary cleanup and escalate to IR — that folder is not cleared on reboot or update, so absence is anomalous. - CSE and DSC both emit
Create or Update Virtual Machine Extension. Do not alert on that log alone — parse the log JSON to confirm the CSE (or DSC) extension type as correlation. Legitimate CSE use after provisioning is rare. - Watch for the op-sec-unfriendly portal path: portal CSE requires the script to come from an Azure Storage Account, which generates an additional storage-upload log. Command-line (
Set-AzVMCustomScriptExtension) and REST-API (PATCH) paths pull from arbitrary URIs (e.g. GitHub) and skip that signal.
Caveats
- DSC executes even when it reports failure. Because the malicious payload isn't valid DSC syntax, the extension status reads
failurewhile the code still runs — and the failure message overwrites any command output. Defenders cannot infer "did nothing" from a failed DSC extension. - Article is Windows-biased; techniques apply to Linux with changes.
- The VM Application Definitions section is truncated in the source text.
Organisations named here
- Invoke-AzureRunProgram
- Invoke-AzureVMCustomScriptExtension
Technologies named here
- Azure Virtual Machines
- Azure Run Command
- Windows 10 VM
- PowerZure
- Az PowerShell
- Azure REST API
- Azure CLI
- Custom Script Extension
- DesiredConfigurationState extension
- VM Application Definitions
- Hybrid Worker Groups
- Azure Activity Log
- Azure
- PowerShell
Techniques named here
- Run Command execution
- Custom Script Extension execution
- DSC extension abuse
- VM Application Definition abuse
- Hybrid Worker Group execution
Related in Offensive Security