| Server IP : 152.53.162.115 / Your IP : 216.73.217.85 Web Server : Apache/2 System : Linux host 6.12.0-55.40.1.el10_0.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Oct 21 05:54:51 EDT 2025 x86_64 User : pbshosting ( 1005) PHP Version : 8.3.30 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/pbshosting/domains/hengxinae.com/private_html/ |
Upload File : |
<?php
/**
* WordPress malware scanner / cleaner
*
* Place this file in the WordPress root (same folder as wp-config.php).
*
* Infected sites often 403 this filename because malware .htaccess denies
* unknown *.php files. If you see Forbidden, upload this same file as:
* ext.php
* then open: https://your-site.example/ext.php
*
* The scan runs on load. Use the red button to delete matches.
*
* Matched from samples in malware-effected-wp:
* - Obfuscated index.php (Japanese labels / goto)
* - Duplicate trees: wp-admin__*, wp-content__*, wp-includes__*
* - Backdoors: lock360.php, radio.php, panel.php, L86Rgr eval loaders
* - Malicious .htaccess FilesMatch allow-lists
*
* Delete this file after cleanup.
*/
declare(strict_types=1);
define('CLEANER_SELF', basename(__FILE__));
@ini_set('display_errors', '1');
@ini_set('max_execution_time', '0');
@ini_set('memory_limit', '512M');
@set_time_limit(0);
$ROOT = realpath(__DIR__);
if ($ROOT === false) {
$ROOT = __DIR__;
}
$is_cli = (PHP_SAPI === 'cli');
if (!$is_cli) {
session_start();
}
function h(string $s): string
{
return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
function csrf_token(): string
{
if (empty($_SESSION['wp_mc_csrf'])) {
$_SESSION['wp_mc_csrf'] = bin2hex(random_bytes(16));
}
return $_SESSION['wp_mc_csrf'];
}
function csrf_ok(): bool
{
return isset($_POST['csrf']) && hash_equals(csrf_token(), (string) $_POST['csrf']);
}
function rel_path(string $root, string $path): string
{
$root = rtrim(str_replace('\\', '/', $root), '/');
$path = str_replace('\\', '/', $path);
if (strpos($path, $root) === 0) {
$rel = substr($path, strlen($root));
return $rel === '' ? '/' : $rel;
}
return $path;
}
function skip_path(string $root, string $path): bool
{
$rel = rel_path($root, $path);
$base = basename($path);
if ($base === CLEANER_SELF) {
return true;
}
$skip = array(
'/malware-effected-wp',
'/wp-content/cache',
'/wp-content/upgrade',
'/.git',
'/node_modules',
);
foreach ($skip as $prefix) {
if ($rel === $prefix || strpos($rel, $prefix . '/') === 0) {
return true;
}
}
return false;
}
function protected_core_file(string $rel): bool
{
$protected = array(
'/wp-config.php',
'/wp-config-sample.php',
'/wp-load.php',
'/wp-blog-header.php',
'/xmlrpc.php',
'/wp-cron.php',
'/wp-settings.php',
'/wp-links-opml.php',
'/wp-mail.php',
'/wp-activate.php',
'/wp-comments-post.php',
'/wp-signup.php',
'/wp-login.php',
'/wp-trackback.php',
'/license.txt',
'/readme.html',
);
if (in_array($rel, $protected, true)) {
return true;
}
if (strpos($rel, '/wp-admin/') === 0 || strpos($rel, '/wp-includes/') === 0) {
return true;
}
return false;
}
function default_wp_index_php(): string
{
return <<<'PHP'
<?php
/**
* Front to the WordPress application. This file doesn't do anything, but loads
* wp-blog-header.php which does and tells WordPress to load the theme.
*
* @package WordPress
*/
/**
* Tells WordPress to load the WordPress theme and output it.
*
* @var bool
*/
define( 'WP_USE_THEMES', true );
/** Loads the WordPress Environment and Template */
require __DIR__ . '/wp-blog-header.php';
PHP;
}
function default_silence_index(): string
{
return "<?php\n// Silence is golden.\n";
}
function default_wp_htaccess(): string
{
return <<<'HTA'
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
HTA;
}
function read_head(string $path, int $bytes = 16384): string
{
$fh = @fopen($path, 'rb');
if (!$fh) {
return '';
}
$data = fread($fh, $bytes);
fclose($fh);
return is_string($data) ? $data : '';
}
function looks_like_malicious_htaccess(string $content): bool
{
if (stripos($content, 'lock360.php') !== false) {
return true;
}
if (stripos($content, 'wp-l0gin.php') !== false) {
return true;
}
if (preg_match('/<FilesMatch\s+"\.\(py\|exe\|php\)\$"/i', $content)) {
return true;
}
return false;
}
function content_malware_reason(string $content, string $basename): ?string
{
if ($content === '') {
return null;
}
$needles = array(
'goto スタート' => 'obfuscated index (Japanese goto)',
'関数群' => 'obfuscated PHP function block',
'function 문자열(' => 'obfuscated string builder',
'$L86Rgr' => 'eval/preg_replace loader',
'serialize(/****/@eval' => 'eval/preg_replace loader',
'a8c3f0d9ad1f23e06f3b6c1a72f3619b' => 'known backdoor hash',
'$O00OO_0_O_=urldecode' => 'hex-obfuscated dropper',
'c.lo62.xyz' => 'C2 host lo62.xyz',
'c2.icw7.com' => 'C2 host icw7.com',
'51la.lo61.xyz' => 'C2 host lo61.xyz',
'51la.vo4.xyz' => 'C2 host vo4.xyz',
'drsomanathcp.com' => 'C2 / panel host',
'lock360.php' => 'lock360 backdoor reference',
);
foreach ($needles as $needle => $reason) {
if (strpos($content, $needle) !== false) {
return $reason;
}
}
if (looks_like_malicious_htaccess($content) && strtolower($basename) === '.htaccess') {
return 'malicious .htaccess FilesMatch';
}
return null;
}
function looks_like_original_php(string $tail): bool
{
$tail = ltrim($tail);
if (strlen($tail) < 20 || strpos($tail, '<?php') !== 0) {
return false;
}
if (content_malware_reason(substr($tail, 0, 20000), 'kept.php')) {
return false;
}
$markers = array(
'@package WordPress',
"define( 'WP_USE_THEMES'",
'define("WP_USE_THEMES"',
'Silence is golden',
'Plugin Name:',
'Theme Name:',
'wp-blog-header.php',
'wp-load.php',
'ABSPATH',
);
foreach ($markers as $marker) {
if (stripos($tail, $marker) !== false) {
return true;
}
}
return strlen($tail) > 80;
}
/**
* Keep original PHP after a prepended malware block (e.g. index.php lines 1–251).
*/
function extract_clean_php(string $content): ?string
{
if ($content === '' || content_malware_reason(substr($content, 0, 20000), 'scan.php') === null) {
return null;
}
if (preg_match_all('/\?>\s*(<\?php[\s\S]*)/s', $content, $matches)) {
for ($i = count($matches[1]) - 1; $i >= 0; $i--) {
$tail = $matches[1][$i];
$prefix = substr($content, 0, -strlen($tail));
if (content_malware_reason(substr($prefix, 0, 20000), 'scan.php') && looks_like_original_php($tail)) {
return rtrim($tail) . "\n";
}
}
}
if (strpos($content, '$O00OO_0_O_=urldecode') !== false && stripos($content, 'Silence is golden') !== false) {
return default_silence_index();
}
foreach (array(' * @package WordPress', "define( 'WP_USE_THEMES'") as $mark) {
$pos = strpos($content, $mark);
if ($pos === false) {
continue;
}
$start = strrpos(substr($content, 0, $pos), '<?php');
if ($start === false || $start < 40) {
continue;
}
$tail = substr($content, $start);
$prefix = substr($content, 0, $start);
if (content_malware_reason(substr($prefix, 0, 20000), 'scan.php') && looks_like_original_php($tail)) {
return rtrim($tail) . "\n";
}
}
return null;
}
/**
* Cloned WP copies use a double-underscore + random id.
* The sample used __f01915c; other sites use a different token
* (hex, letters, longer/shorter). Match any such suffix.
*/
function is_clone_suffix_name(string $name): bool
{
// wp-admin__abc123 | index.php__f01915c | license.txt__deadbeef99
return (bool) preg_match(
'/^(?:wp-admin|wp-content|wp-includes|.+\.[a-z0-9]{1,12})__[a-z0-9][a-z0-9_-]{2,31}$/i',
$name
);
}
function name_malware_reason(string $rel, string $basename): ?string
{
$first = explode('/', ltrim($rel, '/'), 2)[0];
if (is_clone_suffix_name($first) || is_clone_suffix_name($basename)) {
if (preg_match('/^(wp-admin|wp-content|wp-includes)__/i', $first)) {
return 'cloned WordPress tree (wp-*__random-suffix)';
}
return 'backup/clone suffix on filename (not limited to __f01915c)';
}
$dropper_names = array(
'lock360.php',
'wp-l0gin.php',
'wp-the1me.php',
'wp-scr1pts.php',
'mah.php',
'jp.php',
'ext.php',
'2index.php',
);
if (in_array(strtolower($basename), $dropper_names, true)) {
return 'known malware filename';
}
if (preg_match('#^/wp-content/uploads/.+\.(php|phtml|phar)$#i', $rel)) {
return 'PHP file inside uploads';
}
if (preg_match('#^/[0-9a-f]{6,16}(/|$)#i', $rel)) {
return 'random hex folder at site root';
}
return null;
}
function scan_tree(string $root): array
{
$hits = array();
$seen_dirs = array();
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $item) {
$path = $item->getPathname();
if (skip_path($root, $path)) {
continue;
}
$rel = rel_path($root, $path);
$base = $item->getBasename();
$name_reason = name_malware_reason($rel, $base);
if ($item->isDir()) {
if ($name_reason) {
$top = $rel;
// collapse to top-level cloned dir / hex folder
if (preg_match('#^/[^/]+__[a-z0-9][a-z0-9_-]{2,31}#i', $rel, $m)) {
$top = $m[0];
} elseif (preg_match('#^/[0-9a-f]{6,16}#i', $rel, $m)) {
$top = $m[0];
}
if (!isset($seen_dirs[$top])) {
$seen_dirs[$top] = true;
$hits[] = array(
'path' => $root . $top,
'rel' => $top,
'type' => 'dir',
'reason' => $name_reason,
'action' => 'delete',
);
}
}
continue;
}
if (!$item->isFile()) {
continue;
}
// Skip files already covered by a deleted parent folder hit
$covered = false;
foreach ($seen_dirs as $dir => $_) {
if (strpos($rel, $dir . '/') === 0) {
$covered = true;
break;
}
}
if ($covered) {
continue;
}
$ext = strtolower(pathinfo($base, PATHINFO_EXTENSION));
$scan_ext = in_array($ext, array('php', 'phtml', 'php5', 'phar', 'htaccess', 'js', 'html', 'htm', 'txt'), true)
|| $base === '.htaccess'
|| preg_match('/\.(php|html|js)__[a-z0-9]+$/i', $base);
$head = $scan_ext ? read_head($path) : '';
$reason = $name_reason;
if (!$reason && $scan_ext) {
$reason = content_malware_reason($head, $base);
}
if (!$reason) {
continue;
}
$action = 'delete';
$full = ($scan_ext && $reason) ? @file_get_contents($path) : false;
$can_strip = is_string($full) && extract_clean_php($full) !== null && !is_clone_suffix_name($base);
if ($can_strip) {
$action = 'strip-inject';
} elseif ($rel === '/.htaccess') {
$action = 'restore-htaccess';
} elseif ($rel === '/index.php') {
$action = 'restore-index';
} elseif ($base === 'index.php' && !protected_core_file($rel) && strpos($head, 'Silence is golden') !== false) {
$action = 'restore-silence';
} elseif (protected_core_file($rel)) {
$action = 'flag-core';
}
$hits[] = array(
'path' => $path,
'rel' => $rel,
'type' => 'file',
'reason' => $reason,
'action' => $action,
);
}
usort($hits, function ($a, $b) {
return strcmp($a['rel'], $b['rel']);
});
return $hits;
}
function rrmdir(string $dir): bool
{
if (!is_dir($dir)) {
return false;
}
$items = scandir($dir);
if ($items === false) {
return false;
}
foreach ($items as $item) {
if ($item === '.' || $item === '..') {
continue;
}
$path = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($path) && !is_link($path)) {
rrmdir($path);
} else {
@unlink($path);
}
}
return @rmdir($dir);
}
function apply_hit(array $hit, string $root): array
{
$path = $hit['path'];
$real = realpath($path);
$root_real = realpath($root);
if ($real && $root_real && strpos($real, $root_real) !== 0) {
return array('ok' => false, 'msg' => 'Path escaped root');
}
if (basename($path) === CLEANER_SELF) {
return array('ok' => false, 'msg' => 'Refused to touch cleaner');
}
switch ($hit['action']) {
case 'delete':
if (is_dir($path)) {
$ok = rrmdir($path);
return array('ok' => $ok, 'msg' => $ok ? 'Folder deleted' : 'Failed to delete folder');
}
$ok = @unlink($path);
return array('ok' => $ok, 'msg' => $ok ? 'File deleted' : 'Failed to delete file');
case 'restore-index':
$ok = @file_put_contents($path, default_wp_index_php()) !== false;
return array('ok' => $ok, 'msg' => $ok ? 'Restored default WordPress index.php' : 'Failed to restore index.php');
case 'restore-htaccess':
$ok = @file_put_contents($path, default_wp_htaccess()) !== false;
return array('ok' => $ok, 'msg' => $ok ? 'Restored default WordPress .htaccess' : 'Failed to restore .htaccess');
case 'restore-silence':
$ok = @file_put_contents($path, default_silence_index()) !== false;
return array('ok' => $ok, 'msg' => $ok ? 'Restored silence index.php' : 'Failed to restore index.php');
case 'strip-inject':
$full = @file_get_contents($path);
$clean = is_string($full) ? extract_clean_php($full) : null;
if ($clean === null) {
return array('ok' => false, 'msg' => 'Could not separate original code from malware');
}
$ok = @file_put_contents($path, $clean) !== false;
return array('ok' => $ok, 'msg' => $ok ? 'Removed injected malware, kept original PHP' : 'Failed to write cleaned file');
case 'flag-core':
return array(
'ok' => false,
'msg' => 'Core file flagged only — reinstall WordPress core instead of deleting',
);
default:
return array('ok' => false, 'msg' => 'Unknown action');
}
}
if (PHP_SAPI === 'cli') {
$cli_root = $ROOT;
$do_delete = in_array('--delete', $argv, true);
foreach ($argv as $i => $arg) {
if ($arg === '--root' && isset($argv[$i + 1])) {
$cli_root = realpath($argv[$i + 1]) ?: $argv[$i + 1];
}
}
$hits = scan_tree($cli_root);
fwrite(STDOUT, 'Scanned ' . $cli_root . ' — ' . count($hits) . " items\n");
foreach ($hits as $hit) {
fwrite(STDOUT, sprintf("[%s] %s (%s) %s\n", $hit['action'], $hit['rel'], $hit['type'], $hit['reason']));
}
if ($do_delete) {
foreach ($hits as $hit) {
if ($hit['action'] === 'flag-core') {
fwrite(STDOUT, 'SKIP core ' . $hit['rel'] . "\n");
continue;
}
$out = apply_hit($hit, $cli_root);
fwrite(STDOUT, ($out['ok'] ? 'OK ' : 'FAIL ') . $hit['rel'] . ' — ' . $out['msg'] . "\n");
}
}
exit(0);
}
$error = '';
$notice = '';
$hits = null;
$results = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!csrf_ok()) {
$error = 'Security check failed. Reload the page and try again.';
} elseif (isset($_POST['delete'])) {
$hits = $_SESSION['wp_mc_hits'] ?? scan_tree($ROOT);
$results = array();
foreach ($hits as $hit) {
if ($hit['action'] === 'flag-core') {
$results[] = $hit + array('ok' => false, 'msg' => 'Skipped (WordPress core — replace from a clean WP zip)');
continue;
}
$out = apply_hit($hit, $ROOT);
$results[] = $hit + $out;
}
unset($_SESSION['wp_mc_hits']);
$notice = 'Cleanup finished. Reload to scan again, then delete ' . CLEANER_SELF . '.';
$hits = null;
} else {
$hits = scan_tree($ROOT);
$_SESSION['wp_mc_hits'] = $hits;
}
} else {
$hits = scan_tree($ROOT);
$_SESSION['wp_mc_hits'] = $hits;
}
header('Content-Type: text/html; charset=utf-8');
header('X-Robots-Tag: noindex, nofollow');
header('Cache-Control: no-store');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WP malware cleaner</title>
<style>
:root { font-family: ui-sans-serif, system-ui, sans-serif; color: #0f172a; background: #f1f5f9; }
body { max-width: 1100px; margin: 32px auto; padding: 0 16px; }
.card { background: #fff; border-radius: 12px; padding: 24px; box-shadow: 0 1px 3px rgba(0,0,0,.08); }
h1 { margin: 0 0 8px; font-size: 1.4rem; }
p.muted { color: #64748b; margin-top: 0; }
.err { background: #fef2f2; color: #991b1b; padding: 10px 12px; border-radius: 8px; }
.ok { background: #ecfdf5; color: #065f46; padding: 10px 12px; border-radius: 8px; }
.warn { background: #fffbeb; color: #92400e; padding: 10px 12px; border-radius: 8px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: left; padding: 8px 6px; border-bottom: 1px solid #e2e8f0; vertical-align: top; }
code { font-size: 12px; }
.btn { display: inline-block; border: 0; border-radius: 8px; padding: 10px 16px; font-weight: 600; cursor: pointer; }
.btn-scan { background: #2563eb; color: #fff; }
.btn-del { background: #dc2626; color: #fff; }
.btn-ghost { background: #e2e8f0; color: #0f172a; text-decoration: none; padding: 10px 16px; border-radius: 8px; }
input[type=password] { width: 100%; max-width: 360px; padding: 10px; border: 1px solid #cbd5e1; border-radius: 8px; }
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 16px 0; }
.tag { display: inline-block; font-size: 11px; padding: 2px 8px; border-radius: 999px; background: #e2e8f0; }
.tag-del { background: #fee2e2; color: #991b1b; }
.tag-fix { background: #dbeafe; color: #1e40af; }
.tag-skip { background: #fef3c7; color: #92400e; }
</style>
</head>
<body>
<div class="card">
<h1>WordPress malware cleaner</h1>
<p class="muted">Root: <code><?php echo h($ROOT); ?></code></p>
<?php if ($error) : ?>
<p class="err"><?php echo h($error); ?></p>
<?php endif; ?>
<?php if ($notice) : ?>
<p class="ok"><?php echo h($notice); ?></p>
<?php endif; ?>
<div class="row">
<form method="post">
<input type="hidden" name="csrf" value="<?php echo h(csrf_token()); ?>">
<button class="btn btn-scan" type="submit" name="scan" value="1">Scan again</button>
</form>
<?php if (is_array($hits) && count($hits) > 0) : ?>
<form method="post" onsubmit="return confirm('Delete / restore all listed malware items? This cannot be undone.');">
<input type="hidden" name="csrf" value="<?php echo h(csrf_token()); ?>">
<button class="btn btn-del" type="submit" name="delete" value="1">Delete all affected files & folders</button>
</form>
<?php endif; ?>
</div>
<p class="warn">
If this page 403s, the malware <code>.htaccess</code> is blocking extra PHP files. Rename this script to
<code>ext.php</code> (that name is on the infection allow-list) and open <code>/ext.php</code>.
Infected core files under <code>wp-admin</code> / <code>wp-includes</code> are listed but not deleted.
If malware is prepended onto real WordPress code (like root <code>index.php</code>), that injection is stripped
and the original PHP is kept. Clone folders and pure backdoors are deleted. Malicious <code>.htaccess</code>
is restored. Delete this cleaner when you are done.
</p>
<?php if (is_array($results)) : ?>
<h2>Cleanup results (<?php echo count($results); ?>)</h2>
<table>
<thead>
<tr><th>Path</th><th>Result</th></tr>
</thead>
<tbody>
<?php foreach ($results as $row) : ?>
<tr>
<td><code><?php echo h($row['rel']); ?></code></td>
<td><?php echo $row['ok'] ? '✓ ' : '• '; echo h($row['msg']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php elseif (is_array($hits)) : ?>
<h2>Scan results (<?php echo count($hits); ?>)</h2>
<?php if (count($hits) === 0) : ?>
<p class="ok">No matching malware signatures from the sample set.</p>
<?php else : ?>
<table>
<thead>
<tr><th>Path</th><th>Why</th><th>Action</th></tr>
</thead>
<tbody>
<?php foreach ($hits as $hit) : ?>
<tr>
<td><code><?php echo h($hit['rel']); ?></code><br><span class="tag"><?php echo h($hit['type']); ?></span></td>
<td><?php echo h($hit['reason']); ?></td>
<td>
<?php
$cls = 'tag-del';
$label = $hit['action'];
if ($hit['action'] === 'flag-core') {
$cls = 'tag-skip';
} elseif (strpos($hit['action'], 'restore') === 0 || $hit['action'] === 'strip-inject') {
$cls = 'tag-fix';
}
?>
<span class="tag <?php echo $cls; ?>"><?php echo h($label); ?></span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<?php endif; ?>
</div>
</body>
</html>