<?php
/*
author: sohay (ditingkatkan oleh asisten keamanan)
title: Backdoor Scanner v2.0.0 - Lengkap & Aman
*/

// Hanya bisa diakses via browser, bukan CLI
if (php_sapi_name() === 'cli') {
    exit("Gunakan via browser.\n");
}

// Hanya bisa diakses dari localhost (opsional, bisa dikomentari)
// if ($_SERVER['REMOTE_ADDR'] !== '127.0.0.1' && $_SERVER['REMOTE_ADDR'] !== $_SERVER['SERVER_ADDR']) {
//     die("Akses ditolak.");
// }

// Konfigurasi
define('LOG_FILE', 'infected_files.txt');
define('MAX_FILE_SIZE', 10 * 1024 * 1024);
define('SUSPICIOUS_PATTERNS', [
    '/exec\s*\(/i',
    '/system\s*\(/i',
    '/passthru\s*\(/i',
    '/shell_exec\s*\(/i',
    '/popen\s*\(/i',
    '/proc_open\s*\(/i',
    '/eval\s*\(/i',
    '/assert\s*\(/i',
    '/preg_replace\s*\([^,]*,.*?\$[^,]/i',
    '/base64_decode\s*\(/i',
    '/gzinflate\s*\(/i',
    '/gzuncompress\s*\(/i',
    '/str_rot13\s*\(/i',
    '/file_put_contents\s*\(/i',
    '/fopen.*?w/i',
    '/curl_exec\s*\(/i',
    '/copy\s*\(\s*["\']https?:/i',
    '/<\?php @include/i',
    '/wp_cache_phase2/i',
    '/iframe.*?src=.*?http/i',
    '/c99|c100|r57|b374k|weevely|phpspy|404\.php|shell\.php|eval\(/i',
]);

