# VM100 (Windows 7): периодические разрывы RDP — итоговый план

## 1. Симптом

VM100 каждые 3–5 минут разрывает RDP-сессию пользователя с ошибкой:

> Не удается завершить требуемую операцию, поскольку служба удаленных рабочих столов сейчас занята. Повторите попытку через несколько минут. Другие пользователи должны по-прежнему иметь возможность входа.

## 2. Ревизия исходных выводов

### 2.1. Главная ошибка: нейтрализован не тот файл

| Что запускается | Что заменено пустым скриптом |
|---|---|
| `HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce\zzInitDisk50` → `wscript.exe C:\initdisk.vbs` | `C:\Users\user\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\initdisk.vbs` |

Это разные файлы. Тест «заменили скрипт, разрывы продолжились» **ничего не доказывает** — гипотеза про RunOnce не опровергнута, а не проверена.

### 2.2. Что подтверждено, а что нет

| Исходное утверждение | Оценка |
|---|---|
| RunOnce срабатывает каждые 3–5 минут | Штатно невозможно: значение RunOnce удаляется при запуске. Значит, запись кто-то пересоздаёт, либо каждые 3–5 минут происходит новый вход или перезагрузка |
| RunOnce срабатывает при каждом подключении RDP | Переподключение к существующему сеансу не является новым входом и RunOnce не запускает |
| VBS через NTVDM «отбирает консоль» | NTVDM не переключает сеансы. `wscript.exe` сам по себе NTVDM не требует. На **x64** Windows 7 NTVDM отсутствует — тогда вся ветка про DOS отпадает |
| Изменение времени IO.SYS/MSDOS.SYS доказывает работу NTVDM | Показывает факт изменения файлов, но не процесс, который их изменил |
| Ошибка «службы заняты» = захват консольной сессии | Не единственное объяснение. Кандидаты: (а) переключение/захват сеанса — автологон, `tscon`, задание планировщика; (б) сбой службы профилей `ProfSvc` (известная проблема Win7 SP1 / 2008 R2) |

### 2.3. Рабочие гипотезы по приоритету

1. **Цикл перезагрузок** (BSOD, watchdog, запланированный `shutdown -r`) + автологон после каждого старта.
2. **Цикл входов**: AutoAdminLogon, скрипт или задание, повторно создающие вход/переносящие сеанс (`tscon ... /dest:console`).
3. **Пересоздание `zzInitDisk50`** каким-либо скриптом, заданием или GPO.
4. **Сбой `ProfSvc`** — если переключение сеанса не подтвердится.
5. **Побочный эффект `/root/watch100.sh`** — если скрипт не только снимает экран, но и отправляет клавиши или выполняет вход.

## 3. Принципы работы

- Сначала собрать доказательства **только чтением**, потом менять.
- Изменения вносить **строго по одному**, с наблюдением 30–60 минут после каждого. Иначе невозможно понять, что именно помогло.
- Перед каждым изменением — экспорт/резервная копия.
- Живой куст `SOFTWARE` через SMB **не заменять**: sharing violation ожидаем, куст занят системой.
- Диск работающей VM снаружи **не изменять**.

## 4. Этап 1 — диагностика без изменений

### 4.1. Внутри VM100 (cmd от имени администратора)

```cmd
mkdir C:\VM100-Diag

:: разрядность и время последней загрузки (перезагрузка или цикл входов)
wmic os get OSArchitecture,LastBootUpTime

:: что реально запускается
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce"
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run"
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce"
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"
reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"

:: содержимое скриптов (type читает, не исполняет)
type C:\initdisk.vbs
type "C:\Users\user\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\initdisk.vbs"

:: кто ещё упоминает запись и скрипт
findstr /s /i /m "zzInitDisk50 initdisk" C:\*.vbs C:\*.cmd C:\*.bat C:\*.js 2>nul

:: задания планировщика
schtasks /query /fo LIST /v > C:\VM100-Diag\tasks.txt
dir /s /b C:\Windows\System32\Tasks > C:\VM100-Diag\tasks-list.txt

:: журналы
wevtutil epl "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" C:\VM100-Diag\LSM.evtx
wevtutil epl "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational" C:\VM100-Diag\RCM.evtx
wevtutil epl Security C:\VM100-Diag\Security.evtx
wevtutil epl System C:\VM100-Diag\System.evtx
wevtutil epl Application C:\VM100-Diag\Application.evtx
```

