Adhoc deploy Sysmon on Azure Virtual Machine

If you ever need to deploy an executable like Sysmon on one or more VMs on Azure and don’t have any configuration management in place…

These Powershell Script snippets will come to rescue!

This process doesn’t provide a best practise on how to deploy software in an environment but if your tools and resources are limited this will help you out.

Powershell Az module

The plan is to send a script to an Azure VM using the following command as found in the Powershell Az module

Invoke-AzVMRunCommand -CommandId ‘RunPowerShellScript’ -ScriptPath ‘script.ps1’ -Parameter @{param1 = “-Verbose”}

What will happen, the script we refer to will be uploaded to the VM.
Next the script will be executed.

The script itself would download and execute a Sysmon.exe.

function DownloadSysmon {
$Result = $(Test-Path (Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath sysmon.exe));
if(-not $Result) {
try {
$tmpfile = [System.IO.Path]::GetTempFileName()
$null = Invoke-WebRequest -Uri '' `
-OutFile $tmpfile -ErrorAction Stop
Write-Verbose 'Sucessfully downloaded Sysmon.exe'
Unblock-File -Path $tmpfile -ErrorAction Stop
$exefile = Join-Path -Path (Split-Path -Path $tmpfile -Parent) -ChildPath 'a.exe'
if (Test-Path $exefile) {
Remove-Item -Path $exefile -Force -ErrorAction Stop
$tmpfile | Rename-Item -NewName 'a.exe' -Force -ErrorAction Stop
} catch {
Write-Verbose "Something went wrong $($_.Exception.Message)"

But this didn’t work out!
the command Invoke-Webrequest will result in “The underlying connection was closed: An unexpected error occurred on a send.

Underlying connection closed
Even though this machine normally could perform webrequests, from this session it doesn’t.
And there could also be a case where machines are isolated.
This approach is likely to fail.

Self extracting powershell script reversed

My next idea, we could convert a binary file into a string, put this string into a script file as a string variable together with scripting that would execute the opposite.
Let’s see what come of this.
1. read the contents of the file to a variable (Array of Bytes)
2. convert this Byte Array into a Base64 String
3. write string variable to a file

$fileAsByteArray = [System.IO.File]::ReadAllBytes($FilePath);
$Base64String = [System.Convert]::ToBase64String($fileAsByteArray);
$Base64String | Out-File '.\a file'

We wrap this file with scripting so the string will be loaded as a String variable and a function that will convert the string back to a byteArray and Write it to disk as an executable.
In the end we execute the executable.

$ByteArray = [System.Convert]::FromBase64String($sysmonAsString)
[System.IO.File]::WriteAllBytes('.\Sysmon.exe', $ByteArray);
Start-Process FilePath '.\Sysmon.exe'

There are cases this could work, but we are working with Sysmon.exe, it contains over 3M of Bytes.

This will result in: “Internal server error”Internal server error

Do not fear!
Back in the days of limited diskspace and 1,44MB High Density diskettes people invented compression.
The good thing is we can leverage this into our script.

The solution!
Compress Sysmon.exe to string

After compression Sysmon is only 31% of it’s original size.
And now everything is small enough to be send and the installation goes great!

Invoke AZVMRunCommand compressed Sysmon.exe as a string
Like I said before this is not a typical good form of software deployment.
Problems arise when the configuration drifts from the desired state.
If we need to change the configuration we need to change that on all the affected machines one by one.

But that will be a whole other blog…

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.