Updating Apps: A New Era

Last Updated on February 1, 2022 by rudyooms

Last week I was asked to come up with a solution to give end-users the possibility to start updating DDS-CAD on their own.

Because of that nice option we created, we immediately had a lot of use cases. One of them was the Sonos App. Of course, there are many more examples, but this one was already asked for a long time ago.

I will divide this blog into multiple parts

  1. Introduction
  2. The Script Explanation
  3. The PowerShell Script
  4. The Results

1. Introduction

“Some Companies” are using the Sonos app to deploy music to their sound systems. Normally this shouldn’t be a problem when the device is not enrolled. As mentioned in the last blog about the app update solution, when NOT being a local admin, updating “stuff” could be difficult!

When launching the Sonos App, it will check for an update and you can’t update it without the proper permissions, and without that update, you just can’t use the Sonos App anymore! What comes first? The Chicken or the App?

Another little difference between DDS-Cad and the Sonos app is that with the DDS-CAD app there was already a build-in solution to update the DDS-CAD app, but with the Sonos update, it was a little bit different.

As told above, you can’t use the app to update it so we needed to download the so much-needed update from their website. So we altered and updated our App update script a little bit.

2. The Script Explanation

Just like the last time, I will first show you a brief summary of what we did to get it working. This explanation will show you the part you will need to Encode (Please read this blog how you could do so) and some very important stuff of the PowerShell command we are executing with a system “scheduled” task

  • Let’s start with the most important one!: When making use of serviceui.exe as shown below

Please, pretty please make sure to try to use the Silent installation first. If that’s not possible check the Application update yourself! Because when the application asks for the installation location, you could easily escape the app and open a cmd with system permissions by browsing to the system32 folder and opening the CMD.exe. That’s definitely something we don’t want!

I Don't Want That GIFs | Tenor
  • We added the part to download the required EXE file. As shown below we are making use of the “net.webclient” instead of the “invoke-webrequest because we all know invoke-webrequest is a little bit slo………wwwwww… Also we needed to added some headers otherwise we would end up with a 403 Error.
Afbeelding met tekst

Automatisch gegenereerde beschrijving
  • After we downloaded the file to a temporary location we first need to check if the file matches the allowed publisher. Why? Because we want to be sure it’s not been tempered with.
  • If the publisher matches we need to extract the EXE $outfile first with the use of some parameters.
Afbeelding met tekst

Automatisch gegenereerde beschrijving

We first tried the installation without extracting the EXE file. When we didn’t extract the file to a specific location it showed us a nice error. As it would try to launch the MSI file from the c:\windows\temp\templocation in a different process.

Please Note: We could add the /qn switch to the msiexec.exe command, but I wanted to show some progress to the user itself even while we are also showing some toast notifications

  • This part isn’t in the encoded command but still I need to mention it!. In the DDS-CAD update blog, I already was mentioning the version 2 of changing the task permissions. With this PowerShell script we removed the old version and made sure this one is doing its job. Looking closer to this part: ‘(A;;GRGX;;;AU)’. It is just the accessmask 1179817 and this maps to read and execute permissions for Authenticated Users
Afbeelding met tekst

Automatisch gegenereerde beschrijving

3. The PowerShell script

I will divide it into 2 parts.. First the PowerShell you will need to deploy. The second one will show you what you will need to change/convert! As I am mentioning in this blog

Remove Sensitive Information from the Intune Log Files (call4cloud.nl)

The First Part (Encoded)

Of Course, like always I am using toast notifications and serviceui.exe to get it working!

#################################
#Configure encoded commands here#
#################################