Если `OSArchitecture` = `64-bit`, дополнительно проверить 32-разрядное представление реестра:

```cmd
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce" /reg:32
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /reg:32
```

**В Winlogon смотреть:** `AutoAdminLogon`, `DefaultUserName`, `ForceAutoLogon`, `Shell`, `Userinit`.

**В `initdisk.vbs`, заданиях и найденных скриптах искать:** `tscon`, `logoff`, `shutdown`, `mstsc`, `RegWrite` с `RunOnce`, запуск других скриптов, создание заданий.

### 4.2. На хосте виртуализации

```bash
cat /root/watch100.sh
```

Убедиться, что скрипт **только** снимает изображение/OCR и не использует `sendkey`, `qm sendkey`, `monitor`-команды ввода, не выполняет автоматический вход и не запускает другие управляющие команды. Сверить время запусков скрипта со временем разрывов.

### 4.3. Запасной путь, если попасть внутрь гостя нельзя

Резервная копия VM → штатное выключение VM100 → работа с диском офлайн через libguestfs (SMB не участвует).

`<disk>` — путь к диску VM100 (например `/dev/pve/vm-100-disk-0`, `/dev/zvol/...` или `.qcow2`-файл, зависит от хранилища).

```bash
export LIBGUESTFS_BACKEND=direct

# чтение реестра
virt-win-reg <disk> 'HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce'
virt-win-reg <disk> 'HKLM\Software\Microsoft\Windows\CurrentVersion\Run'
virt-win-reg <disk> 'HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon'

# журналы, скрипт и задания — только чтение
mkdir -p /mnt/vm100 /root/vm100-diag
guestmount -a <disk> -i --ro /mnt/vm100
cp /mnt/vm100/Windows/System32/winevt/Logs/{System,Security,Application}.evtx /root/vm100-diag/
cp "/mnt/vm100/Windows/System32/winevt/Logs/Microsoft-Windows-TerminalServices-LocalSessionManager%4Operational.evtx" /root/vm100-diag/
cp /mnt/vm100/initdisk.vbs /root/vm100-diag/
cp -r /mnt/vm100/Windows/System32/Tasks /root/vm100-diag/
ls -la /mnt/vm100/Windows/Minidump/ 2>/dev/null
guestunmount /mnt/vm100
```

Разбор EVTX офлайн: `pip install python-evtx`, затем `evtx_dump.py <файл>.evtx`.

## 5. Этап 2 — разбор одного конкретного разрыва

Взять точное время одного разрыва из `/root/console100-watch.log` или со слов пользователя и сопоставить события в окне ±2 минуты.

### 5.1. Ключевые события

| Журнал | Событие | Что даёт |
|---|---|---|
| Security | 4624 | Вход. **Главное поле — LogonType**: 2 = консоль/интерактив, 10 = RDP. Также пользователь, адрес, Logon ID |
| Security | 4634 / 4647 | Завершение сеанса / инициирование выхода |
| Security | 4778 / 4779 | Переподключение / отключение сеанса. В Win7 по умолчанию **не пишутся** — нужен аудит «Другие события входа/выхода» |
| Security | 4688 | Создание процесса (только если включён аудит) |
| Security | 4672 | Специальные привилегии; сам по себе разрыв не объясняет |
| System | 41, 1001, 6008 | Некорректное завершение, BugCheck |
| System | 1074 | Кто инициировал перезагрузку/выключение |
| System | 6005 / 6006 | Запуск / остановка журнала событий (старт/выключение ОС) |
| Application | 1500, 1502, 1530 | Ошибки User Profile Service |
| LSM Operational | 21, 23, 24, 25, 39, 40 | Вход, выход, отключение, переподключение сеанса; 39/40 — кто и почему отключил сеанс |

Сопоставлять не только время, но и **пользователя, Logon ID, Session ID, имя станции и адрес клиента**.

### 5.2. Интерпретация

