# KZ система за борба с измамите
**Система за откриване на измама чрез манипулиране на движението за сървърите на KZ за Counter-Strike 1.6**
Автор: **illusion @ CodeStrike** · [codestrike.store](https://codestrike.store)
---
## Какво открива
| Детектор | Улови |
|---|---|
| `BUNNYHOP` | автоматичен „бънихоп“, скриптове за скокове, `+jump`макро цикли |
| `GROUNDSTRAFE` | Скриптове GS и SGS, включително варианти, които никога не се докосват `+duck` |
| `STRAFE-STABILIZER` | оптимизатори за въздушни стрелби / хакове за „перфектна стрелба“ |
| `PRESTRAFE-STABILIZER` | оптимизатори за обстрел на наземни цели (експериментални, изключени по подразбиране) |
| `INPUT-ANOMALY` | speedhack и манипулиране на часовника на клиента |
---
## Идеята
Движението на играчите в GoldSrc е напълно детерминистично. При всеки тик сървърът получава
usercmd — бутони, милисекунди, движение напред, движение настрани, ъгли на видимост — и изпълнява
`PM_Friction`, `PM_Accelerate`, и`PM_AirAccelerate` върху`PM_Jump` него.
Този плъгин препрограмира тази математика. За всеки отделен тик той знае не само
не това, което е направил двигателят, а **това, което би се получило при най-добрия възможен вход**.
`PM_AirAccelerate` добавя `min(K, 30 − dot(v, wishdir)) · wishdir`към скоростта,
с `K = sv_airaccelerate · wishspeed · frametime`. Максимизиране на това по отношение на
Свободно избраното отклонение има затворен вид:
```
Δv_max = √(v² + wishspd² − max(0, wishspd − K)²) − v
```
Всичко се извлича от това и от cvars на сървъра на живо. Нищо не е
магическо число, измислено от нищото.
### Защо това е важно за airaccelerate
Един и същ трик се проявява напълно различно в зависимост от `sv_airaccelerate`,
затова един-единствен фиксиран праг не може да сработи:
| | `sv_airaccelerate 10` | `sv_airaccelerate 100` |
|---|---|---|
| K при 250 u/s, 100 fps | 25 | 250 |
| оптимален `dot(v, wishdir)` | 5 | 0 |
| ъгъл на наблюдение, който трябва да се запази | 88.9° | 90° |
| диапазон за ефективност ≥0,90 | **±0.85°** | **±2.2°** |
Стабилизаторът, написан за сървър с 100 AA, е насочен перпендикулярно, което е точно
там е оптимално — а на сървър с 10 AA има отклонение от 1,1°, където след това печалбата е *по-малка*
отколкото един добър човек. Всеки праг в този плъгин се интерполира между
Стойностите 10 AA и 100 AA се определят чрез cvar в реално време, така че и двете се оценяват правилно.
Същият принцип важи и за FPS. Всички времена за стрелба при движение по земя се измерват в
**милисекунди по часовника**, никога в тикове, защото 25 тика са 250 ms при
100 кадъра в секунда и 27 милисекунди при 940 кадъра в секунда.
---
## Инсталиране
1. Копирай в`kz_anticheat.amxx` `cstrike/addons/amxmodx/plugins/`
2. Добавете този ред към`cstrike/addons/amxmodx/configs/plugins.ini`:
```
kz_anticheat.amxx
```
3. Сменете картата или рестартирайте сървъра.
При първото зареждане плъгинът създава и изпълнява:
```
addons/amxmodx/configs/CodeStrikePlugins/kz_anticheat.cfg
```
Този файл се генерира **еднократно** въз основа на собствените настройки по подразбиране на плъгина и никога не се
отново е презаписан. Изтрийте го, за да го генерирате отново. Всичко се конфигурира от
Ето — никога не се налага да се редактира или прекомпилира някой изходен файл.
В конзолата на сървъра ще видите банер, потвърждаващ зареждането и движението
cvars, които е прочел, и максималната скорост преди наказанието, която е изчислил въз основа на тях.
---
## Първите пет минути на нов сървър
```
kzac_physics
```
Изпълнете това преди всичко останало. То извежда модела на движение на приставката
изчислено. **Ако посоченият от него таван за престрафе не съвпада с това, което вашите играчи
всъщност достига (обикновено ~278 u/s), вашите CVAR-и за движение не са тези, които плъгинът
е четенето, и нищо друго няма да е наред.**
```
kzac_diag
```
Потвърждава, че куките за придвижване са активни. `ticks processed`Трябва да се изкачва, докато
някой се мести.
---
## Административни команди
Всички изискват флаг **`c`**(`ADMIN_KICK`).
Букви от флага на AMXX: `a`имунитет · `b`резервация · **`c`**изгонване · `d`забрана ·
`e` slay · `f`map · `g`cvar · `l`rcon.
| Команда | Цел |
|---|---|
| `kzac_stats <target>` | всички показатели, които плъгинът съхранява за един играч |
| `kzac_watch <цел\|изключено>` | телеметрия в реално време във вашата конзола |
| `kzac_physics` | полученият модел на движението и всички прагове на активност |
| `kzac_diag` | задействат ли се куките за движение и кой гвардиан изхвърля тикове |
| `kzac_reset <target>` | изтриване на натрупаните доказателства за един играч |
`kzac_stats` това е най-важното. Всяко откриване може да бъде проверено ръчно
в сравнение с показаните от него стойности, като всеки детектор показва **пикове** за съответната **сесия**
блок — най-крайните стойности, които този играч е постигнал. Това е, което ти
с което да се сравнява, ако някога се наложи да промените праговата стойност.
---
## Конфигурация
### Обявления
```
kzac_announce_mode 1 // 0 = silent, 1 = admins only, 2 = everyone
kzac_announce_flag "c" // flag required to see them in mode 1
```
Режим **1 е зададен по подразбиране умишлено**. По подразбиране флагът е `c`(`ADMIN_KICK`),
същата, която се изисква за административните команди, така че всеки, който може да разследва
разкриването също показва, че това се случва. Публичното обвинение не може да бъде оттеглено,
и нито една система за борба с измамите не е съвършена. Изходът към конзолата и файлът с логове винаги се записват
независимо от тази настройка.
### Наказание
```
kzac_punish_bhop 0 // 0 = nothing, 1 = kick, 2 = ban
kzac_punish_gstrafe 0
kzac_punish_strafe 0
kzac_punish_prestrafe 0
kzac_punish_input 0
kzac_punish_hits 3 // detections of the SAME type before it fires
kzac_ban_minutes 0 // 0 = permanent
```
Всеки детектор съдържа собствен текст с обяснение, така че на забранения играч се посочва какво точно е
действително уловена, а не просто някаква обикновена риба:
```
kzac_reason_bhop "Bunnyhop Cheat Detected"
kzac_reason_gstrafe "Ground Strafe Cheat Detected"
kzac_reason_strafe "Strafe Stabilizer Cheat Detected"
kzac_reason_prestrafe "Prestrafe Stabilizer Cheat Detected"
kzac_reason_input "Speedhack Detected"
kzac_punish_reason "Movement cheat detected" // fallback
```
Оставете едно **празно** и то ще се върне към `kzac_punish_reason`. Изчистете и петте
да се използва един-единствен ред за всичко.
Наказанията са **изключени по подразбиране**. Активирайте ги умишлено и предпочитайте да
започнете с (`1`kick), докато следите показателите на собствения си сървър.
Те са зададени умишлено за всеки детектор поотделно. `BUNNYHOP`и имат`GROUNDSTRAFE`
най-голямото измерено разстояние между ръката и текста — това са най-безопасните
за автоматизиране. `STRAFE-STABILIZER`има най-малките маржове.
### Команда „Ban“
**Цялата команда** е cvar, така че на плъгина не му пука коя система за забрана се използва
изпълняваш — напиши каквото и да очаква твоята програма, в какъвто и ред на аргументите да иска.
```
kzac_ban_cmd amx_ban %n %m %r // default
kzac_kick_cmd amx_kick %n %r // default
```
| | |
|---|---|
| `%m` | продължителност на забраната в минути, `0`= постоянна |
| `%n` | име на играча — **вече е поставено в кавички за вас** |
| `%r` | текстът на обосновката — **вече е цитиран за вас** |
| `%u` | userid, използва се като `#%u` |
| `%s` | steamid |
| `%i` | IP адрес |
| `%N` `%R` | име и причина **без кавички**, ако вашата система за блокиране ги изисква в суров вид |
**Първо проверете собствения си сървър.** Въведете `amx_ban`без аргументи в сървъра
конзолата и извежда очакваното описание на употребата. Редът на аргументите **не** е
еднакво във всички системи за забрана – в някои се изисква първо да се въведе целта, а в други – първо да се въведат минутите.
Ако сгрешите, ще се получи грешка с `Client with that name or userid not found`.
```
amx_ban %n %m %r # target first (default)
amx_ban %m %n %r # minutes first
amx_ban #%u %m %r # by userid
amx_banip %s %m %r # by steamid
banid %m %s ; writeid ; kick # %u # engine level ban
```
Редът на аргументите зависи изцяло от вас — заместителите се разширяват там, където ги поставите,
а няколко команди могат да се свържат с `;`.
### Ако наказанието не бъде наложено
Конзолата винаги извежда точно командата, която е изпълнила:
```
[KZ-AC] executing: amx_kick "illusion" "Bunnyhop Cheat Detected"
```
Ако тази редица се появи и играчът все още е там, това означава, че плъгинът е изпълнил задачата си и
командата е отхвърлена. Обичайната причина е, че **`amx_kick` и не се `amx_ban`съблюдават
Имунитет AMXX** – играч, държащ знамето `a`(`ADMIN_IMMUNITY`), на кой сървър
която собствениците обикновено си поставят, се пренебрегва мълчаливо. Самостоятелно тестване
Следователно акаунтът изглежда точно като неработещ плъгин.
Изпълнете същата команда ръчно в конзолата на сървъра, за да се уверите. Двигателят
командите напълно пренебрегват имунитета:
```
kzac_kick_cmd kick # %u
kzac_ban_cmd banid %m %s ; writeid ; kick # %u
```
Ако `executing:`редът **не** се появи, проверете в конзолата за:
```
[KZ-AC] illusion :: BUNNYHOP held - 1 of 3 detections needed (kzac_punish_hits)
```
Само обявените открития се отчитат`kzac_punish_hits`; тези, които са скрити от
`kzac_cooldown` не.
**Никога не поставяйте сами символ за кавички в тези стойности.** Стойността на cvar завършва с
първата кавичка, която двигателят вижда, така че шаблонът, написан с кавички около
разсъждението би се прекъснало на това място и би изчезнало безшумно. Това е
точно защо и`%n` вече `%r`са посочени.
### Дърводобив
```
kzac_log 1
kzac_log_file "kzac_detections.log"
```
Записано в `addons/amxmodx/logs/`. Резултатите от проверките също винаги се изпращат към стандартния
AMXX лог чрез `log_amx`.
### Чувствителност
```
kzac_min_conf 80.0
```
Необходима е сигурност, преди да се обяви откриване. Повишете я до , за`90` да я поддържате
Само най-строгите правила важат. Ако ги облекчите, ще започнете да виждате спорни решения.
```
kzac_immunity ""
```
Административни сигнали, които никога не се докладват и не се санкционират. „Празно“ означава, че никой не е имунизиран.
---
## Извършените тестове
Тествано срещу **реални читъри**, а не срещу симулации, на активен сървър на KZ:
| Измама | `sv_airaccelerate 10` | `sv_airaccelerate 100` |
|---|---|---|
| Автоматичен „бънихоп“ | открит | открит |
| Скрипт „Bunnyhop“ | открит | открит |
| GS скрипт | открит | открит |
| Скрипт на SGS | открит | открит |
| Стабилизатор за стрелба | открит | открит |
Законната игра беше тествана в същия диапазон — ръчен „бънихоп“ с
колелце за превъртане, ръчно управление на GS и SGS, въздушно обстрелване, предварително обстрелване — при 100 кадъра в секунда и при
1000 кадъра в секунда при двете настройки на AirAccelerate.
### Измерено разстояние
Всеки активен праг се намира между стойност, измерена въз основа на реална човешка игра, и
стойност, измерена от истински измамник на същия сървър:
| Сигнал | Човек | Праг | Измама |
|---|---|---|---|
| `+jump` натискания на скок | 5.26 | 1.20 | 1.00 |
| поредица от перфектни скокове | 3 | 12 | 20–23 |
| идеален скок сподели | 26.6% | 80% | 100% |
| `+duck` удара в секунда | 13.3 | 35.0 | — |
| `+duck` вариация на разстоянието | 0.70–0.88 | 0.10 | — |
| пробиви при нулеви ходове | 3 % (спрямо 9 % вероятност) | 50 % и 3× шанс | 99 % (спрямо 5 %) |
| ефективност на въздушния обстрел, период от 300 тика | 0.583–0.65 | 0.85 | 0.909 |
| вариация на ефективността, прозорец от 300 тика | 0.172 | 0.075 | — |
### Как всъщност изглежда едно истинско наземно обстрелване
Добре е да се знае, защото именно това е причината скоростта сама по себе си никога да не се използва като доказателство:
```
GS spd 324.9->323.2 bound 324.5 | grnd 11 run 6 | z 36.03
GS spd 571.4->569.2 bound n/a | grnd 11 run 1 | z 36.03
+duck edges 102 | +duck held 102 ticks
```
Беше измерена легитимна стойност на GS от **571 u/s при горна граница от 278,7 u/s**. Всяка
`+duck` натискането продължи точно един тик — тоест едно завъртане на колелцето за превъртане. По тиковете
когато играчът наистина е на земята, получената скорост винаги е малко *под*
границата в затворен вид: основните физични принципи остават непроменени. Скоростта произтича от
малките колебания на корпуса, които възникват при всеки преход на „патето“.
Така че детекторът за „groundstrafe“ никога не отчита скоростта. Той отчита входните данни
поток: колко бързо се повтаря`+duck`, колко е равномерен и дали има контакт със земята
се нарушава от команди, които изобщо не съдържат време.
---
## Няма съвършена система срещу измамите
И това също не е така, и трябва да го изпълните, като имате това предвид.
**Възможни са фалшиви положителни резултати.** По време на разработката бяха открити и отстранени шест такива,
всяко от тях произтичаше от различно правило, но всички имаха една и съща основна причина: праг
което изглеждаше логично, но никога не беше тествано в сравнение с човешката игра
в тази конкретна ситуация. Статистическите данни за човешкото движение се променят с airaccelerate,
в зависимост от броя на кадрите в секунда и от действията на играча — движение настрани по земята, „заешки скокове“ и
въздушните атаки дават наистина различни резултати при един и същ човек.
Пет правила бяха **деактивирани,** след като доведоха до фалшиви положителни резултати, и те се доставят
деактивирани. Те все още са в конфигурацията за всеки, който иска да ги разгледа:
`kzac_st_err_aa10`, `kzac_st_err_aa100`, `kzac_st_err_sd`, `kzac_st_inband`.
Какво означава това на практика:
- **Не активирайте автоматичните забрани още от първия ден.** Засега се задоволете с предупреждения
и прочетете какво излиза от вашия собствен сървър.
- **`kzac_stats` преди да предприемете действие.** При всяко откриване се извеждат числата, които стоят зад
това. Ако не изглеждат крайни, третирайте сигнала като незначителен.
- **Детекторът за въздушни атаки е най-несигурният от трите.** Неговите граници
са най-тънките. Предупредете или го изгонете; оставете забраната за „бънихоп“ и
детектори за наземни удари, които са разположени на много по-голямо разстояние един от друг.
- **Използвана само частично измама е по-трудно да бъде разкрита.** Стабилизатор, който играчът
когато се бори със собствените си входни данни, печели по-малко и изглежда по-човечен. Откриване
мащабира се при използване на предимството, което е разумно свойство, но
не е пълна.
- **Може да се напише програма за измама, която да остава под всеки праг**, като умишлено се
по-лошо, отколкото би могло да бъде. В този момент то вече не носи особена полза,
но трябва честно да се каже, че обхватът не е пълен.
Ако даден играч оспори дадено засичане, `kzac_stats`върху него и да се сравни с
измерените човешки ценности в таблицата по-горе. Плъгинът ви предоставя доказателствата, за да
направете тази преценка — то не ви моли да му се доверявате сляпо.
---
## Файлове
```
kz_anticheat.sma main plugin
include/kzac_core.inc movement math, guards, reporting, punishment
include/kzac_bhop.inc bunnyhop detector
include/kzac_gstrafe.inc ground strafe detector
include/kzac_strafe.inc air strafe detector
include/kzac_config.inc config file generator
compiled/kz_anticheat.amxx ready to use
```
За да се стартира плъгинът, `kz_anticheat.amxx`е необходимо само . Изходният код е включен, така че
можете да го проверите или да го разширите.
За да прекомпилирате, поставете петте `kzac_*.inc`файла във вашата `scripting/include/`
папка и компилирайте `kz_anticheat.sma`както обикновено. Компилира се без грешки на AMX Mod X
1.10 **без грешки и без предупреждения**.
---
## Забележки относно сигурността
**Имената на играчите се преобразуват, преди да стигнат до конзолната команда.** Име
ако съдържа цитат или точка и запетая, това би позволило на заловения измамник да изпълни кода
произволни команди към сървъра чрез шаблона за изгонване или блокиране. Кавички, точка и запетая
а контролните символи се заменят с `_`.
**Наказанията никога не се изпълняват в рамките на конвейера на движенията.** Те се поставят в опашката и
изстрелян от задачата един кадър по-късно. Изпълнение на ритник синхронно отвътре
действие за преминаване напред прекъсва връзката на играча по време на обратното извикване и води до срив на сървъра —
това беше открито и отстранено по време на тестването.
---
## Изисквания
- AMX Mod X 1.8.2 или по-нова версия (разработена и компилирана на версия 1.10)
- `fakemeta` модул
- Counter-Strike 1.6 — работи с HLDS, ReHLDS и ReGameDLL
Не се изисква никакъв друг плъгин, модул или зависимост.
---
## Производителност
Един нападател (`FM_CmdStart`) поема цялата игра. За всеки играч на всеки тик
плъгинът извършва няколко операции с числа с плаваща запетая и няколко четения`pev`; сървърни CVAR-и
се съхраняват в кеш и се обновяват веднъж в секунда, вместо да се четат при всеки тик.
Няма сканиране на обекти за всеки кадър, няма `set_task`цикли за всеки играч и няма
работа с низове по „горещия път“.
---
## Поддръжка
Купено от [codestrike.store](https://codestrike.store).
Когато съобщавате за проблем, включете изхода от и`kzac_stats <player>`
`kzac_physics`. Тези две архиви съдържат всичко необходимо, за да се създаде истински
откриване въз основа на прагова стойност, която трябва да се променя на вашия сървър.
---
*KZ Anti-Cheat — illusion @ CodeStrike*
---
## Зрялост на детектора — прочетете това, преди да активирате наказанията
Не всичките три детектора са еднакво доказали ефективността си, а разликата е достатъчно голяма
че те не трябва да бъдат конфигурирани по един и същ начин.
### BUNNYHOP и GROUNDSTRAFE — готови за производство
Проверено при **двама независими играчи**, и при двете настройки на airaccelerate, както и
истински измамни резултати. Нищо не се доближи до прага нито в една, нито в другата посока:
| Сигнал | Играч А | Играч Б | Праг | Измама |
|---|---|---|---|---|
| `+jump` натискания на скок | 5.26 | 5.30–6.19 | 1.20 | 1.00 |
| поредица от перфектни скокове | 3 | 2–4 | 12 | 20–23 |
| `+duck` в секунда | 13.3 | 9.0–20.2 | 35.0 | — |
| `+duck` вариация на разстоянието | 0.70–0.88 | 1.03–1.16 | 0.10 | — |
| прекъсвания при ходове с нулеви резултати | 3% | 0% | 50% | 99% |
Тези процеси могат безопасно да бъдат автоматизирани. и`kzac_punish_bhop 2` `kzac_punish_gstrafe 2`
са разумни.
### STRAFE-STABILIZER — само предупреждение
По време на разработката бяха открити девет фалшиви положителни резултата, всеки от които произтичаше от различно правило.
Пет правила трябваше да бъдат **деактивирани,** тъй като разпределенията на „човешки“ и „измамни“ резултати се припокриват:
| Правило за хора с увреждания | Защо |
|---|---|
| грешка в ъгъла | човек 1,83°, измама 1,34–2,20° — припокриване |
| стандартно отклонение на ъгловата грешка | диапазон за човешкото око 0,69–5,47°, осемкратно разпространение |
| споделяне в същата честотна лента | това е ъглов прозорец, зависещ от скоростта, а не постоянна величина |
| затвор с въртене | минимален резултат за човек: 0,139 за един играч, **0,026** за друг |
| ефективност при единичен скок | човек 0,684–0**,956**, измамник 0,835–0,946 — *обърнато* |
Последният е най-важният урок. При един-единствен скок играчът, който просто
страфите, които се изпълняват добре, достигат ефективност на ниво решаващ алгоритъм, а човешките оценки се изпълняват
направо през и отвъд измамните стойности. Разликата между ръка и
машината се появява едва след като се изчисли средната стойност **на стотици тикове**.
Остават активни двете правила за прозорци при над 300 отметки за чист въздух —
средната стойност на ефективността и вариацията на ефективността — които никога не са давали погрешни резултати
положителни при всяка записана сесия. Те надеждно улавят стабилизатора при високи
`sv_airaccelerate`, където той достига 0,909, докато максималната стойност за човека е 0,65.
**Стабилизаторът`sv_airaccelerate 10`, настроен на 90°, има по-малко усилване от един добър
човешки и не се открива с достатъчна надеждност.** Това е обективно ограничение, а не
проблем с настройката: въз основа на наличните данни няма измерен сигнал, който
в този случай ги разделя.
Препоръчва се:
```
kzac_punish_bhop 2 // ban
kzac_punish_gstrafe 2 // ban
kzac_punish_strafe 0 // warn only, decide by hand
```
Използвайте го върху`kzac_stats` всеки, за когото сигнализира детекторът за стрелба в движение. Числата зад
Всички оценки са налице, а администраторът ги сравнява с таблиците по-горе
е по-добър критерий от всеки съществуващ праг.