$encodedcommand = "JAB1AHIAbAAgAD0AIAAiAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHMAbwBuAG8AcwAuAGMAbwBtAC8AcgBlAGQAaQByAC8AYwBvAG4AdAByAG8AbABsAGUAcgBfAHMAbwBmAHQAdwBhAHIAZQBfAHAAYwAyACIACgAkAG8AdQB0AGYAaQBsAGUAIAA9ACAAIgBjADoAXAB0AGUAbQBwAFwAUwBvAG4AbwBzAFUAcABkAGEAdABlAC4AZQB4AGUAIgAKACQAYQBsAGwAbwB3AGUAZABwAHUAYgBsAGkAcwBoAGUAcgAgAD0AIAAiAE8APQBTAE8ATgBPAFMALAAgAEkATgBDAC4ALAAgAEwAPQBTAEEATgBUAEEAIABCAEEAUgBCAEEAUgBBACwAIABTAD0AQwBBAEwASQBGAE8AUgBOAEkAQQAsACAAQwA9AFUAUwAiAAoAJABNAFMASQBGAGkAbABlACAAPQAgACIAQwA6AFwAVABlAG0AcABcAFMAbwBuAG8AcwAuAG0AcwBpACIACgAKAAoAJABwAGEAdABoACAAPQAgACIAQwA6AFwAdABlAG0AcABcACIACgBJAGYAKAAhACgAdABlAHMAdAAtAHAAYQB0AGgAIAAkAHAAYQB0AGgAKQApAAoACQB7AAoAIAAgACAAIAAJAAkATgBlAHcALQBJAHQAZQBtACAALQBJAHQAZQBtAFQAeQBwAGUAIABEAGkAcgBlAGMAdABvAHIAeQAgAC0ARgBvAHIAYwBlACAALQBQAGEAdABoACAAJABwAGEAdABoAAoACQB9AAoACgAkAGMAbwBtAHAAdQB0AGUAcgAgAD0AIAAiAGwAbwBjAGEAbABoAG8AcwB0ACIACgAKACQAdQByAGwAIAA9ACAAIgBoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBzAG8AbgBvAHMALgBjAG8AbQAvAHIAZQBkAGkAcgAvAGMAbwBuAHQAcgBvAGwAbABlAHIAXwBzAG8AZgB0AHcAYQByAGUAXwBwAGMAMgAiAAoAJABvAHUAdABmAGkAbABlACAAPQAgACIAYwA6AFwAdABlAG0AcABcAFMAbwBuAG8AcwBVAHAAZABhAHQAZQAuAGUAeABlACIACgAkAGEAbABsAG8AdwBlAGQAcAB1AGIAbABpAHMAaABlAHIAIAA9ACAAIgBPAD0AUwBPAE4ATwBTACwAIABJAE4AQwAuACwAIABMAD0AUwBBAE4AVABBACAAQgBBAFIAQgBBAFIAQQAsACAAUwA9AEMAQQBMAEkARgBPAFIATgBJAEEALAAgAEMAPQBVAFMAIgAKAAoAJAB0AGkAdABsAGUAMQAgAD0AIAAiAFMAbwBuAG8AcwAgAHcAbwByAGQAdAAgAGcAZQBkAG8AdwBuAGwAbwBhAGQAIgAKACQAbQBlAHMAcwBhAGcAZQAxACAAPQAgACIARQBlAG4AIABiAGUAbABhAG4AZwByAGkAagBrAGUAIAB1AHAAZABhAHQAZQAgAHYAbwBvAHIAIABTAG8AbgBvAHMAIAB3AG8AcgBkAHQAIABnAGUAZABvAHcAbgBsAG8AYQBkACIACgAkAHQAaQB0AGwAZQAxAGEAIAA9ACAAIgBTAG8AbgBvAHMAIABrAGEAbgAgAHcAbwByAGQAZQBuACAAZwBlAO8AbgBzAHQAYQBsAGwAZQBlAHIAZAAiAAoAJABtAGUAcwBzAGEAZwBlADEAYQAgAD0AIAAiAEIAaQBuAG4AZQBuACAAZQBuAGsAZQBsAGUAIABtAG8AbQBlAG4AdABlAG4AIAB6AGEAbAAgAGgAZQB0ACAAaQBuAHMAdABhAGwAbABhAHQAaQBlAHMAYwBoAGUAcgBtACAAZwBlAHQAbwBvAG4AZAAgAHcAbwByAGQAZQBuACIACgAKACQAdABpAHQAbABlADIAIAA9ACAAIgBTAG8AbgBvAHMAIABpAHMAIABiAGkAagBnAGUAdwBlAHIAawB0ACIACgAkAG0AZQBzAHMAYQBnAGUAMgAgAD0AIAAiAEUAZQBuACAAYgBlAGwAYQBuAGcAcgBpAGoAawBlACAAdQBwAGQAYQB0AGUAIAB2AG8AbwByACAAUwBvAG4AbwBzACAAaQBzACAAYgBpAGoAZwBlAHcAZQByAGsAdAAiAAoAJAB0AGkAdABsAGUAMwA9ACAAIgBTAG8AbgBvAHMAIABiAGkAagB3AGUAcgBrAGUAbgAgAGkAcwAgAG0AaQBzAGwAdQBrAHQAIgAKACQAbQBlAHMAcwBhAGcAZQAzACAAPQAgACIAUwBvAG4AbwBzACAAawBhAG4AIAAgAG4AaQBlAHQAIABiAGkAagBnAGUAdwBlAHIAawB0ACAAdwBvAHIAZABlAG4AIgAKAFsAcgBlAGYAbABlAGMAdABpAG8AbgAuAGEAcwBzAGUAbQBiAGwAeQBdADoAOgBsAG8AYQBkAHcAaQB0AGgAcABhAHIAdABpAGEAbABuAGEAbQBlACgAIgBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBGAG8AcgBtAHMAIgApAAoAWwByAGUAZgBsAGUAYwB0AGkAbwBuAC4AYQBzAHMAZQBtAGIAbAB5AF0AOgA6AGwAbwBhAGQAdwBpAHQAaABwAGEAcgB0AGkAYQBsAG4AYQBtAGUAKAAiAFMAeQBzAHQAZQBtAC4ARAByAGEAdwBpAG4AZwAiACkACgAkAFAAUwBwAGEAdABoACAAPQAgAEcAZQB0AC0AUAByAG8AYwBlAHMAcwAgAC0AaQBkACAAJABwAGkAZAAgAHwAIABTAGUAbABlAGMAdAAtAE8AYgBqAGUAYwB0ACAALQBFAHgAcABhAG4AZABQAHIAbwBwAGUAcgB0AHkAIABQAGEAdABoACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAACgAkAGkAYwBvAG4AIAA9ACAAWwBTAHkAcwB0AGUAbQAuAEQAcgBhAHcAaQBuAGcALgBJAGMAbwBuAF0AOgA6AEUAeAB0AHIAYQBjAHQAQQBzAHMAbwBjAGkAYQB0AGUAZABJAGMAbwBuACgAJABQAFMAcABhAHQAaAApACAAIAAgACAAIAAgACAAIAAgACAAIAAKACQAbgBvAHQAaQBmAHkAIAA9ACAAbgBlAHcALQBvAGIAagBlAGMAdAAgAHMAeQBzAHQAZQBtAC4AdwBpAG4AZABvAHcAcwAuAGYAbwByAG0AcwAuAG4AbwB0AGkAZgB5AGkAYwBvAG4ACgAkAG4AbwB0AGkAZgB5AC4AaQBjAG8AbgAgAD0AIAAkAGkAYwBvAG4ACgAkAG4AbwB0AGkAZgB5AC4AdgBpAHMAaQBiAGwAZQAgAD0AIAAkAHQAcgB1AGUACgAkAG4AbwB0AGkAZgB5AC4AcwBoAG8AdwBiAGEAbABsAG8AbwBuAHQAaQBwACgANQAwACwAJAB0AGkAdABsAGUAMQAsACQATQBlAHMAcwBhAGcAZQAxACwAWwBzAHkAcwB0AGUAbQAuAHcAaQBuAGQAbwB3AHMALgBmAG8AcgBtAHMALgB0AG8AbwBsAHQAaQBwAGkAYwBvAG4AXQA6ADoAaQBuAGYAbwApACAACgAKACQAZABjACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0AAoACgAjACMAIABTAHQAYQByAHQAIABEAG8AdwBuAGwAbwBhAGQAIABJAG4AcwB0AGEAbABsAGUAcgAgACMAIwAKACQAbgBvAHQAaQBmAHkALgBzAGgAbwB3AGIAYQBsAGwAbwBvAG4AdABpAHAAKAA1ADAALAAkAHQAaQB0AGwAZQAxACwAJABNAGUAcwBzAGEAZwBlADEALABbAHMAeQBzAHQAZQBtAC4AdwBpAG4AZABvAHcAcwAuAGYAbwByAG0AcwAuAHQAbwBvAGwAdABpAHAAaQBjAG8AbgBdADoAOgBpAG4AZgBvACkACgAkAGQAYwAuAFUAcwBlAEQAZQBmAGEAdQBsAHQAQwByAGUAZABlAG4AdABpAGEAbABzACAAPQAgACQAdAByAHUAZQAKACQAZABjAC4ASABlAGEAZABlAHIAcwAuAEEAZABkACgAIgB1AHMAZQByAC0AYQBnAGUAbgB0ACIALAAgACIASQBuAHQAZQByACAARQB4AHAAbABvAHIAZQByACIAKQAKACQAZABjAC4ASABlAGEAZABlAHIAcwAuAEEAZABkACgAIgBYAC0ARgBPAFIATQBTAF8AQgBBAFMARQBEAF8AQQBVAFQASABfAEEAQwBDAEUAUABUAEUARAAiACwAIAAiAGYAIgApAAoACgAkAGQAYwAuAEQAbwB3AG4AbABvAGEAZABGAGkAbABlACgAJAB1AHIAbAAsACQAbwB1AHQAZgBpAGwAZQApAAoACgAjACMAIABHAGUAdAAgAFAAdQBiAGwAaQBzAGgAZQByACAAbwBmACAAZABvAHcAbgBsAG8AYQBkAGUAZAAgAGYAaQBsAGUAIAAjACMACgAkAHAAdQBiAGwAaQBzAGgAZQByACAAPQAgACgARwBlAHQALQBBAHAAcABMAG8AYwBrAGUAcgBGAGkAbABlAEkAbgBmAG8AcgBtAGEAdABpAG8AbgAgAC0AcABhAHQAaAAgACQAbwB1AHQAZgBpAGwAZQApAC4AUAB1AGIAbABpAHMAaABlAHIACgAKACMAIwAgAFMAdABhAHIAdAAgAGkAbgBzAHQAYQBsAGwAYQB0AGkAbwBuACwAIABvAG4AbAB5ACAAaQBmACAAcAB1AGIAbABpAHMAaABlAHIAIABpAHMAIABhAGwAbABvAHcAZQBkACAAIwAjAAoAaQBmACgAJABwAHUAYgBsAGkAcwBoAGUAcgAuAFAAdQBiAGwAaQBzAGgAZQByAE4AYQBtAGUAIAAtAGUAcQAgACQAYQBsAGwAbwB3AGUAZABwAHUAYgBsAGkAcwBoAGUAcgApAHsACgAgACAAIAAgACQAbgBvAHQAaQBmAHkALgBzAGgAbwB3AGIAYQBsAGwAbwBvAG4AdABpAHAAKAA1ADAALAAkAHQAaQB0AGwAZQAxAGEALAAkAE0AZQBzAHMAYQBnAGUAMQBhACwAWwBzAHkAcwB0AGUAbQAuAHcAaQBuAGQAbwB3AHMALgBmAG8AcgBtAHMALgB0AG8AbwBsAHQAaQBwAGkAYwBvAG4AXQA6ADoAaQBuAGYAbwApAAoAIAAgACAAIAB0AHIAeQB7AAoAJgAgACQAbwB1AHQAZgBpAGwAZQAgAC8AcwAgAC8AeAAgAC8AYgAiAEMAOgBcAHQAZQBtAHAAIgAgAC8AdgAiAC8AcQBuACIACgAgACAAIAAgACAAIAAgACAAUwB0AGEAcgB0AC0AUwBsAGUAZQBwACAALQBzACAAMwAKACAAIAAgACAAIAAgACAAIABSAGUAbQBvAHYAZQAtAEkAdABlAG0AIAAtAFAAYQB0AGgAIAAkAG8AdQB0AGYAaQBsAGUACgAKACAAIAAgACAAIAAgACAAIAAjACMAIABTAHQAYQByAHQAIABpAG4AcwB0AGEAbABsAGUAcgAgAGkAZgAgAGUAeABpAHMAdABzACAAIwAjAAoAIAAgACAAIAAgACAAIAAgAEkAZgAoACgAdABlAHMAdAAtAHAAYQB0AGgAIAAkAE0AUwBJAEYAaQBsAGUAIAAtAFAAYQB0AGgAVAB5AHAAZQAgAEwAZQBhAGYAKQApAAoACQAgACAAIAAgACAAIAAgACAAewAKACAAIAAgACAACQAJACAAIAAgACAAIAAgACAAIABNAHMAaQBFAHgAZQBjAC4AZQB4AGUAIAAvAGkAIAAkAE0AUwBJAEYAaQBsAGUAIAAKAAkAIAAgACAAIAAgACAAIAAgAH0ACgAKACAAIAAgACAAfQAKACAAIAAgACAAIAAgACAAIABjAGEAdABjAGgAewAKACAAIAAgACAAIAAgACAAIAB3AHIAaQB0AGUALQBoAG8AcwB0ACAAIgBCAGkAagB3AGUAcgBrAGUAbgAgAE0AaQBzAGwAdQBrAHQAIQAiAAoAIAAgACAAIAAgACAAIAAgACQAbgBvAHQAaQBmAHkALgBzAGgAbwB3AGIAYQBsAGwAbwBvAG4AdABpAHAAKAA1ADAALAAkAHQAaQB0AGwAZQAzACwAJABNAGUAcwBzAGEAZwBlADMALABbAHMAeQBzAHQAZQBtAC4AdwBpAG4AZABvAHcAcwAuAGYAbwByAG0AcwAuAHQAbwBvAGwAdABpAHAAaQBjAG8AbgBdADoAOgBpAG4AZgBvACkACgAgACAAIAAgACAAIAAgACAAfQAKAH0ACgA="

