HEX
Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/8.4.25
System: Windows NT DESKTOP-4TAV2RJ 10.0 build 19045 (Windows 10) AMD64
User: fred (0)
PHP: 8.4.25
Disabled: NONE
Upload Files
File: C:/xampp/cleanup_ushort.php
<?php

$root = 'C:/xampp/htdocs';
$execute = in_array('--execute', $argv, true);
$targetPath = null;

foreach ($argv as $arg) {
    if (strpos($arg, '--path=') === 0) {
        $targetPath = substr($arg, 7);
    }
}

function cleanMalware(string $content): string
{
    $patterns = [
        '#\s*<script>\s*const isMobile = .*?window\.location\.(?:replace|href)\(\s*["\"]//(?:https://)?ushort\.observer/EtzysRdms0r1["\"]\s*\);?\s*\}\s*</script>\s*#is',
        '#^[^\S\r\n]*window\.location\.(?:href|replace)\s*=\s*["\"]//https://ushort\.observer/EtzysRdms0r1["\"];?[^\r\n]*(?:\r?\n)?#mi',
        '#^[^\S\r\n]*window\.location\.(?:href|replace)\s*=\s*["\"]//ushort\.observer/EtzysRdms0r1["\"];?[^\r\n]*(?:\r?\n)?#mi',
        '#^[^\S\r\n]*window\.location\.(?:href|replace)\(\s*["\"]//(?:https://)?ushort\.observer/EtzysRdms0r1["\"]\s*\);?[^\r\n]*(?:\r?\n)?#mi',
        '#^[^\r\n]*ushort\.observer[^\r\n]*(?:\r?\n)?#mi',
    ];

    $cleaned = $content;
    foreach ($patterns as $pattern) {
        $cleaned = preg_replace($pattern, '', $cleaned);
    }

    return $cleaned;
}

function candidateFiles(string $root, ?string $targetPath): iterable
{
    if ($targetPath !== null) {
        yield $targetPath;
        return;
    }

    $extensions = ['php', 'js', 'html', 'asp', 'aspx'];
    $directory = new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS);
    $iterator = new RecursiveIteratorIterator($directory);

    foreach ($iterator as $fileInfo) {
        if (!$fileInfo->isFile()) {
            continue;
        }

        $extension = strtolower($fileInfo->getExtension());
        if (!in_array($extension, $extensions, true)) {
            continue;
        }

        yield $fileInfo->getPathname();
    }
}

$matched = 0;
$changed = 0;
$unchanged = 0;
$errors = [];

foreach (candidateFiles($root, $targetPath) as $path) {
    $content = @file_get_contents($path);
    if ($content === false) {
        $errors[] = "READ $path";
        continue;
    }

    if (stripos($content, 'ushort.observer') === false) {
        continue;
    }

    $matched++;
    $cleaned = cleanMalware($content);

    if ($cleaned === $content) {
        $unchanged++;
        echo "UNCHANGED $path\n";
        continue;
    }

    if ($execute) {
        $written = @file_put_contents($path, $cleaned);
        if ($written === false) {
            $errors[] = "WRITE $path";
            continue;
        }

        $verify = @file_get_contents($path);
        if ($verify === false) {
            $errors[] = "VERIFY $path";
            continue;
        }

        if (stripos($verify, 'ushort.observer') !== false) {
            $errors[] = "REMAINING $path";
            continue;
        }
    }

    $changed++;
    echo ($execute ? 'CLEANED ' : 'WOULD_CLEAN ') . $path . "\n";
}

echo "SUMMARY matched=$matched changed=$changed unchanged=$unchanged errors=" . count($errors) . " mode=" . ($execute ? 'execute' : 'dry-run') . "\n";
foreach ($errors as $error) {
    echo "ERROR $error\n";
}