$allowed_extensions = ['php', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phar', 'inc', 'htaccess'];

function printCSS() {
    echo '<style>
        body { 
            background: #000; 
            color: #0f0; 
            font-family: "Courier New", monospace; 
            font-size: 12px; 
            line-height: 1.4; 
            margin: 0; 
            padding: 10px;
        }
        h1 { 
            color: #0f0; 
            border: 1px solid #0f0; 
            padding: 8px; 
            margin: 0 0 10px 0; 
            font-size: 18px; 
            font-weight: bold; 
        }
        a { color: #0f0; text-decoration: none; }
        a:hover { background: #f00; }
        .infected { color: #ff0; font-weight: bold; }
        textarea { 
            width: 80%; 
            height: 350px;           /* Diperbesar dari 120px → 300px */
            font-family: "Courier New", monospace;
            font-size: 12px;
            line-height: 1.4;
            margin: 8px 0;
            background: #111;
            color: #0f0;
            border: 1px solid #0f0;
            padding: 10px;
            box-sizing: border-box;
            resize: vertical;         /* Bisa diperbesar manual */
            word-wrap: break-word;    /* Jika ada string panjang */
            overflow-y: auto;         /* Scroll vertikal */
        }
        input, button { 
            padding: 8px; 
            margin: 5px; 
            background: #111; 
            color: #0f0; 
            border: 1px solid #0f0; 
            cursor: pointer;
        }
        .result { 
            margin: 10px 0; 
            padding: 10px; 
            border-bottom: 1px dashed #333; 
            background: #000; 
            border-left: 4px solid #ff0;
        }
        .delete-btn { color: #f00; font-weight: bold; }
        #footer { 
            margin: 20px 0; 
            text-align: center; 
            color: #555; 
            font-size: 11px; 
        }
    </style>';
}

if (isset($_GET['kill'])) {
    unlink(__FILE__);
    die("<h1>[!] Scanner telah dihapus.</h1>");
}

if (isset($_GET['delete'])) {
    $file = urldecode($_GET['delete']);
    if (file_exists($file) && is_writable($file)) {
        unlink($file) ? $msg = "Dihapus" : $msg = "Gagal dihapus";
    } else {
        $msg = "File tidak ada atau tidak bisa dihapus";
    }
    echo "<div class='result'><b>[DELETE]</b> $file — <span class='infected'>$msg</span></div><br>";
}

if (isset($_GET['clearlog'])) {
    @unlink(LOG_FILE);
    echo "<div class='result'><b>[LOG]</b> Log dibersihkan.</div><br>";
}

printCSS();
echo "<h1>🔍 Backdoor Scanner v2.0.0</h1>";
echo "<a href='?kill'><font color='yellow'>[Self Delete]</font></a> | <a href='?clearlog'><font color='cyan'>[Clear Log]</font></a><br><br>";

$current_dir = getcwd();
if (isset($_GET['dir']) && is_dir($_GET['dir'])) {
    $current_dir = rtrim($_GET['dir'], '/\\');
}

echo "<form method='GET'>
    <input type='text' name='dir' value='" . htmlspecialchars($current_dir) . "' style='width:600px;' />
    <button type='submit'>Scan</button>
</form><br>";

echo "<b>Current Directory:</b> <font color='yellow'>" . htmlspecialchars($current_dir) . "</font><br><br>";

function logInfection($file, $reason = 'suspect') {
    $log = "[" . date('Y-m-d H:i:s') . "] $file | $reason\n";
    file_put_contents(LOG_FILE, $log, FILE_APPEND | LOCK_EX);
}

function scanFile($file) {
    global $allowed_extensions;

    $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));

    // Cek ekstensi
    if (!in_array($ext, $allowed_extensions) && $ext !== 'zip') {
        return;
    }

    if ($ext === 'zip') {
        scanZip($file);
        return;
    }

    if (filesize($file) > MAX_FILE_SIZE) {
        return;
    }

    $content = @file_get_contents($file);
    if ($content === false || strlen($content) === 0) {
        return;
    }

    foreach (SUSPICIOUS_PATTERNS as $pattern) {
        if (preg_match($pattern, $content)) {
            $pattern_name = htmlspecialchars($pattern);
            echo "<div class='result'>
                <b>[+] INFECTED</b> → 
                <a href='?delete=" . urlencode($file) . "&dir=" . urlencode(dirname($file)) . "' class='delete-btn'>[DELETE]</a>
                <span class='infected'>" . htmlspecialchars($file) . "</span><br>
                Pattern: $pattern_name<br>
                <textarea>" . htmlspecialchars($content) . "</textarea>
            </div>";

            logInfection($file, "Match: $pattern_name");
            return;
        }
    }
}

function scanZip($zipFile) {
    $zip = new ZipArchive();
    if ($zip->open($zipFile) !== TRUE) {
        return;
    }

    for ($i = 0; $i < $zip->numFiles; $i++) {
        $filename = $zip->getNameIndex($i);
        $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));

        if (!in_array($ext, ['php', 'phtml', 'shtml', 'htaccess'])) {
            continue;
        }

        $stream = $zip->getStream($filename);
        if (!$stream) continue;

        $content = stream_get_contents($stream);
        fclose($stream);

        foreach (SUSPICIOUS_PATTERNS as $pattern) {
            if (preg_match($pattern, $content)) {
                $full_path = "$zipFile::$filename";
                echo "<div class='result'>
                    <b>[ZIP]</b> → 
                    <span class='infected'>" . htmlspecialchars($full_path) . "</span><br>
                    Pattern: " . htmlspecialchars($pattern) . "<br>
                    <textarea>" . htmlspecialchars(substr($content, 0, 2000)) . "...</textarea>
                </div>";

                logInfection($full_path, "ZIP infected: $pattern");
                break;
            }
        }
    }

    $zip->close();
}

function scanDirectory($dir) {
    if (!is_readable($dir)) return;

    $files = scandir($dir);
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;

        $path = $dir . DIRECTORY_SEPARATOR . $file;

        if (is_file($path)) {
            scanFile($path);
        } elseif (is_dir($path)) {
            scanDirectory($path);
        }
    }
}

echo "<div style='margin:10px 0; color:cyan;'>[+] Memulai scan... (mungkin butuh waktu lama)</div>";
scanDirectory($current_dir);
echo "<div style='margin:10px 0; color:yellow;'>[✓] Scan selesai.</div>";

echo "<div id='footer'>
    <div class='footer-left'>Backdoor Scanner v2.0.0 &copy; " . date('Y') . "</div>
</div>";
?>