$taskname = "UpdateSonosV2"
$Shortcutname = "Update Sonos"
$Link = "C:\Users\Public\Desktop\$Shortcutname.lnk"
$iconlocation = "C:\Program Files (x86)\SonosV2\Sonos.exe,0"



##############################################################################################
#Download and install ServiceUI#
##############################################################################################

$path = "C:\program files (x86)\service"
New-Item -ItemType Directory -Force -Path $path
Invoke-WebRequest https://call4cloud.nl/wp-content/uploads/2021/07/ServiceUI.zip -OutFile "$path\ZippedFile.zip"
Expand-Archive -LiteralPath "$path\ZippedFile.zip" -DestinationPath "$path" -force


####################################################
####Install the Update task !                #
####################################################

$triggers = New-ScheduledTaskTrigger -Once -At (get-date).AddSeconds(-200); $triggers.EndBoundary = (get-date).AddSeconds(-100).ToString('s')
$Action = New-ScheduledTaskAction -Execute "c:\program files (x86)\service\ServiceUI.exe" -argument "-process:explorer.exe c:\Windows\System32\WindowsPowershell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -encodedcommand $encodedcommand"
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable
$Null = Register-ScheduledTask -TaskName $taskname -Trigger $triggers -User "SYSTEM" -Action $Action -Settings $Settings -Force


