Did you know you can wipe a computer using code? I didn’t realize this was an option until I needed to do it the other day. Well, I quickly found code to wipe a computer using PowerShell. It was pretty simple as a full Microsoft documentation page is dedicated to the wipe types. You can read about it here. The only problem I ran into was this code needs to be launched as a “System User” instead of a domain admin. This presented a problem if I wanted to use PowerShell for this task. However, psexec could launch scripts as a system user. That was my solution for running a Remote Wipe on a Computer with PowerShell.

The Script

Today we start out with a rough script. This script is designed to give you a rough idea of what I am thinking about and how I was able to do it. You can do additional items to this script like split the here-string and add options. However, most of my items have been from a clean local wipe idea.

function Invoke-RemoteWipeComputer {
    param (
        [parameter(Mandatory = $true)][string[]]$ComputerName
    )
    begin {
        if (!(Test-Path -Path "$env:SystemDrive\Temp")) { New-Item -Path c:\ -Name Temp -ItemType Directory }
        if (!(Test-Path -Path "$env:SystemDrive\Temp\PsExec.exe")) { Invoke-WebRequest -Uri "https://live.sysinternals.com/PsExec.exe" -OutFile "$env:SystemDrive\Temp\PsExec.exe" }
        $WipeScript = @'

            $session = New-CimSession
            $params = New-Object Microsoft.Management.Infrastructure.CimMethodParametersCollection
            $param = [Microsoft.Management.Infrastructure.CimMethodParameter]::Create("param", "", "String", "In")
            $params.Add($param)
            $CimSplat = @{
                Namespace = "root\cimv2\mdm\dmmap"
                ClassName = "MDM_RemoteWipe"
                Filter    = "ParentID='./Vendor/MSFT' and InstanceID='RemoteWipe'"
            }

            try {
                $instance = Get-CimInstance @CimSplat
                $session.InvokeMethod($CimSplat["Namespace"], $instance, "doWipeMethod", $params)
            }
            catch {
                Write-Error $_
                exit 1
            }
'@ 
        $WipeScript > "$env:SystemDrive\Temp\WipeScript.ps1"
    }
    process {
        foreach ($Computer in $ComputerName) {
            if (Test-Connection -ComputerName $Computer -Count 2 -Quiet) {
                Copy-Item "$env:SystemDrive\Temp\WipeScript.ps1" -Destination "\\$Computer\c$\Temp\WipeScript.ps1" -Force
                & "$env:SystemDrive\Temp\PsExec.exe" -s \\$Computer PowerShell -ExecutionPolicy Bypass -File "\\$Computer\c$\Temp\WipeScript.ps1"
            }
        }
    }
    end {}
}

The Breakdown

Let’s break down this script. The first item is always the parameters. In this case, we are making a list of strings with computer names. We will use these later. This script is broken up into a begin and process. Remember, begin, process, end, and final are all simple organization tools. This makes life easier because we are going to need to download the psexec command from sysinternals life site. We also need to build out the main script and have a folder to add it all in.

Begin

The first thing we need to do is test if the c:\temp exists as we are going to download everything into it. This one liner makes life much easier. We test if the path doesn’t exist, then we make it if that is true. The ! mark indicates do the opposite of what is inside the (). Inside the () we are testing for c:\temp or local system drive temp in this case. If that doesn’t exist, we create a new item with a path of the system drive. We create a new item with new item and call it temp making sure it’s a directory flag in the item type.

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

Next, we test if the psexec exists and download it accordingly. Once again, we are using the ! test. If the file doesn’t exist, we us invoke-webrequest to reach out to the live sysinternals site and download it to our c:\temp.

if (!(Test-Path -Path "$env:SystemDrive\Temp\PsExec.exe")) { Invoke-WebRequest -Uri "https://live.sysinternals.com/PsExec.exe" -OutFile "$env:SystemDrive\Temp\PsExec.exe" }

