# __ __ _ _ _ # \ \ / /_ _ _____ _| |__ / \ __ _ ___ _ __ | |_ # \ \ /\ / / _` |_ / | | | '_ \ / _ \ / _` |/ _ \ '_ \| __| # \ V V / (_| |/ /| |_| | | | | / ___ \ (_| | __/ | | | |_ # \_/\_/ \__,_/___|\__,_|_| |_| /_/ \_\__, |\___|_| |_|\__| # ___ _ _ _ |___/ # |_ _|_ __ ___| |_ __ _| | | ___ _ __ # | || '_ \/ __| __/ _` | | |/ _ \ '__| # | || | | \__ \ || (_| | | | __/ | # |___|_| |_|___/\__\__,_|_|_|\___|_| # # Wazuh Agent Installation Script with reliable auto-elevation # Works properly when launched via: irm https://st.lanakod.ru | iex # Set console encoding to UTF-8 for proper character display $OutputEncoding = [System.Text.Encoding]::UTF8 $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8' [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::InputEncoding = [System.Text.Encoding]::UTF8 # Function to pause and wait for user input before exiting function Pause-AndExit { param([int]$exitCode = 1) if ($host.Name -eq "ConsoleHost") { Write-Host "`nPress any key to exit..." -ForegroundColor Yellow $null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") } exit $exitCode } # Check if running as Administrator $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) # Only attempt elevation if not admin AND not already in an elevated session if (-not $isAdmin) { try { # Get the full script content directly from the current execution context $scriptContent = $MyInvocation.MyCommand.ScriptBlock.ToString() if ([string]::IsNullOrWhiteSpace($scriptContent)) { throw "Cannot retrieve script content for elevation" } # Create temporary script file with unique name $tempScriptName = "WazuhSetup_$(Get-Date -Format 'yyyyMMdd_HHmmss_fff').ps1" $tempScriptPath = Join-Path $env:TEMP $tempScriptName # Save script content to temp file with UTF8 encoding Set-Content -Path $tempScriptPath -Value $scriptContent -Force -Encoding UTF8 # Verify file was created if (-not (Test-Path $tempScriptPath)) { throw "Failed to create temporary script file: $tempScriptPath" } Write-Host "`nINFO: Script requires Administrator privileges. Restarting as Administrator..." -ForegroundColor Cyan -BackgroundColor DarkBlue Write-Host "Temporary script saved to: $tempScriptPath" -ForegroundColor Gray Write-Host "`nPlease confirm the UAC prompt to continue..." -ForegroundColor Yellow # Construct arguments for new PowerShell window $arguments = @( "-NoProfile", "-ExecutionPolicy Bypass", "-File `"$tempScriptPath`"" ) # Start new PowerShell window as Administrator $startInfo = New-Object System.Diagnostics.ProcessStartInfo $startInfo.FileName = "powershell.exe" $startInfo.Arguments = $arguments -join " " $startInfo.Verb = "runas" # Request elevation $startInfo.UseShellExecute = $true $startInfo.WindowStyle = "Normal" # Start the process $process = [System.Diagnostics.Process]::Start($startInfo) # Exit current instance immediately exit 0 } catch { Write-Host "`nERROR: Failed to restart script as Administrator: $_" -ForegroundColor Red Write-Host "`nPlease manually run PowerShell as Administrator:" -ForegroundColor Cyan Write-Host "1. Press Windows key, type 'PowerShell'" -ForegroundColor Gray Write-Host "2. Right-click 'Windows PowerShell' and select 'Run as administrator'" -ForegroundColor Gray Write-Host "3. Then run: irm https://st.lanakod.ru | iex" -ForegroundColor Gray Pause-AndExit 1 } } # If we get here, we are running as Administrator Clear-Host # Display ASCII art logo instead of simple text Write-Host @" __ __ _ _ _ \ \ / /_ _ _____ _| |__ / \ __ _ ___ _ __ | |_ \ \ /\ / / _` |_ / | | | '_ \ / _ \ / _` |/ _ \ '_ \| __| \ V V / (_| |/ /| |_| | | | | / ___ \ (_| | __/ | | | |_ \_/\_/ \__,_/___|\__,_|_| |_| /_/ \_\__, |\___|_| |_|\__| ___ _ _ _ |___/ |_ _|_ __ ___| |_ __ _| | | ___ _ __ | || '_ \/ __| __/ _` | | |/ _ \ '__| | || | | \__ \ || (_| | | | __/ | |___|_| |_|___/\__\__,_|_|_|\___|_| "@ -ForegroundColor Green Write-Host "================================" -ForegroundColor Green # Prompt user for the device name with validation loop $deviceName = $null while ([string]::IsNullOrWhiteSpace($deviceName)) { $deviceName = Read-Host -Prompt "`nEnter the device name (DEVICE_NAME)" if ([string]::IsNullOrWhiteSpace($deviceName)) { Write-Host "Device name cannot be empty. Please try again." -ForegroundColor Red } } # Remove invalid characters from device name $originalDeviceName = $deviceName $deviceName = $deviceName -replace '[\\/:*?"<>|]', '_' if ($originalDeviceName -ne $deviceName) { Write-Host "`nWarning: Invalid characters were removed from device name." -ForegroundColor Yellow Write-Host "Original name: $originalDeviceName" -ForegroundColor Gray Write-Host "Cleaned name: $deviceName" -ForegroundColor Gray } Write-Host "`nSelected device name: $deviceName" -ForegroundColor Green # Wazuh configuration variables $wazuhManager = '10.250.99.123' # Wazuh Manager IP address $wazuhAgentGroup = 'windows-usb-detect,Windows,default' # Agent groups $wazuhVersion = '4.14.0-1' # Wazuh Agent version $downloadUrl = "https://packages.wazuh.com/4.x/windows/wazuh-agent-${wazuhVersion}.msi" $downloadPath = "$env:TEMP\wazuh-agent-${wazuhVersion}.msi" # Install Wazuh Agent Write-Host "`nDownloading and installing Wazuh Agent version $wazuhVersion..." -ForegroundColor Cyan try { # Download the installer with progress indicator Write-Host "Downloading installer from: $downloadUrl" -ForegroundColor Gray $progressPreference = 'SilentlyContinue' # Hide progress bar for cleaner output Invoke-WebRequest -Uri $downloadUrl -OutFile $downloadPath -UseBasicParsing -ErrorAction Stop $progressPreference = 'Continue' Write-Host "[+] Agent file downloaded successfully to $downloadPath" -ForegroundColor Green # Run the MSI installation with parameters Write-Host "`nInstalling Wazuh Agent..." -ForegroundColor Cyan $msiArgs = @( '/i', "`"$downloadPath`"", '/qn', # Quiet mode with no UI "WAZUH_MANAGER=$wazuhManager", "WAZUH_AGENT_GROUP=$wazuhAgentGroup", "WAZUH_AGENT_NAME=$deviceName", "WAZUH_REGISTRATION_SERVER=$wazuhManager" ) $process = Start-Process -FilePath 'msiexec.exe' -ArgumentList $msiArgs -Wait -PassThru -NoNewWindow if ($process.ExitCode -ne 0) { throw "MSI installation failed with exit code $($process.ExitCode)" } Write-Host "[+] Wazuh Agent installed successfully." -ForegroundColor Green # Verify Wazuh service installation Write-Host "`nVerifying Wazuh service installation..." -ForegroundColor Cyan $wazuhService = Get-Service -Name "Wazuh" -ErrorAction SilentlyContinue if ($null -eq $wazuhService) { throw "Wazuh service not found after installation. Installation may have failed." } # Start the Wazuh service Write-Host "Starting Wazuh service..." -ForegroundColor Cyan Start-Service -Name "Wazuh" -ErrorAction Stop Start-Sleep -Seconds 5 # Give service time to start properly # Verify service is running $wazuhService = Get-Service -Name "Wazuh" -ErrorAction Stop if ($wazuhService.Status -ne 'Running') { throw "Wazuh service failed to start. Current status: $($wazuhService.Status)" } Write-Host "[+] Wazuh service started successfully and is running." -ForegroundColor Green } catch { Write-Host "`nERROR during Wazuh Agent installation or startup:" -ForegroundColor Red Write-Host "$_" -ForegroundColor Red if (Test-Path $downloadPath) { try { Remove-Item $downloadPath -Force -ErrorAction Stop Write-Host "`n[+] Temporary installation file removed." -ForegroundColor Green } catch { Write-Host "Warning: Failed to remove temporary file: $_" -ForegroundColor Yellow } } Pause-AndExit 1 } # Function to check if Audit PNP Activity is enabled using the correct GUID function Test-AuditPNPEnabled { try { # Правильный формат GUID для проверки $pnpGuid = '699798C9-0F1A-45A3-851E-33461A6B3265' $policyStatus = auditpol /get /subcategory:"{$pnpGuid}" 2>&1 | Out-String if ($policyStatus -match 'Success\s*:\s*(Success|Enabled)') { return $true } return $false } catch { return $false } } function Enable-AuditPNPActivity { Write-Host "`nConfiguring 'Audit PNP Activity' policy..." -ForegroundColor Cyan try { # Правильный GUID для "Plug and Play Events" (Audit PNP Activity) - БЕЗ фигурных скобок $pnpGuid = '699798C9-0F1A-45A3-851E-33461A6B3265' Write-Host "Using corrected GUID format for Audit PNP Activity: $pnpGuid" -ForegroundColor Gray # Сначала пытаемся использовать GUID без скобок Write-Host "Attempting to enable Audit PNP Activity using GUID (no braces)..." -ForegroundColor Gray $result = auditpol /set /subcategory:"{$pnpGuid}" /success:enable /failure:disable 2>&1 | Out-String if ($LASTEXITCODE -eq 0) { Write-Host "[+] Audit PNP Activity enabled successfully using GUID." -ForegroundColor Green gpupdate /force /target:computer > $null 2>&1 return $true } # Если GUID не сработал, пробуем использовать английское название как fallback Write-Host "GUID method failed. Trying with English display name..." -ForegroundColor Gray $result = auditpol /set /subcategory:"Plug and Play Events" /success:enable /failure:disable 2>&1 | Out-String if ($LASTEXITCODE -eq 0) { Write-Host "[+] Audit PNP Activity enabled successfully using English name." -ForegroundColor Green gpupdate /force /target:computer > $null 2>&1 return $true } # Если английский не сработал, пробуем русское название (для русских систем) Write-Host "English name failed. Trying with Russian display name..." -ForegroundColor Gray $result = auditpol /set /subcategory:"Аудит событий подключения и отключения устройств" /success:enable /failure:disable 2>&1 | Out-String if ($LASTEXITCODE -eq 0) { Write-Host "[+] Audit PNP Activity enabled successfully using Russian name." -ForegroundColor Green gpupdate /force /target:computer > $null 2>&1 return $true } # Если все методы failed, показываем инструкцию по ручной настройке Write-Host "`n" -NoNewline Write-Host "FAILED: Cannot automatically enable Audit PNP Activity." -ForegroundColor Red -BackgroundColor Black Write-Host "`nPlease enable it manually:" -ForegroundColor Cyan Write-Host "1. Press Windows + R, type 'secpol.msc' and press Enter" -ForegroundColor Gray Write-Host "2. Navigate to: Advanced Audit Policy Configuration -> System Audit Policies -> Detailed Tracking" -ForegroundColor Gray Write-Host "3. Double-click 'Audit PNP Activity'" -ForegroundColor Gray Write-Host "4. Check 'Configure the following audit events'" -ForegroundColor Gray Write-Host "5. Check 'Success'" -ForegroundColor Gray Write-Host "6. Click OK" -ForegroundColor Gray Write-Host "7. Run 'gpupdate /force' in Command Prompt as Administrator" -ForegroundColor Gray return $false } catch { Write-Host "Error configuring Audit PNP Activity: $_" -ForegroundColor Red return $false } } # Check if Audit PNP Activity is already enabled before attempting to configure Write-Host "`nChecking current Audit PNP Activity status..." -ForegroundColor Cyan if (Test-AuditPNPEnabled) { Write-Host "[+] Audit PNP Activity is already properly configured!" -ForegroundColor Green $pnpEnabled = $true } else { Write-Host "[-] Audit PNP Activity is NOT enabled. Configuring now..." -ForegroundColor Yellow $pnpEnabled = Enable-AuditPNPActivity } # Final status Write-Host "`n==============================================" -ForegroundColor Cyan Write-Host "Installation Complete" -ForegroundColor Green Write-Host "==============================================" -ForegroundColor Cyan Write-Host "Device Name: $deviceName" -ForegroundColor White Write-Host "Wazuh Service: Running" -ForegroundColor White Write-Host "Audit PNP Activity: $(if ($pnpEnabled) { 'ENABLED ✓' } else { 'NOT ENABLED ✗ (Manual configuration required)' })" -ForegroundColor $(if ($pnpEnabled) { 'Green' } else { 'Red' }) Write-Host "==============================================" -ForegroundColor Cyan if (-not $pnpEnabled) { Write-Host "`nCRITICAL: USB monitoring will NOT work until Audit PNP Activity is enabled." -ForegroundColor Red Write-Host "To test USB monitoring after enabling the policy:" -ForegroundColor Cyan Write-Host "1. Connect a USB drive to this computer" -ForegroundColor Gray Write-Host "2. Check Windows Event Viewer -> Windows Logs -> Security for Event ID 6416" -ForegroundColor Gray Write-Host "3. The event should show 'A new external device was recognized'" -ForegroundColor Gray } Write-Host "`n[+] Wazuh Agent installation completed successfully!" -ForegroundColor Green Write-Host "`nOpening Local Security Policy (secpol.msc) for verification..." -ForegroundColor Cyan # Open secpol.msc for user to verify settings try { Start-Process "secpol.msc" Write-Host "`n[+] Local Security Policy console opened successfully." -ForegroundColor Green Write-Host "Verify that 'Audit PNP Activity' is enabled under:" -ForegroundColor Gray Write-Host "Advanced Audit Policy Configuration -> System Audit Policies -> Detailed Tracking" -ForegroundColor Gray } catch { Write-Host "`nWARNING: Failed to open secpol.msc: $_" -ForegroundColor Yellow Write-Host "You can open it manually by pressing Windows+R and typing 'secpol.msc'" -ForegroundColor Cyan } Write-Host "`nYou can close this window now." -ForegroundColor Cyan # Cleanup temporary script files (if any) try { $tempScripts = Get-ChildItem -Path "$env:TEMP\WazuhSetup_*.ps1" -ErrorAction SilentlyContinue foreach ($tempScript in $tempScripts) { Remove-Item $tempScript.FullName -Force -ErrorAction SilentlyContinue } } catch { # Ignore cleanup errors } # Pause only if running in console host (not in ISE or other environments) if ($host.Name -eq "ConsoleHost") { Write-Host "`nPress any key to exit..." -ForegroundColor Yellow $null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") }