Microsoft Safety Scanner Powershell One Liner

Microsoft Safety Scanner Powershell One Liner

A client called in and told me a line of information that made me concerned about security. I ran a webroot scan and wanted to give another level of the scan. I am partial to the Microsoft Safety Scanner. It runs well connectwise backstage. You can read more about the safety scanner here. So, lets look at this oneliner.

if (!(Test-Path "c:\Temp")) { New-Item -Path "c:\" -Name Temp -ItemType Directory }; invoke-webrequest -Uri https://go.microsoft.com/fwlink/?LinkId=212732 -OutFile c:\temp\mss.exe -UseBasicParsing; c:\temp\mss.exe /Q /F:Y

The first part of this little script is to test and create the folder that will hold our file. We are doing this by using test-path. Then if the file doesn’t exist, aka !. Then we create it with the new-item.

if (!(Test-Path "c:\Temp")) { New-Item -Path "c:\" -Name Temp -ItemType Directory }

The next part is we are going to download the Microsoft security scanner from Microsoft directly. The link is the direct download. We use invoke-webrequest to download the file. The -outfile flag is where we will download the file at and its name. In this case, we are going to name it something simple. Mss.exe inside our temp folder. We use the -usebasicparsing because most machines only have PowerShell 5.

invoke-webrequest -Uri https://go.microsoft.com/fwlink/?LinkId=212732 -OutFile c:\temp\mss.exe -UseBasicParsing

Then we run the command needed. We start the command with the path. C:\temp\mss.exe. We want it to be quiet and we want to force it. So we use the /Q to quiet, and /F:Y to force.

c:\temp\mss.exe /Q /F:Y

The system will not prompt for any kind of approval. It will run and delete what it needs to delete. This is a simple, deploy and walk away one-liner. So, add it to your deployment scripts and enjoy scanning with a Microsoft safety scanner.

Install Sentinel One with Intune

Install Sentinel One with Intune

It’s time to Install Sentinel One. In this blog, we are going to go through the process of installing Sentinel One through Intune. We are going to be using the IntuneWinAppUtil program, and the MSI download of Sentinel one that you can obtain from your Sentinel one login portal. I will not go over how to download the msi installer.

File/Folder Structure

The next item you will need is the Microsoft Win32 Content Prep Tool [Link]. Once you have downloaded this file, I suggest creating a file structure as follows

  • Intune
    • Files
    • IntuneWin

After that, Extract the intunewinapputil.exe file to the top level of your file structure, intune. Place the MSI inside the Files location. Then we should be ready to run intunewinapputil.exe. Before you do, I always suggest reading the help by using the /? command line prompt. Here is the command we are going to use to convert our file.

Intune Win App Util

.\IntuneWinAppUtil.exe -c c:\Intune\Files -s SentinelOneInstaller.msi - o c:\Intune\IntuneWin

Afterward, we use the command above to convert our file into a intune installer file. This will give us a large amount of control. Things like detection rules, custom msi inputs and more. Which we will be using.

Intune – Setting up the installer

Next, It’s time to crack open the intune process. Log in to https://endpoint.microsoft.com/ with an account with intune rights.

Once you have logged into the endpoint management system. Click the Apps on the left-hand side of the screen.

Since we are deploying sentinel one to windows machines, under by platform, click the windows icon.

Uploading the Installer

Now we are going to click the add button on the right-hand side of the screen. This will bring up the add dialog box. We are deploying out the final option. Click the Windows App (Win32) option.

You will be brought to an upload page. Here you select the app package file and click the blue button on the right-hand side of the screen. This is where we go to the file we created in the previous steps. We upload the file here. Once it uploads it will populate the information like name and other items. Click ok to move to the app information page.

Setting the rules

Here we can change the name. Add a unique, html, description. Update the publisher, the application version and more. The category we are going to select is computer management. They show this as a featured app in the company portal. You want to check that one. This allows people to download this version of perch. If you want to feel in any of the other information you are welcome to. Once you have the required information, click next to go to the Program page. Where we determine how to install this application.

Adding the Key

On this page, we want to show the install and uninstall commands. This is where research comes into play. If you don’t know the silent install command of your program then that’s a problem. If you don’t know how your program responds to installs and the error codes or success codes it produces. that’s also a problem. You will need to know these things for other applications. Sentinel One is unique as it’s commands is a little different. Here is the install command:

msiexec /i "SentinelInstalle.msi" /q SITE_TOKEN="YourSiteToken"

Keep the uninstall command the same. As the MSI installer of Sentinel One is the app code. The biggest problem with the uninstall command with S1 is that it doesn’t work without prior approval. You have to log into the S1 Portal and approve its uninstall. Keep the default and continue.

Another thing to point out, this kicked my tail, the SITE_TOKEN does not have a /, I repeat NO /.

On this page, we can scan the system to make sure we meet the requirements. So if you know this is a heavy application, you can say to have at least 8GB of ram. You can even have PowerShell scripts that can trigger. A good example would be a user. If user Bob is on this PC don’t install it. The required items are the OS Arch and the minimum os. Which is going to be windows 10 1607 as that is intune’s min. Don’t get this confused with the next item. These are the requirements. Not meeting the requirements will prevent the app from installing. Once you have added what you want, click next.

On this page, we are going to select any dependencies that the application may need. Something unique about Sentinel One is, it will capture all of your custom PowerShell deployments. It’s best to set those as dependencies on this installer. This way they will deploy before S1 does. S1, doesn’t need any additional dependencies from my current knowledge and testing.

Detection Rules

We are going to use a Powershell Script to validate the install. Click on the Rule Format and select Use Custom Detection script. Upload your script file using the blue folder icon.

$A = 0
do {
    try {
        $Services = Get-Service -name SentinelAgent
    }
    catch {
        $Services = $null
    }
    start-sleep -Seconds 30
    $A = $A + 30
} until (($null -ne $Services) -or ($A -ge 300))
if ($null -ne $Services) { Write-Host "Installed" } else { exit }

This script checks for the Sentinel Agent every 30 seconds after installation. Then it increases my timer, by 30. It finally stops at 300 seconds. If services are null, it just exits, and thus a failure is seen in intune. If it is installed, it exits with a string. This tells the system that the installation was successful. What I like about this part is, that if the edit needs to be done, it can be done at this point using PowerShell.

The next screen supersedence is where you can choose what will replace the application. This is a preview feature at the moment and the idea is for upgrades. The final section is the Assignment, this is where you will select a group of devices for S1 to deploy out to.

I hope this is helpful for everyone viewing this page.

Perch Log Shipper with Intune

Perch Log Shipper with Intune

Recently I covered how to install perch using PowerShell. Today we are going to Install Perch Log Shipper with Intune. This is very useful for tools like continuum where there is very few software deployment tools built-in. Intune is a powerful tool that you can use to deploy software for a client. Today we are going to be looking at how to deploy Perch through intune.

The first thing we need is a fresh perch installer. You can acquire one here. [link]. Once you have the installer, you will need to download the Microsoft Win32 Content Prep Tool [Link]. Let’s setup our directory like so. Top Folder = Intune. Two subfolders, one called Files and the other called intunewin. Extract the exe from the Microsoft win32 content prep tool to the intune folder. Copy the perch installer to the files folder. Now we have a setup that is easy to remember.

By default, you can not deploy EXE programs via intune. You must convert them to the win32 application or a .intunewin file. The tool you just downloaded can do just that. The Tools name is IntuneWinAppUtil.exe.

IntuneWinAppUtil.exe

Start a command prompt and navigate to your intune folder using the CD command. Run the intunewinapputil.exe /? command to view the help selection. Notice we are going to be using the -c -s and -o commands. Here is the following command you will use to convert the perch installer into a intunewin application.

IntuneWinAppUtil.exe -c c:\Intune\Files -s perch-log-shipper-latest.exe -o c:\Intune\intunewin

Now we have a perch installer for Intune. Lets move to intune and take a look.

Intune Apps

It’s time to crack open the Intune process. Log in to https://endpoint.microsoft.com/ with an account with intune rights.

Once you have logged into the endpoint management system. Click the Apps on the left-hand side of the screen.

Since we are deploying perch to windows machines, under by platform, click the windows icon.

Now we are going to click the add button on the right-hand side of the screen. This will bring up the add dialog box. We are deploying out the final option. Click the Windows App (Win32) option.

Upload the Package

Afterward, we are brought to the app page. Here you select the app package file and click the blue button on the right-hand side of the screen. This is where we go to the file we created in the previous steps. We upload the file here. Once it uploads it will populate the information like name and other items. Click ok to move to the app information page.

App Information

Here we can change the name. Add a unique, html, description. Update the publisher, the application version and more. The category we are going to select is computer management. The show this as a featured app in the company portal. You want to check that one. This allows people to download this version of perch. If you want to feel in any of the other information you are welcome to. Once you have the required information, click next to go to the Program page. Where we determine how to install this application.

Program Information

On this page we want to show the install and uninstall command. This is where research comes into play. If you don’t know the silent install command of your program then that’s a problem. If you don’t know how your program responds to installs and the error codes or success codes it produces. that’s also a problem. You will need to know these things for other applications. Thankfully perch follows the basic ones. Here is the installer command:

 perch-log-shipper-latest.exe /q OUTPUT="TOKEN" Value="YourSiteToken"

The uninstall command is as follows:

 perch-log-shipper-latest.exe /uninstall

Once you have the installer and uninstaller in place, click the next button to go to the requirement page.

Requirements

On this page, we can scan the system to make sure we meet the requirements. So if you know this is a heavy application, you can say to have at least 8GB of ram. You can even have PowerShell scripts that can trigger. A good example would be a user. If user Bob is on this PC don’t install. The required items are the OS Arch and the minimum os. Which is going to be windows 10 1607 as that is intunes min. Don’t get this confused with the next item. These are the requirements. Once you have added what you want, click next.

Dependencies

On this page, we are going to select any dependencies that the application may need. For example, let’s say your application needs 7-zip. Set up an install for 7 zip and make it a dependency and have it install the dependency. One hack I found is if you know the app is going to break other apps while installing as the ITS Platform does, then you can set the other applications as dependants and install them. Thankfully perch does not have any additional dependants. So, when it does it’s taxes, life is easier. (American joke).

Detection Rules

Detection is very important. if the rule doesn’t exist, then intune has no idea if it was installed. If the detection policy is incorrect, the same issue. It’s very wise to know what you are looking for. In this case perch always installs on c:\program files\perch. So we will select the manual to configure detection rule. Then select add. We will select a file from the drop-down list and enter the folder path of c:\program files and the folder name perch. Then click folder or existing file. That’s your detection policy.

Group Assignments

In like fashion, The next window of importance is the Assign. If you want the app to deploy with autopilot, you must select the app as required, or be tied into another application install dependency. Here we are adding a group of computers. This is very common. The other options are available for enrolled devices. If the computer has the company portal, they can download it without needing admin rights. The final option is to uninstall which would uninstall from the select computers.

Finally, the last page is to review all the settings. Once you click save the file will upload and it might take some time. The bigger the file the longer it will take. This is how you Install Perch Log Shipper with Intune.

Conclusion

Hopefully this guide helped you through the process of setting up an Install Perch Log Shipper with Intune

Install Perch with PowerShell

Install Perch with PowerShell

Perch is an event log tracker that can catch a lot of useful information. I like perch because it captures failed login information. It’s easy to sort and exportable. This is why many companies use the software. There are some gatchya’s with perch installs though. If you are installing it on a server, some services don’t auto start. Installing it from PowerShell also has a gatchya. This post is about how to install perch via PowerShell scripts. This method uses your token for the client’s site. Let’s Install Perch with PowerShell.

The Script

if (!(Test-Path "$($env:SystemDrive)\Temp")) { New-Item -Path "$env:SystemDrive\" -Name Temp -ItemType Directory }
$PerchURL = "https://cdn.perchsecurity.com/downloads/perch-log-shipper-latest.exe"
$PerchFullFileName = "$($env:SystemDrive)\Temp\perch-log-shipper-latest.exe"
Invoke-WebRequest -Uri $PerchURL -Outfile $PerchFullFileName -UseBasicParsing
start-process -FilePath "$PerchFullFileName" -ArgumentList @("/qn", 'OUTPUT="TOKEN"', 'VALUE="Your Token"') 
$Timeout = 0
do {
    $Timeout = $Timeout + 5
    start-sleep -Seconds 5
} Until (((Get-service -Name "Perch*" -ErrorAction SilentlyContinue).count -ge 2) -or ($Timeout -ge 500))

if ((Get-service -Name "Perch*" -ErrorAction SilentlyContinue).count -ge 2) {
    Get-Service -name perch-auditbeat | Set-Service -StartupType Automatic
    Get-Service -name perch-auditbeat | Start-Service
} else {
    Write-Error "Services did not install."
}

The Breakdown

Let’s break down the script. The first thing we do is create the download repo. I personally like to use the C:\Temp. Not all machines have a c:\. This is why I use the variable $Env:SystemDrive. If the OS drive is d, the code will add a D:\Temp. and so on and so forth.

The next line is the URL for the latest and greatest Perch installer. This keeps your download up to date. With that stated, this also means if they change something you will need to be able to catch that change. So you will need to stay up to date with their deployment. A good way to do that is by registering with their updates emails. I like to have a ticket every 3 to 6 months, randomly placed, to review deployments like this one. This is just a good habit.

Now we have the url, we want to create a path. Using the Env:SystemDrive we place the perch-log-shipper-latest.exe into the temp folder, our local repo. This will make the next command easier.

Now we invoke-webrequest this bad boy. Just like curl and wget, we are able to download the file. Using the PerchURL in the URI position and then the outfile will be the perchfullfilename. Of course, we use the basic parsing just in case it’s an older version of PowerShell. At the time of this writing, the default PowerShell is 5.1 on windows 10.

Now we start the installation. We start-process. Using the PerchFullFileName as the target. See, using parameters helps. Our argument list is /qn for quiet. The output is going to be the token. Finally our token value, value is our token from perch’s site.

Getting the token

To get the token, you will need to log into your perch system. At the top, select the company you wish to get the token from.

Next, you will need to click on the settings icon on the bottom left-hand corner. Then click the Network icon.

Normally we want to add a -wait flag to the end of the installer. Things like google chrome do great with the -wait flag. However, in this case, we don’t want to do that. The reason we create advanced checks is due to the multiple sub-processes inside of the perch install process. The wait flag only captures the first process.

Confirming Install Perch with Powershell

With all that, it’s time to confirm the installation. The most simple way to do this is by watching the services. Perch installs 2 services. It installs perch-auditbeat and perch-winlogbeat. During the confirmation process, we wait. If a timeout occurs, we get the error. If the application installs, we get the results. At this point, we want to start our time-out timer. That’s why we have a $timeout = 0. We then start a do until. Each time the system loops, we wait for 5 seconds. Then we add 5 to the timer. This effectively creates a timer for us. This process is repeated until the conditions are met. The services with the name perch* are greater than or equal to 2, or the time-out reaches 500.

If the services are installed or if the timeout is reached, we moved to the next step. By default, the auditbeat is set to manual. So we check to see if we have the two services. If we do, we then set the perch-auditbeat to automatic and start the service. If not, we throw an error saying the services did not install. This will alert the deployment engineer to dig deeper into this machine. From my experience, it’s because another application is installed.

Don’t forget to take a look at how you can install perch using intune.

Embed Files into Powershell Scripts

Embed Files into Powershell Scripts

Do you have a zip file or an msi file that you need to embed into a powershell script for deployment. This is a quick and simple way to do this. The method is pretty sound and works most of the time. The larger the file, the more troubles the system has converting and converting back, so small files works wonders for this method.

The first thing we are going to do is convert a file into a base 64 string. This is done through the command Get-Content and the system convert method. Powershell 7 recently changed the command for this method and we will cover that first.

Powershell 7 Command

The get content changed the encoding flag to asbytestream flag.

$Content = Get-Content -Path $Path -AsByteStream -raw

This command will read the data as raw byte data which is needed for the System convert method. The Powershell 5 method users Encoding and then you select your type which is byte.

Powershell 5

$Content = Get-Content -Path $Path -Encoding Byte

These commands reads the data as raw information that will be used for the system.convert to base 64 string method.

$base64 = [system.convert]::ToBase64String($content)

Now the Base64 contains something that looks like this:

"//4wADEAMAAwADAAMAAwADAAZAAwADgAYwA5AGQAZABmADAAMQAxADUAZAAxADEAMQA4AGMANwBhADAAMABjADAANABmAGMAMgA5ADcAZQBiADAAMQAwADAAMAAwADAAMABlADYAYQAyADMAOAA4ADIAOQA3ADIAOQBiADIANABhAGEAMAA0ADcAMQBjADEANQBjADcAYwAwAGQANQA4AGYAMAAwADAAMAAwADAAMAAwADAAMgAwADAAMAAwADAAMAAwADAAMAAwADAAMwA2ADYAMAAwADAAMABjADAAMAAwADAAMAAwADAAMQAwADAAMAAwADAAMAAwAGIAMQA5ADcAOAA5AGQAYgBmADkAMAAxADYANgA2ADEANQBlADgAMwAzAGQAOQAxADMANgA0ADEAYwBmAGIANAAwADAAMAAwADAAMAAwADAAMAA0ADgAMAAwADAAMAAwAGEAMAAw==

We take that information and Pipe it into the clip.exe to bring it to our clipboard.

$Base64 | clip.exe

Converting it back

Now we need to convert the string back to a file. To do that we are going to use the System.Convert from base 64 string.

$Object = [System.Convert]::FromBase64String("The crazy text")

Now we have an object of random-looking data like before. We need to write those bytes to a file we do that with the System.IO.File write all bytes method. We will need the outfile location. and the object we created earlier to complete this task.

[system.io.file]::WriteAllBytes($OutFile,$object)

This will create the file you embedded into your powershell script.

Use Case

Encrypted Passwords

Let’s secure a password file and key file inside our embedded script. First, we are going to create the key for out password file.

$key = New-Object byte[] 16
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
$key | Out-File C:\temp\TestPassword.key 

This is the content of our key file:

41
202
16
223
129
18
138
116
106
132
9
217
180
41
226
108

Now we have our key made it’s time to create the password file.

$Password = "lazyAppl351" | ConvertTo-SecureString -AsPlainText -Force 
$Password | ConvertFrom-SecureString -Key $Key | Out-File c:\temp\TestPassword.txt

This is what the Password file looks like on the inside:

76492d1116743f0423413b16050a5345MgB8ADkAMAA1AGYAaABaAC8ASAB3AG8AUQBQAGUAdwBKAHgAbwBJAFIAKwA5AHcAPQA9AHwAZQA2ADQAOQBiADMAMQA2AGEAYwBjADAANAA4AGUANQAxAGMAOAA2ADgAOABkADkAYgBmAGIANgBkAGUAMgAwADQAZQA3AGQAMgA2ADMAMQBiADQANQA4AGIAOAA1ADcAMABlADAAMQBhAGIAYgA4AGIAYQBhADEAOAA4ADMANAA=

Now we will embed these files into our script.

$KeyFile = Get-Content -Path C:\temp\TestPassword.key -Encoding Byte
$base64 = [system.convert]::ToBase64String($Keyfile)
$Base64 | clip.exe

This will convert the key file into a working string that we can convert later. This is what the information looks like:

NDENCjIwMg0KMTYNCjIyMw0KMTI5DQoxOA0KMTM4DQoxMTYNCjEwNg0KMTMyDQo5DQoyMTcNCjE4MA0KNDENCjIyNg0KMTA4DQo=

Now we will do the same thing for the password file.

$KeyFile = Get-Content -Path C:\temp\TestPassword.txt -Encoding Byte
$base64 = [system.convert]::ToBase64String($Keyfile)
$Base64 | clip.exe

This is what this looks like:

NzY0OTJkMTExNjc0M2YwNDIzNDEzYjE2MDUwYTUzNDVNZ0I4QURrQU1BQTFBR1lBYUFCYUFDOEFTQUIzQUc4QVVRQlFBR1VBZHdCS0FIZ0Fid0JKQUZJQUt3QTVBSGNBUFFBOUFId0FaUUEyQURRQU9RQmlBRE1BTVFBMkFHRUFZd0JqQURBQU5BQTRBR1VBTlFBeEFHTUFPQUEyQURnQU9BQmtBRGtBWWdCbUFHSUFOZ0JrQUdVQU1nQXdBRFFBWlFBM0FHUUFNZ0EyQURNQU1RQmlBRFFBTlFBNEFHSUFPQUExQURjQU1BQmxBREFBTVFCaEFHSUFZZ0E0QUdJQVlRQmhBREVBT0FBNEFETUFOQUE9DQo=

Now we build the script with these two pieces of information. We recreate the files from the script and then pull them in like before. Here is the key code:

$keyBase64 = "NDENCjIwMg0KMTYNCjIyMw0KMTI5DQoxOA0KMTM4DQoxMTYNCjEwNg0KMTMyDQo5DQoyMTcNCjE4MA0KNDENCjIyNg0KMTA4DQo="
$Object = [System.Convert]::FromBase64String($keyBase64)
[system.io.file]::WriteAllBytes('C:\temp\TestPassword.key',$object)

and here is the Password code:

$PassBase64 = "NzY0OTJkMTExNjc0M2YwNDIzNDEzYjE2MDUwYTUzNDVNZ0I4QURrQU1BQTFBR1lBYUFCYUFDOEFTQUIzQUc4QVVRQlFBR1VBZHdCS0FIZ0Fid0JKQUZJQUt3QTVBSGNBUFFBOUFId0FaUUEyQURRQU9RQmlBRE1BTVFBMkFHRUFZd0JqQURBQU5BQTRBR1VBTlFBeEFHTUFPQUEyQURnQU9BQmtBRGtBWWdCbUFHSUFOZ0JrQUdVQU1nQXdBRFFBWlFBM0FHUUFNZ0EyQURNQU1RQmlBRFFBTlFBNEFHSUFPQUExQURjQU1BQmxBREFBTVFCaEFHSUFZZ0E0QUdJQVlRQmhBREVBT0FBNEFETUFOQUE9DQo="
$Object = [System.Convert]::FromBase64String($PassBase64)
[system.io.file]::WriteAllBytes('C:\temp\TestPassword.txt',$object)

Now we have both files needed to receive our password, let’s convert that password using the key from before. We get the content of the .key file with get-content. Then we use it when we convert to secure string the password file. Pushing all that information into a new credential object for later use in something like a nextcloud download. Then we remove the files as we don’t want that password getting out there.

$Username = "BobTheUser"
$key = Get-Content 'C:\temp\TestPassword.Key'
$MyCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content 'c:\temp\TestPassword.txt' | ConvertTo-SecureString -Key $key)
remove-item c:\temp\TestPassword.txt
remove-item c:\temp\TestPassword.key

MSI file

Let’s say we need to embed an MSI file. For example, we have a custom Open DNS MSI that will auto setup the Umbrella client on an end user’s computer. The first thing we want to do is convert that msi file to the base 64 string like above.

$content = Get-Content -Path C:\Temp\CustomOpenDNS.msi -Encoding Bye
[system.Convert]::ToBase64String($Content) | clip.exe

Here we are using the powershell 5 code to convert the msi into a string and pushing it out to our clipboard. Now we need to place that information into the script. This is what the script would look like:

$Base64 = "PCFET0NUWVBFIGh0bWw+CjxodG1sIGNsYXNzPSJuZy1jc3AiIGRhdGEtcGxhY2Vob2xkZXItZm9jdXM9ImZhbHNlIiBsYW5nPSJlbiIgZGF0YS1sb2NhbGU9ImVuIiA+Cgk8aGVhZAogZGF0YS1yZXF1ZXN0dG9rZW49IkZPVkorSVltUkJucnoyNU4zZDZyclhIM0Y5c3NzK3BSOS9HaVN2WFBMZHc9OldLQjd0OHdRSzE2TWx5VVBsNy9ZM0R2T1dMWjk5dHBpcjRlYkxzS3RXTFU9Ij4KCQk8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CgkJPHRpdGxlPgoJCVJhbmRvbW5lc3MJCTwvdGl0bGU+CgkJPG1ldGEgaHR0cC1lcXVpdj0iWC1VQS1Db21wYXRpYmxlIiBjb250ZW50PSJJRT1lZGdlIj4KCQk8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCwgbWluaW11bS1zY2FsZT0xLjAiPgoJCQkJPG1ldGEgbmFtZT0iYXBwbGUtaXR1bmVzLWFwcCIgY29udGVudD0iYXBwLWlkPTExMjU0MjAxMDIiPgoJCQkJPG1ldGEgbmFtZT0idGhlbWUtY29sb3IiIGNvbnRlbnQ9IiMwMDIxMzMiPgoJCTxsaW5rIHJlbD0iaWNvbiIgaHJlZj0iL2luZGV4LnBocC9hcHBzL3RoZW1pbmcvZmF2aWNvbj92PTMiPgoJCTxsaW5rIHJlbD0iYXBwbGUtdG91Y2gtaWNvbiIgaHJlZj0iL2luZGV4LnBocC9hcHBzL3RoZW1pbmcvaWNvbj92PTMiPgoJCTxsaW5rIHJlbD0ibWFzay1pY29uIiBzaXplcz0iYW55IiBocmVmPSIvY29yZS9pbWcvZmF2aWNvbi1tYXNrLnN2ZyIgY29sb3I9IiMwMDIxMzMiPgoJCTxsaW5rIHJlbD0ibWFuaWZlc3QiIGhyZWY9Ii9pbmRleC5waHAvYXBwcy90aGVtaW5nL21hbmlmZXN0P3Y9MyI+CgkJPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSIvaW5kZXgucGhwL2Nzcy9jb3JlLzEzM2EtZDJjNi1zZXJ2ZXIuY3NzP3Y9YmUwYjQ2NTY1ZjcwNWM3YmYzNzQ0OTIxMmRmYWQxNzYtYjA3MTM1Y2MtMyI+CjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iL2luZGV4LnBocC9jc3MvY29yZS8xMzNhLWQyYzYtY3NzLXZhcmlhYmxlcy5jc3M/dj1iZTBiNDY1NjVmNzA1YzdiZjM3NDQ5MjEyZGZhZDE3Ni1iMDcxMzVjYy0zIj4KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSIvYXBwcy9maWxlc19yaWdodGNsaWNrL2Nzcy9hcHAuY3NzP3Y9NDdjZDc2ZTQtMyI+CjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iL2luZGV4LnBocC9jc3MvdGV4dC8wNzBhLWQyYzYtaWNvbnMuY3NzP3Y9YmUwYjQ2NTY1ZjcwNWM3YmYzNzQ0OTIxMmRmYWQxNzYtYjA3MTM1Y2MtMyI+CjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iL2NvcmUvY3NzL2d1ZXN0LmNzcz92PWIwNzEzNWNjLTMiPgo8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii9jb3JlL2Nzcy9wdWJsaWNzaGFyZWF1dGguY3NzP3Y9YjA3MTM1Y2MtMyI+CjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iL2NvcmUvY3NzL2d1ZXN0LmNzcz92PWIwNzEzNWNjLTMiPgoJCTxzY3JpcHQgbm9uY2U9IlJrOVdTaXRKV1cxU1FtNXllakkxVGpOa05uSnlXRWd6UmpsemMzTXJjRkk1TDBkcFUzWllVRXhrZHowNlYwdENOM1E0ZDFGTE1UWk5iSGxWVUd3M0wxa3pSSFpQVjB4YU9UbDBjR2x5TkdWaVRITkxkRmRNVlQwPSIgZGVmZXIgc3JjPSIvaW5kZXgucGhwL2NvcmUvanMvb2MuanM/dj1iMDcxMzVjYyI+PC9zY3JpcHQ+CjxzY3JpcHQgbm9uY2U9IlJrOVdTaXRKV1cxU1FtNXllakkxVGpOa05uSnlXRWd6UmpsemMzTXJjRkk1TDBkcFUzWllVRXhrZHowNlYwdENOM1E0ZDFGTE1UWk5iSGxWVUd3M0wxa3pSSFpQVjB4YU9UbDBjR2x5TkdWaVRITkxkRmRNVlQwPSIgZGVmZXIgc3JjPSIvY29yZS9qcy9kaXN0L21haW4uanM/dj1iMDcxMzVjYy0zIj48L3NjcmlwdD4KPHNjcmlwdCBub25jZT0iUms5V1NpdEpXVzFTUW01eWVqSTFUak5rTm5KeVdFZ3pSamx6YzNNcmNGSTVMMGRwVTNaWVVFeGtkejA2VjB0Q04zUTRkMUZMTVRaTmJIbFZVR3czTDFrelJIWlBWMHhhT1RsMGNHbHlOR1ZpVEhOTGRGZE1WVDA9IiBkZWZlciBzcmM9Ii9jb3JlL2pzL2Rpc3QvZmlsZXNfZmlsZWluZm8uanM/dj1iMDcxMzVjYy0zIj48L3NjcmlwdD4KPHNjcmlwdCBub25jZT0iUms5V1NpdEpXVzFTUW01eWVqSTFUak5rTm5KeVdFZ3pSamx6YzNNcmNGSTVMMGRwVTNaWVVFeGtkejA2VjB0Q04zUTRkMUZMTVRaTmJIbFZVR3czTDFrelJIWlBWMHhhT1RsMGNHbHlOR1ZpVEhOTGRGZE1WVDA9IiBkZWZlciBzcmM9Ii9jb3JlL2pzL2Rpc3QvZmlsZXNfY2xpZW50LmpzP3Y9YjA3MTM1Y2MtMyI+PC9zY3JpcHQ+CjxzY3JpcHQgbm9uY2U9IlJrOVdTaXRKV1cxU1FtNXllakkxVGpOa05uSnlXRWd6UmpsemMzTXJjRkk1TDBkcFUzWllVRXhrZHowNlYwdENOM1E0ZDFGTE1UWk5iSGxWVUd3M0wxa3pSSFpQVjB4YU9UbDBjR2x5TkdWaVRITkxkRmRNVlQwPSIgZGVmZXIgc3JjPSIvaW5kZXgucGhwL2pzL2NvcmUvbWVyZ2VkLXRlbXBsYXRlLXByZXBlbmQuanM/dj1iMDcxMzVjYy0zIj48L3NjcmlwdD4KPHNjcmlwdCBub25jZT0iUms5V1NpdEpXVzFTUW01eWVqSTFUak5rTm5KeVdFZ3pSamx6YzNNcmNGSTVMMGRwVTNaWVVFeGtkejA2VjB0Q04zUTRkMUZMTVRaTmJIbFZVR3czTDFrelJIWlBWMHhhT1RsMGNHbHlOR1ZpVEhOTGRGZE1WVDA9IiBkZWZlciBzcmM9Ii9jb3JlL2pzL2JhY2tncm91bmRqb2JzLmpzP3Y9YjA3MTM1Y2MtMyI+PC9zY3JpcHQ+CjxzY3JpcHQgbm9uY2U9IlJrOVdTaXRKV1cxU1FtNXllakkxVGpOa05uSnlXRWd6UmpsemMzTXJjRkk1TDBkcFUzWllVRXhrZHowNlYwdENOM1E0ZDFGTE1UWk5iSGxWVUd3M0wxa3pSSFpQVjB4YU9UbDBjR2x5TkdWaVRITkxkRmRNVlQwPSIgZGVmZXIgc3JjPSIvYXBwcy9maWxlc19zaGFyaW5nL2pzL2Rpc3QvbWFpbi5qcz92PWIwNzEzNWNjLTMiPjwvc2NyaXB0Pgo8c2NyaXB0IG5vbmNlPSJSazlXU2l0SldXMVNRbTV5ZWpJMVRqTmtObkp5V0VnelJqbHpjM01yY0ZJNUwwZHBVM1pZVUV4a2R6MDZWMHRDTjNRNGQxRkxNVFpOYkhsVlVHdzNMMWt6UkhaUFYweGFPVGwwY0dseU5HVmlUSE5MZEZkTVZUMD0iIGRlZmVyIHNyYz0iL2FwcHMvZXB1YnJlYWRlci9qcy9wbHVnaW4uanM/dj1iMDcxMzVjYy0zIj48L3NjcmlwdD4KPHNjcmlwdCBub25jZT0iUms5V1NpdEpXVzFTUW01eWVqSTFUak5rTm5KeVdFZ3pSamx6YzNNcmNGSTVMMGRwVTNaWVVFeGtkejA2VjB0Q04zUTRkMUZMTVRaTmJIbFZVR3czTDFrelJIWlBWMHhhT1RsMGNHbHlOR1ZpVEhOTGRGZE1WVDA9IiBkZWZlciBzcmM9Ii9hcHBzL2ZpbGVzX3ZpZGVvcGxheWVyL2pzL21haW4uanM/dj1iMDcxMzVjYy0zIj48L3NjcmlwdD4KPHNjcmlwdCBub25jZT0iUms5V1NpdEpXVzFTUW01eWVqSTFUak5rTm5KeVdFZ3pSamx6YzNNcmNGSTVMMGRwVTNaWVVFeGtkejA2VjB0Q04zUTRkMUZMTVRaTmJIbFZVR3czTDFrelJIWlBWMHhhT1RsMGNHbHlOR1ZpVEhOTGRGZE1WVDA9IiBkZWZlciBzcmM9Ii9hcHBzL2ZpbGVzX3JpZ2h0Y2xpY2svanMvc2NyaXB0LmpzP3Y9YjA3MTM1Y2MtMyI+PC9zY3JpcHQ+CjxzY3JpcHQgbm9uY2U9IlJrOVdTaXRKV1cxU1FtNXllakkxVGpOa05uSnlXRWd6UmpsemMzTXJjRkk1TDBkcFUzWllVRXhrZHowNlYwdENOM1E0ZDFGTE1UWk5iSGxWVUd3M0wxa3pSSFpQVjB4YU9UbDBjR2x5TkdWaVRITkxkRmRNVlQwPSIgZGVmZXIgc3JjPSIvYXBwcy9maWxlc19yaWdodGNsaWNrL2pzL2ZpbGVzLmpzP3Y9YjA3MTM1Y2MtMyI+PC9zY3JpcHQ+CjxzY3JpcHQgbm9uY2U9IlJrOVdTaXRKV1cxU1FtNXllakkxVGpOa05uSnlXRWd6UmpsemMzTXJjRkk1TDBkcFUzWllVRXhrZHowNlYwdENOM1E0ZDFGTE1UWk5iSGxWVUd3M0wxa3pSSFpQVjB4YU9UbDBjR2x5TkdWaVRITkxkRmRNVlQwPSIgZGVmZXIgc3JjPSIvYXBwcy90ZXh0L2pzL3B1YmxpYy5qcz92PWIwNzEzNWNjLTMiPjwvc2NyaXB0Pgo8c2NyaXB0IG5vbmNlPSJSazlXU2l0SldXMVNRbTV5ZWpJMVRqTmtObkp5V0VnelJqbHpjM01yY0ZJNUwwZHBVM1pZVUV4a2R6MDZWMHRDTjNRNGQxRkxNVFpOYkhsVlVHdzNMMWt6UkhaUFYweGFPVGwwY0dseU5HVmlUSE5MZEZkTVZUMD0iIGRlZmVyIHNyYz0iL2FwcHMvdGhlbWluZy9qcy90aGVtaW5nLmpzP3Y9YjA3MTM1Y2MtMyI+PC9zY3JpcHQ+CjxzY3JpcHQgbm9uY2U9IlJrOVdTaXRKV1cxU1FtNXllakkxVGpOa05uSnlXRWd6UmpsemMzTXJjRkk1TDBkcFUzWllVRXhrZHowNlYwdENOM1E0ZDFGTE1UWk5iSGxWVUd3M0wxa3pSSFpQVjB4YU9UbDBjR2x5TkdWaVRITkxkRmRNVlQwPSIgZGVmZXIgc3JjPSIvY29yZS9qcy9wdWJsaWNzaGFyZWF1dGguanM/dj1iMDcxMzVjYy0zIj48L3NjcmlwdD4KCQk8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii9pbmRleC5waHAvY3NzL2ljb25zL2ljb25zLXZhcnMuY3NzP3Y9MTYyOTE3OTQyOSIvPjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgbWVkaWE9IihwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykiIGhyZWY9Ii9pbmRleC5waHAvYXBwcy9hY2Nlc3NpYmlsaXR5L2Nzcy91c2VyLWE4MmZkOTVkYjEwZmYyNWRmYWQzOWYwNzM3MmViZTM3Ii8+PGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSIvaW5kZXgucGhwL2FwcHMvdGhlbWluZy9zdHlsZXM/dj0zIi8+PG1ldGEgbmFtZT0icm9ib3RzIiBjb250ZW50PSJub2luZGV4LCBub2ZvbGxvdyIvPgk8L2hlYWQ+Cgk8Ym9keSBpZD0iYm9keS1sb2dpbiI+CgkJPG5vc2NyaXB0PgoJPGRpdiBpZD0ibm9qYXZhc2NyaXB0Ij4KCQk8ZGl2PgoJCQlUaGlzIGFwcGxpY2F0aW9uIHJlcXVpcmVzIEphdmFTY3JpcHQgZm9yIGNvcnJlY3Qgb3BlcmF0aW9uLiBQbGVhc2UgPGEgaHJlZj0iaHR0cHM6Ly93d3cuZW5hYmxlLWphdmFzY3JpcHQuY29tLyIgdGFyZ2V0PSJfYmxhbmsiIHJlbD0ibm9yZWZlcnJlciBub29wZW5lciI+ZW5hYmxlIEphdmFTY3JpcHQ8L2E+IGFuZCByZWxvYWQgdGhlIHBhZ2UuCQk8L2Rpdj4KCTwvZGl2Pgo8L25vc2NyaXB0PgoJCQkJCTxpbnB1dCB0eXBlPSJoaWRkZW4iIGlkPSJpbml0aWFsLXN0YXRlLXRleHQtd29ya3NwYWNlX2F2YWlsYWJsZSIgdmFsdWU9ImRISjFaUT09Ij4KCQkJCQk8aW5wdXQgdHlwZT0iaGlkZGVuIiBpZD0iaW5pdGlhbC1zdGF0ZS1jb3JlLWNvbmZpZyIgdmFsdWU9ImV5SnpaWE56YVc5dVgyeHBabVYwYVcxbElqb3hORFF3TENKelpYTnphVzl1WDJ0bFpYQmhiR2wyWlNJNmRISjFaU3dpWVhWMGIxOXNiMmR2ZFhRaU9tWmhiSE5sTENKMlpYSnphVzl1SWpvaU1qRXVNQzR4TGpFaUxDSjJaWEp6YVc5dWMzUnlhVzVuSWpvaU1qRXVNQzR4SWl3aVpXNWhZbXhsWDJGMllYUmhjbk1pT25SeWRXVXNJbXh2YzNSZmNHRnpjM2R2Y21SZmJHbHVheUk2Ym5Wc2JDd2liVzlrVW1WM2NtbDBaVmR2Y210cGJtY2lPbVpoYkhObExDSnphR0Z5YVc1bkxtMWhlRUYxZEc5amIyMXdiR1YwWlZKbGMzVnNkSE1pT2pJMUxDSnphR0Z5YVc1bkxtMXBibE5sWVhKamFGTjBjbWx1WjB4bGJtZDBhQ0k2TUN3aVlteGhZMnRzYVhOMFgyWnBiR1Z6WDNKbFoyVjRJam9pWEZ3dUtIQmhjblI4Wm1sc1pYQmhjblFwSkNKOSI+CgkJCQkJPGlucHV0IHR5cGU9ImhpZGRlbiIgaWQ9ImluaXRpYWwtc3RhdGUtY29yZS1jYXBhYmlsaXRpZXMiIHZhbHVlPSJleUpqYjNKbElqcDdJbkJ2Ykd4cGJuUmxjblpoYkNJNk5qQXNJbmRsWW1SaGRpMXliMjkwSWpvaWNtVnRiM1JsTG5Cb2NGd3ZkMlZpWkdGMkluMHNJbUp5ZFhSbFptOXlZMlVpT25zaVpHVnNZWGtpT2pCOUxDSm1hV3hsY3lJNmV5SmlhV2RtYVd4bFkyaDFibXRwYm1jaU9uUnlkV1VzSW1Kc1lXTnJiR2x6ZEdWa1gyWnBiR1Z6SWpwYklpNW9kR0ZqWTJWemN5SmRMQ0prYVhKbFkzUkZaR2wwYVc1bklqcDdJblZ5YkNJNkltaDBkSEJ6T2x3dlhDOXlibVJoWkdoa2JXRnVMbU52YlZ3dmIyTnpYQzkyTWk1d2FIQmNMMkZ3Y0hOY0wyWnBiR1Z6WEM5aGNHbGNMM1l4WEM5a2FYSmxZM1JGWkdsMGFXNW5JaXdpWlhSaFp5STZJall5TWpaaVlUZzNNek0zTTJZMVpUY3pZVE5sWmpVd05ERXdOelV5TTJZM0luMHNJbU52YlcxbGJuUnpJanAwY25WbExDSjFibVJsYkdWMFpTSTZkSEoxWlN3aWRtVnljMmx2Ym1sdVp5STZkSEoxWlgwc0ltRmpkR2wyYVhSNUlqcDdJbUZ3YVhZeUlqcGJJbVpwYkhSbGNuTWlMQ0ptYVd4MFpYSnpMV0Z3YVNJc0luQnlaWFpwWlhkeklpd2ljbWxqYUMxemRISnBibWR6SWwxOUxDSnZZMjBpT25zaVpXNWhZbXhsWkNJNmRISjFaU3dpWVhCcFZtVnljMmx2YmlJNklqRXVNQzF3Y205d2IzTmhiREVpTENKbGJtUlFiMmx1ZENJNkltaDBkSEJ6T2x3dlhDOXlibVJoWkdoa2JXRnVMbU52YlZ3dmFXNWtaWGd1Y0dod1hDOXZZMjBpTENKeVpYTnZkWEpqWlZSNWNHVnpJanBiZXlKdVlXMWxJam9pWm1sc1pTSXNJbk5vWVhKbFZIbHdaWE1pT2xzaWRYTmxjaUlzSW1keWIzVndJbDBzSW5CeWIzUnZZMjlzY3lJNmV5SjNaV0prWVhZaU9pSmNMM0IxWW14cFl5NXdhSEJjTDNkbFltUmhkbHd2SW4xOVhYMHNJbVJoZGlJNmV5SmphSFZ1YTJsdVp5STZJakV1TUNKOUxDSm1kV3hzZEdWNGRITmxZWEpqYUNJNmV5SnlaVzF2ZEdVaU9uUnlkV1VzSW5CeWIzWnBaR1Z5Y3lJNlcxMTlMQ0p1YjNScFptbGpZWFJwYjI1eklqcDdJbTlqY3kxbGJtUndiMmx1ZEhNaU9sc2liR2x6ZENJc0ltZGxkQ0lzSW1SbGJHVjBaU0lzSW1SbGJHVjBaUzFoYkd3aUxDSnBZMjl1Y3lJc0luSnBZMmd0YzNSeWFXNW5jeUlzSW1GamRHbHZiaTEzWldJaUxDSjFjMlZ5TFhOMFlYUjFjeUpkTENKd2RYTm9JanBiSW1SbGRtbGpaWE1pTENKdlltcGxZM1F0WkdGMFlTSXNJbVJsYkdWMFpTSmRMQ0poWkcxcGJpMXViM1JwWm1sallYUnBiMjV6SWpwYkltOWpjeUlzSW1Oc2FTSmRmU3dpY0dGemMzZHZjbVJmY0c5c2FXTjVJanA3SW0xcGJreGxibWQwYUNJNk9Dd2laVzVtYjNKalpVNXZia052YlcxdmJsQmhjM04zYjNKa0lqcDBjblZsTENKbGJtWnZjbU5sVG5WdFpYSnBZME5vWVhKaFkzUmxjbk1pT21aaGJITmxMQ0psYm1admNtTmxVM0JsWTJsaGJFTm9ZWEpoWTNSbGNuTWlPbVpoYkhObExDSmxibVp2Y21ObFZYQndaWEpNYjNkbGNrTmhjMlVpT21aaGJITmxMQ0poY0draU9uc2laMlZ1WlhKaGRHVWlPaUpvZEhSd2N6cGNMMXd2Y201a1lXUm9aRzFoYmk1amIyMWNMMjlqYzF3dmRqSXVjR2h3WEM5aGNIQnpYQzl3WVhOemQyOXlaRjl3YjJ4cFkzbGNMMkZ3YVZ3dmRqRmNMMmRsYm1WeVlYUmxJaXdpZG1Gc2FXUmhkR1VpT2lKb2RIUndjenBjTDF3dmNtNWtZV1JvWkcxaGJpNWpiMjFjTDI5amMxd3Zkakl1Y0dod1hDOWhjSEJ6WEM5d1lYTnpkMjl5WkY5d2IyeHBZM2xjTDJGd2FWd3ZkakZjTDNaaGJHbGtZWFJsSW4xOUxDSndjbTkyYVhOcGIyNXBibWRmWVhCcElqcDdJblpsY25OcGIyNGlPaUl4TGpFeExqQWlMQ0pCWTJOdmRXNTBVSEp2Y0dWeWRIbFRZMjl3WlhOV1pYSnphVzl1SWpveUxDSkJZMk52ZFc1MFVISnZjR1Z5ZEhsVFkyOXdaWE5HWldSbGNtRjBhVzl1Ulc1aFlteGxaQ0k2ZEhKMVpYMHNJbVpwYkdWelgzTm9ZWEpwYm1jaU9uc2ljMmhoY21WaWVXMWhhV3dpT25zaVpXNWhZbXhsWkNJNmRISjFaU3dpZFhCc2IyRmtYMlpwYkdWelgyUnliM0FpT25zaVpXNWhZbXhsWkNJNmRISjFaWDBzSW5CaGMzTjNiM0prSWpwN0ltVnVZV0pzWldRaU9uUnlkV1VzSW1WdVptOXlZMlZrSWpwbVlXeHpaWDBzSW1WNGNHbHlaVjlrWVhSbElqcDdJbVZ1WVdKc1pXUWlPblJ5ZFdWOWZTd2lZWEJwWDJWdVlXSnNaV1FpT25SeWRXVXNJbkIxWW14cFl5STZleUpsYm1GaWJHVmtJanAwY25WbExDSndZWE56ZDI5eVpDSTZleUpsYm1admNtTmxaQ0k2Wm1Gc2MyVXNJbUZ6YTBadmNrOXdkR2x2Ym1Gc1VHRnpjM2R2Y21RaU9tWmhiSE5sZlN3aVpYaHdhWEpsWDJSaGRHVWlPbnNpWlc1aFlteGxaQ0k2Wm1Gc2MyVjlMQ0p0ZFd4MGFYQnNaVjlzYVc1cmN5STZkSEoxWlN3aVpYaHdhWEpsWDJSaGRHVmZhVzUwWlhKdVlXd2lPbnNpWlc1aFlteGxaQ0k2Wm1Gc2MyVjlMQ0p6Wlc1a1gyMWhhV3dpT21aaGJITmxMQ0oxY0d4dllXUWlPblJ5ZFdVc0luVndiRzloWkY5bWFXeGxjMTlrY205d0lqcDBjblZsZlN3aWNtVnphR0Z5YVc1bklqcDBjblZsTENKMWMyVnlJanA3SW5ObGJtUmZiV0ZwYkNJNlptRnNjMlVzSW1WNGNHbHlaVjlrWVhSbElqcDdJbVZ1WVdKc1pXUWlPblJ5ZFdWOWZTd2laM0p2ZFhCZmMyaGhjbWx1WnlJNmRISjFaU3dpWjNKdmRYQWlPbnNpWlc1aFlteGxaQ0k2ZEhKMVpTd2laWGh3YVhKbFgyUmhkR1VpT25zaVpXNWhZbXhsWkNJNmRISjFaWDE5TENKa1pXWmhkV3gwWDNCbGNtMXBjM05wYjI1eklqb3pNU3dpWm1Wa1pYSmhkR2x2YmlJNmV5SnZkWFJuYjJsdVp5STZkSEoxWlN3aWFXNWpiMjFwYm1jaU9uUnlkV1VzSW1WNGNHbHlaVjlrWVhSbElqcDdJbVZ1WVdKc1pXUWlPblJ5ZFdWOWZTd2ljMmhoY21WbElqcDdJbkYxWlhKNVgyeHZiMnQxY0Y5a1pXWmhkV3gwSWpwbVlXeHpaU3dpWVd4M1lYbHpYM05vYjNkZmRXNXBjWFZsSWpwMGNuVmxmWDBzSW5Sb1pXMXBibWNpT25zaWJtRnRaU0k2SWxKaGJtUnZiVzVsYzNNaUxDSjFjbXdpT2lKb2RIUndjenBjTDF3dmJtVjRkR05zYjNWa0xtTnZiU0lzSW5Oc2IyZGhiaUk2SWtKbGFHOXNaQ0JYYjNKc1pDQnZaaUIzWlhRZ2MyOWphM01pTENKamIyeHZjaUk2SWlNd01ESXhNek1pTENKamIyeHZjaTEwWlhoMElqb2lJMlptWm1abVppSXNJbU52Ykc5eUxXVnNaVzFsYm5RaU9pSWpNREF5TVRNeklpd2lZMjlzYjNJdFpXeGxiV1Z1ZEMxaWNtbG5hSFFpT2lJak1EQXlNVE16SWl3aVkyOXNiM0l0Wld4bGJXVnVkQzFrWVhKcklqb2lJelUxTlRVMU5TSXNJbXh2WjI4aU9pSm9kSFJ3Y3pwY0wxd3ZjbTVrWVdSb1pHMWhiaTVqYjIxY0wyTnZjbVZjTDJsdFoxd3ZiRzluYjF3dmJHOW5ieTV6ZG1jL2RqMHpJaXdpWW1GamEyZHliM1Z1WkNJNklpTXdNREl4TXpNaUxDSmlZV05yWjNKdmRXNWtMWEJzWVdsdUlqcDBjblZsTENKaVlXTnJaM0p2ZFc1a0xXUmxabUYxYkhRaU9uUnlkV1VzSW14dloyOW9aV0ZrWlhJaU9pSm9kSFJ3Y3pwY0wxd3ZjbTVrWVdSb1pHMWhiaTVqYjIxY0wyTnZjbVZjTDJsdFoxd3ZiRzluYjF3dmJHOW5ieTV6ZG1jL2RqMHpJaXdpWm1GMmFXTnZiaUk2SW1oMGRIQnpPbHd2WEM5eWJtUmhaR2hrYldGdUxtTnZiVnd2WTI5eVpWd3ZhVzFuWEM5c2IyZHZYQzlzYjJkdkxuTjJaejkyUFRNaWZTd2lkWE5sY2w5emRHRjBkWE1pT25zaVpXNWhZbXhsWkNJNmRISjFaU3dpYzNWd2NHOXlkSE5mWlcxdmFta2lPblJ5ZFdWOUxDSjNaV0YwYUdWeVgzTjBZWFIxY3lJNmV5SmxibUZpYkdWa0lqcDBjblZsZlgwPSI+CgkJCQkJPGlucHV0IHR5cGU9ImhpZGRlbiIgaWQ9ImluaXRpYWwtc3RhdGUtdGhlbWluZy1kYXRhIiB2YWx1ZT0iZXlKdVlXMWxJam9pVW1GdVpHOXRibVZ6Y3lJc0luVnliQ0k2SW1oMGRIQnpPbHd2WEM5dVpYaDBZMnh2ZFdRdVkyOXRJaXdpYzJ4dloyRnVJam9pUW1Wb2IyeGtJRmR2Y214a0lHOW1JSGRsZENCemIyTnJjeUlzSW1OdmJHOXlJam9pSXpBd01qRXpNeUlzSW1sdGNISnBiblJWY213aU9pSWlMQ0p3Y21sMllXTjVWWEpzSWpvaUlpd2lhVzUyWlhKMFpXUWlPbVpoYkhObExDSmpZV05vWlVKMWMzUmxjaUk2SWpNaWZRPT0iPgoJCQkJCTxpbnB1dCB0eXBlPSJoaWRkZW4iIGlkPSJpbml0aWFsLXN0YXRlLWFjY2Vzc2liaWxpdHktZGF0YSIgdmFsdWU9ImV5SjBhR1Z0WlNJNlptRnNjMlVzSW1ocFoyaGpiMjUwY21GemRDSTZabUZzYzJWOSI+CgkJCQk8ZGl2IGNsYXNzPSJ3cmFwcGVyIj4KCQkJPGRpdiBjbGFzcz0idi1hbGlnbiI+CgkJCQkJCQkJCTxoZWFkZXIgcm9sZT0iYmFubmVyIj4KCQkJCQkJPGRpdiBpZD0iaGVhZGVyIj4KCQkJCQkJCTxkaXYgY2xhc3M9ImxvZ28iPgoJCQkJCQkJCTxoMSBjbGFzcz0iaGlkZGVuLXZpc3VhbGx5Ij4KCQkJCQkJCQkJUmFuZG9tbmVzcwkJCQkJCQkJPC9oMT4KCQkJCQkJCQkJCQkJCQkJPC9kaXY+CgkJCQkJCTwvZGl2PgoJCQkJCTwvaGVhZGVyPgoJCQkJCQkJCTxtYWluPgoJCQkJCTxmb3JtIG1ldGhvZD0icG9zdCI+Cgk8ZmllbGRzZXQgY2xhc3M9Indhcm5pbmciPgoJCQkJCTxkaXYgY2xhc3M9Indhcm5pbmctaW5mbyI+VGhpcyBzaGFyZSBpcyBwYXNzd29yZC1wcm90ZWN0ZWQ8L2Rpdj4KCQkJCQkJPHA+CgkJCTxsYWJlbCBmb3I9InBhc3N3b3JkIiBjbGFzcz0iaW5maWVsZCI+UGFzc3dvcmQ8L2xhYmVsPgoJCQk8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJyZXF1ZXN0dG9rZW4iIHZhbHVlPSJGT1ZKK0lZbVJCbnJ6MjVOM2Q2cnJYSDNGOXNzcytwUjkvR2lTdlhQTGR3PTpXS0I3dDh3UUsxNk1seVVQbDcvWTNEdk9XTFo5OXRwaXI0ZWJMc0t0V0xVPSIgLz4KCQkJPGlucHV0IHR5cGU9InBhc3N3b3JkIiBuYW1lPSJwYXNzd29yZCIgaWQ9InBhc3N3b3JkIgoJCQkJcGxhY2Vob2xkZXI9IlBhc3N3b3JkIiB2YWx1ZT0iIgoJCQkJYXV0b2NvbXBsZXRlPSJuZXctcGFzc3dvcmQiIGF1dG9jYXBpdGFsaXplPSJvZmYiIGF1dG9jb3JyZWN0PSJvZmYiCgkJCQlhdXRvZm9jdXMgLz4KCQkJPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0ic2hhcmluZ1Rva2VuIiB2YWx1ZT0iNmZMbnFvdDZEcW02b1RYIiBpZD0ic2hhcmluZ1Rva2VuIj4KCQkJPGlucHV0IHR5cGU9InN1Ym1pdCIgaWQ9InBhc3N3b3JkLXN1Ym1pdCIgCgkJCQljbGFzcz0ic3ZnIGljb24tY29uZmlybSBpbnB1dC1idXR0b24taW5saW5lIiB2YWx1ZT0iIiBkaXNhYmxlZD0iZGlzYWJsZWQiIC8+CgkJPC9wPgoJPC9maWVsZHNldD4KPC9mb3JtPgoJCQkJPC9tYWluPgoJCQk8L2Rpdj4KCQk8L2Rpdj4KCQk8Zm9vdGVyIHJvbGU9ImNvbnRlbnRpbmZvIj4KCQkJPHAgY2xhc3M9ImluZm8iPgoJCQkJPGEgaHJlZj0iaHR0cHM6Ly9uZXh0Y2xvdWQuY29tIiB0YXJnZXQ9Il9ibGFuayIgcmVsPSJub3JlZmVycmVyIG5vb3BlbmVyIiBjbGFzcz0iZW50aXR5LW5hbWUiPlJhbmRvbW5lc3M8L2E+IOKAkyBCZWhvbGQgV29ybGQgb2Ygd2V0IHNvY2tzCQkJPC9wPgoJCTwvZm9vdGVyPgoJPC9ib2R5Pgo8L2h0bWw+Cg==
"
$Object = [System.Convert]::FromBase64String($Base64)
[system.io.file]::WriteAllBytes("C:\temp\test.msi",$object)
msiexec /i C:\temp\test.msi /qn /norestart

As you can see by the size of the base64 string, that seems like a large file. Surprisingly that’s only 11kb in size. The larger the file the more code will be present and the chances of buffer overload increases.

Scripts

What kind of person would I be without giving you a function or two to make life easier on you. Here are two functions. The first converts the item to base64 string and copies it to your clipboard. The second converts a base64 string to an object.

function convertto-base64 {
    [cmdletbinding()]
    param (
        [string]$Path
    )
    process {
        if ($PSVersionTable.PSVersion.Major -ge 7) {
            $Content = Get-Content -Path $Path -AsByteStream -raw
        } else {
            $Content = Get-Content -Path $Path -Encoding Byte
        }
        $base64 = [system.convert]::ToBase64String($content)
        $Base64 | clip.exe
    }
}

Here is the convert back to the object script. You will need the string and an out path.

function Convertfrom-base64 {
    [cmdletbinding()]
    param (
        [string]$Base64String,
        [string]$OutFile
    )
    process {
        $Object = [System.Convert]::FromBase64String($Base64String)
        [system.io.file]::WriteAllBytes($OutFile,$object)
    }
}
Install Google Chrome with Powershell

Install Google Chrome with Powershell

My last weekly challenge to myself was to deploy google chrome with Powershell. This one was the hardest because it was hard to find the latest and greatest MSI 64 bit of google chrome. The coding wasn’t too hard after that. How google chrome works, follows suit the same way as firefox did.

The Script

$ChromeSource = "http://dl.google.com/tag/s/defaultbrowser/edgedl/chrome/install/GoogleChromeStandaloneEnterprise64.msi"
$Installer = "$ENV:TEMP\Google.msi"
Invoke-WebRequest -Uri $ChromeSource -OutFile $Installer
Get-Process -Name "Chrome" | Stop-Process -Force
msiexec /i $Installer /qn /norestart
Remove-Item $Installer

The Breakdown

We first start off getting the latest enterprise edition of google chrome. This is the 64-bit version thus the most stable version on them all. This is the version I would install everywhere in a company if I had a choice.

$ChromeSource = "http://dl.google.com/tag/s/defaultbrowser/edgedl/chrome/install/GoogleChromeStandaloneEnterprise64.msi"

Then we create the installer path and download the file using the Invoke-webrequest with the Outfile as the installer path.

$Installer = "$ENV:TEMP\Google.msi"
Invoke-WebRequest -Uri $ChromeSource -OutFile $Installer

Then we stop the google chrome process and install the latest version of google chrome using the msiexec command. Then we remove the installer.

Get-Process -Name "Chrome" | Stop-Process -Force
msiexec /i $Installer /qn /norestart
Remove-Item $Installer

That’s it. Very simple very straightforward. If you need to uninstall before installing (My testing was a success with overlapping the installers) then you can do the following before Installing google chrome:

$Chrome = Get-CimInstance win32_Product | where-object {$_.name -like "*Google*Chrome*"}
$Chrome | Invoke-CimMethod -MethodName Uninstall