Now we have downloaded and made all the required folders, it’s time to write the script. In this case, we are building the script with a here-string. This way, the data is the same no matter what we do. It’s a clone each time and we know what we are getting. Let’s break down the wipe script.

The Wipe Script

As stated before, we are building out the script inside our here-string. This way, it is always the same. I prefer to know what is happening with any script I launch. So, it’s time to break it down.

We start off with a new cim session. This is a blank session, with nothing special about it.

$session = New-CimSession

Next, we need to make some new objects. We need a cim method parameters container. So we do this with a new-object command. Then we add the parameters we need inside this new parameter container. Both of these commands use the Management > infrastructure objects as parents. Finally, we add the parameters to the parameters. yeah that sounds weird, but luckily we just change a s and it makes it much easier to understand.

$params = New-Object Microsoft.Management.Infrastructure.CimMethodParametersCollection
$param = [Microsoft.Management.Infrastructure.CimMethodParameter]::Create("param", "", "String", "In")
$params.Add($param)

Now we have our parameter set for our invoke method, it’s time to create the splat. We need a remote wipe command. Viewing this documentation. We see our remote wipe is located inside the ./Device/Vendor/MSFT/RemoteWipe/. This is part of the MDM cim version 2 instance. So, our namespace will need to reflect that. We have a namespace of root\cimv2\mdm\dmmap. Our class name needs to be the MDM_Remotewipe. Finally, our filter needs to be show the vendor msft and the instanceId, the item we are after, is remoteWipe.

$CimSplat = @{
    Namespace = "root\cimv2\mdm\dmmap"
    ClassName = "MDM_RemoteWipe"
    Filter    = "ParentID='./Vendor/MSFT' and InstanceID='RemoteWipe'"
}

Now we start our try catch. Inside our try, we are call the get-ciminstance with the splat from before. This creates an instances on the computer that is talking directly to the wipe system. Now, we need to use the session we made at the beginning of this here-string. We invoke the method using invoke method. From there, we use the $cimsplat namespace, the instance of the cimsplat, the wipe method, in this case, a local wipe, and the parameters we made at the beginning. The system will trigger a wipe at this point. The catch just exits and sends the error it gets.

Now the here-string is built, we push that string into a PowerShell script on our freshly created temp folder. We use the single > to overwrite anything that is already there. This limits mistakes.

Process

Now it’s time for the process. Here we are going to copy the files and execute it with psexec. We are also going to loop through each computer during this process. The first step is to start a loop with a foreach loop.

foreach ($Computer in $ComputerName) {
#            Do something
}

Up to this point, we have done everything on our computer. We have downloaded the psexec. We have created the required script. The next step starts to affect the end user’s computer. This is where the Remote comes into Remote Wipe a Computer. We are going to use the command test-connection and ping the computer twice.

if (Test-Connection -ComputerName $Computer -Count 2 -Quiet) {
    #It was tested
}

If the computer is present, we attempt to copy the script over. We force the copy to overwrite anything with the same name. Finally, we use the local psexec to trigger powershell as the system. We use the -s for psexec to trigger the file that is on the remote computer that we copied. I want the output on my local screen of the psexec command. This is what we trigger it with the & instead of a start-process. Now, could you use the start process, yes, in fact, it would be quicker since you can set it as a job and put the PC name as the job, but you do lose the output information from psexec. So, if there is a problem, you wouldn’t know.

Copy-Item "$env:SystemDrive\Temp\WipeScript.ps1" -Destination "\\$Computer\c$\Temp\WipeScript.ps1" -Force
& "$env:SystemDrive\Temp\PsExec.exe" -s \\$Computer PowerShell -ExecutionPolicy Bypass -File "\\$Computer\c$\Temp\WipeScript.ps1"

At this point, the computer will take a few seconds, and the reset process would start. After that, everything you will need to do will require a hand on the machine. So have fun and use wisely. Also, the script inside the script can be ran by other products like Continuum, ninja, pdq and more.

Continue Reading