| Что найдено в момент разрыва | Вывод | Следующий шаг |
|---|---|---|
| `LastBootUpTime` свежий; в System есть 41 / 1001 / 6008 / 1074 | Цикл перезагрузок | Изучить `C:\Windows\Minidump`; у 1074 — инициатора |
| 4624 с LogonType 2 на того же пользователя | Консольный вход: автологон или скрипт | Этап 3, шаг 2 |
| В LSM сеанс отключён другим сеансом (39/40); в заданиях есть `tscon` | Принудительный перенос сеанса | Отключить найденное задание |
| `zzInitDisk50` снова появился после удаления | Запись пересоздаётся | Искать источник: скрипт, задание, GPO |
| Входа нет; в Application ошибки 1500 / 1502 / 1530 | Проблема `ProfSvc` | Сверить версию ОС и обновления с [описанием Microsoft](https://support.microsoft.com/en-us/topic/-remote-desktop-services-is-currently-busy-or-the-group-policy-client-failed-logon-error-when-you-log-on-to-an-application-in-windows-server-2008-r2-ed9f10a8-8bbe-63b6-ed55-67fa5250872c) |
| Время разрывов совпадает с действиями `watch100.sh` | Побочный эффект мониторинга | Остановить скрипт и понаблюдать |

## 6. Этап 3 — изменения строго по одному

После каждого шага — наблюдение 30–60 минут и повторная проверка журналов.

### Шаг 1. Нейтрализовать реально запускаемый скрипт и запись

```cmd
reg export "HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce" C:\VM100-Diag\RunOnce-before.reg
copy C:\initdisk.vbs C:\VM100-Diag\initdisk.vbs.bak
reg delete "HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce" /v zzInitDisk50 /f
```

- Удалять **только после успешного экспорта**.
- Если запись найдена в 32-разрядном представлении — выполнять `reg export` и `reg delete` с `/reg:32`.
- Ранее положенный пустой `initdisk.vbs` в папке Startup убрать (сохранив копию) — это лишняя переменная.

Проверить: не появилась ли запись снова; повторяются ли разрывы; не запускается ли `C:\initdisk.vbs` из другого места.

### Шаг 2. Только если разрывы продолжились и 4624 LogonType 2 подтверждён — отключить автологон

```cmd
reg export "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" C:\VM100-Diag\Winlogon-before.reg
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 0 /f
```

### Шаг 3. По результатам этапа 2

- Найдено задание с `tscon` / `logoff` / `shutdown` → отключить именно его (`schtasks /change /tn "<имя>" /disable`), предварительно экспортировав (`schtasks /query /tn "<имя>" /xml > C:\VM100-Diag\task.xml`).
- Цикл перезагрузок → разбор minidump и источника 1074.
- Признаки `ProfSvc` → проверка версии и обновлений, без немедленной установки старых hotfix.

### Офлайн-вариант шагов 1–2 (если доступа в гость нет)

Резервная копия → штатное выключение VM100 → на хосте:

```bash
cat > /root/vm100-fix.reg <<'EOF'
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce]
"zzInitDisk50"=-
EOF

virt-win-reg --merge <disk> /root/vm100-fix.reg
```

Автологон офлайн отключать **отдельным** проходом и только после проверки результата шага 1:

```bash
cat > /root/vm100-autologon.reg <<'EOF'
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon]
"AutoAdminLogon"="0"
EOF

virt-win-reg --merge <disk> /root/vm100-autologon.reg
```

## 7. Материалы для окончательного вывода

1. Содержимое `C:\initdisk.vbs`.
2. Содержимое `/root/watch100.sh`.
3. Вывод `wmic os get OSArchitecture,LastBootUpTime`.
4. Точное время одного разрыва.
5. Выгруженные `LSM.evtx`, `Security.evtx`, `System.evtx`, `Application.evtx`.

## 8. Кратко

1. Пустой скрипт положен не по тому пути — текущий тест ничего не доказывает.
2. RunOnce с интервалом 3–5 минут штатно не объясняется: реальный драйвер, скорее всего, — повторяющийся вход или перезагрузка (автологон, задание, BSOD). Запасной кандидат — `ProfSvc`.
3. Порядок: прочитать скрипт, аптайм и 4624 с LogonType → удалить `zzInitDisk50` с экспортом → при необходимости отключить AutoAdminLogon. Каждый шаг отдельно, с наблюдением.