############################################################################
####Change Permissions for the task version 2! #
############################################################################

$scheduler = New-Object -ComObject "Schedule.Service"
$scheduler.Connect()
$task = $scheduler.GetFolder("\").GetTask($taskname)
$sec = $task.GetSecurityDescriptor(0xF)
$sec = $sec + '(A;;GRGX;;;AU)'

             ###################################
             #PLEASE NOTE GRGX --> 1179817     # 
             ###################################

$task.SetSecurityDescriptor($sec, 0)


## Create Shortcut to task on Desktop ##
if (-not (Test-Path $Link))
{
       $null = $WshShell = New-Object -comObject WScript.Shell
       $targetpath = "C:\Windows\System32\schtasks.exe"
       $Shortcut = $WshShell.CreateShortcut($Link)
       $Shortcut.TargetPath = $targetpath
       $Shortcut.Arguments = "/run /TN $taskname"
       $Shortcut.IconLocation = $IconLocation
       $Shortcut.Save()
} 

The Second Part (What you will need to convert)



#########################################################################################
#Toast Example: please convert it to base64 and adjust the $encodedcommand above     #
#read more on https://call4cloud.nl/2021/12/code-name-the-log-cleaner/                      #
#                                                                         #
#      Encoded Command  | Notifying and Installing The Update                         #
###########################################################################################

$url = https://www.sonos.com/redir/controller_software_pc2
$outfile = "c:\temp\SonosUpdate.exe"
$allowedpublisher = "O=SONOS, INC., L=SANTA BARBARA, S=CALIFORNIA, C=US"
$MSIFile = "C:\Temp\Sonos.msi"

$path = "C:\temp\"
If(!(test-path $path))
       {
             New-Item -ItemType Directory -Force -Path $path
       }

$title1 = "Sonos wordt gedownload"
$message1 = "Een belangrijke update voor Sonos wordt gedownload"

$title1a = "Sonos kan worden geïnstalleerd"
$message1a = "Binnen enkele momenten zal het installatiescherm getoond worden"

$title3= "Sonos bijwerken is mislukt"
$message3 = "Sonos kan  niet bijgewerkt worden"

[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
[reflection.assembly]::loadwithpartialname("System.Drawing")
$PSpath = Get-Process -id $pid | Select-Object -ExpandProperty Path                   
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon($PSpath)           
$notify = new-object system.windows.forms.notifyicon
$notify.icon = $icon
$notify.visible = $true
$notify.showballoontip(50,$title1,$Message1,[system.windows.forms.tooltipicon]::info) 

	## Start Download Installer and notify user##

$notify.showballoontip(50,$title1,$Message1,[system.windows.forms.tooltipicon]::info)
$dc = New-Object net.webclient
$dc.UseDefaultCredentials = $true
$dc.Headers.Add("user-agent", "Inter Explorer")
$dc.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$dc.DownloadFile($url,$outfile)

# Get Publisher of downloaded file ##

$publisher = (Get-AppLockerFileInformation -path $outfile).Publisher

## Start installation, only if publisher is allowed ##

if($publisher.PublisherName -eq $allowedpublisher){
    $notify.showballoontip(50,$title1a,$Message1a,[system.windows.forms.tooltipicon]::info)
    try{
& $outfile /s /x /b"C:\temp" /v"/qn"
        Start-Sleep -s 3
        Remove-Item -Path $outfile

        ## Start installer if exists ##
        If((test-path $MSIFile -PathType Leaf))
               {
                     MsiExec.exe /i $MSIFile 
               }

    }
        catch{
        write-host "Bijwerken Mislukt!"
        $notify.showballoontip(50,$title3,$Message3,[system.windows.forms.tooltipicon]::info)
        }
}

###############################################################################################
#				END OF THE ENCODED PART!!!							####
###############################################################################################

4. The Results

The results are very easy to show, please upload the PowerShell script is deployed to the device the end user would receive a nice new icon on his desktop “Update Sonos”

After double-clicking on that icon, we would first receive a toast notification. It will notify the end-user that within a few moments the install screen will be shown

Because we are using the PowerShell webclient instead of the invoke-webrequest, it is just a matter of seconds before the installation screen popups!

After we installed the update it is possible to open the app again! We could even check for updates to see if there are any left…

As expected as shown below the Sonos-Systeem is already up to date

Afbeelding met tekst

Automatisch gegenereerde beschrijving

Conclusion


As mentioned earlier… it’s fantastic to give people the possibility to update some apps on their own behalf but giving the same people the possibility to update apps on their own is just unbelievable!

unbelievable gifs Page 2 | WiffleGif

Not to forget… It saves us time and time is money. I guess just like with the Company App we are now creating our own baseline with a lot of our own created “Update App PowerShell scripts”

Leave a Reply

Your email address will not be published. Required fields are marked *

  +  44  =  46