# ControlD MDM Agent — Windows Installer # Usage: powershell -ExecutionPolicy Bypass -File install.ps1 -ControlDToken -DashboardURL -EmployeeName param( [Parameter(Mandatory=$true)][string]$ControlDToken, [Parameter(Mandatory=$true)][string]$DashboardURL, [Parameter(Mandatory=$true)][string]$EmployeeName ) $ErrorActionPreference = "Stop" $CtrldDir = "C:\ProgramData\ControlD" $CtrldBin = "$CtrldDir\ctrld.exe" $CtrldConfig = "$CtrldDir\ctrld.toml" $DeviceID = [guid]::NewGuid().ToString() $Hostname = $env:COMPUTERNAME Write-Host "[*] Installing ControlD MDM agent for $EmployeeName on $Hostname..." # 1. Download ctrld binary Write-Host "[*] Downloading ctrld..." New-Item -ItemType Directory -Force -Path $CtrldDir | Out-Null $arch = if ([Environment]::Is64BitOperatingSystem) { "amd64" } else { "386" } $url = "https://github.com/Control-D-Inc/ctrld/releases/latest/download/ctrld-windows-$arch.exe" Invoke-WebRequest -Uri $url -OutFile $CtrldBin -UseBasicParsing # 2. Write config Write-Host "[*] Writing ctrld.toml..." @" [upstream.0] endpoint = "https://dns.controld.com/$ControlDToken" type = "doh" timeout = 5000 [listener.0] ip = "127.0.0.1" port = 53 "@ | Set-Content -Path $CtrldConfig -Encoding UTF8 # 3. Install as Windows Service Write-Host "[*] Installing Windows service..." & $CtrldBin service install --config $CtrldConfig 2>$null & $CtrldBin service start 2>$null if ($LASTEXITCODE -ne 0) { sc.exe create "ControlDAgent" binPath= "`"$CtrldBin`" run --config `"$CtrldConfig`"" start= auto | Out-Null sc.exe start "ControlDAgent" | Out-Null } # 4. Set DNS on all adapters to 127.0.0.1 Write-Host "[*] Setting system DNS..." Get-NetAdapter | Where-Object { $_.Status -eq 'Up' } | ForEach-Object { Set-DnsClientServerAddress -InterfaceIndex $_.ifIndex -ServerAddresses "127.0.0.1" } # 5. Register with MDM backend Write-Host "[*] Registering device with MDM backend..." try { $body = @{ device_id = $DeviceID hostname = $Hostname employee = $EmployeeName os = "windows" resolver_id = $ControlDToken } | ConvertTo-Json Invoke-RestMethod -Uri "$DashboardURL/api/register" -Method POST -Body $body -ContentType "application/json" } catch { Write-Host "[!] Warning: Could not reach MDM backend. Device will register on next heartbeat." } # 6. Set up heartbeat scheduled task (every 5 min) Write-Host "[*] Setting up heartbeat..." $heartbeatScript = @" try { `$ip = (Invoke-RestMethod -Uri 'https://ifconfig.me' -UseBasicParsing -TimeoutSec 5) } catch { `$ip = 'unknown' } `$body = @{ device_id = '$DeviceID'; ip = `$ip } | ConvertTo-Json Invoke-RestMethod -Uri '$DashboardURL/api/heartbeat' -Method POST -Body `$body -ContentType 'application/json' -TimeoutSec 10 "@ $heartbeatPath = "$CtrldDir\heartbeat.ps1" $heartbeatScript | Set-Content -Path $heartbeatPath -Encoding UTF8 $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -File `"$heartbeatPath`"" $trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Minutes 5) -Once -At (Get-Date) $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest Register-ScheduledTask -TaskName "ControlDHeartbeat" -Action $action -Trigger $trigger -Principal $principal -Force | Out-Null Write-Host "[+] Installation complete!" Write-Host " Device ID: $DeviceID" Write-Host " Config: $CtrldConfig" Write-Host " DNS: 127.0.0.1 -> ControlD (DoH)"