Стратегії перемоги редакторів пам'яті для обману - Настільні ігри [закрито]


35

Я припускаю, що ми говоримо про настільні ігри - те, що програвач завантажує та працює на своєму локальному комп’ютері. Багато редакторів пам'яті, які дозволяють виявляти та заморожувати такі значення, як стан здоров'я гравця.

Як запобігти обману за допомогою зміни пам'яті? Які стратегії ефективні для боротьби з таким видом обману?

Для довідки, я знаю, що гравці можуть: - Шукати щось за значенням або діапазоном - Шукати щось, що змінило значення - Встановити значення пам'яті - Заморозити значення пам'яті

Я шукаю хороших. Два, які я використовую посередньо:

  • Відображення значень у відсотках замість кількості (наприклад, 46/50 = 92% здоров'я)
  • Клас низького рівня, який містить значення в масиві та переміщує їх із кожною зміною. (Наприклад, замість int у мене є клас, який є масивом ints, і кожного разу, коли значення змінюється, я використовую інший, випадково вибраний елемент масиву, щоб утримувати значення)

Гра в автономному режимі, безкоштовна і однокористувацька.

Редагувати: для нащадків я вирішив це (в C #) і розмістив своє рішення тут , у своєму блозі.

Відповіді:


21

Інша можливість (для цілих значень) полягає у тому, щоб мати змінну другого члена, яка містить побітове доповнення існуючої змінної.

Тож уявіть, що ви отримали health, ви б також мали healthComplement. Ваша реалізація може виглядати приблизно так:

// setter sets value and complement
void setHealth(int value){
    health = value;
    healthComplement = ~value;
}

// getter checks if value was changed outside of the setter
int getHealth(){
    if(value != ~healthComplement){
        // launch some cheat-counter-measure, like crashing the game?
        exit;
    }
    return health;
}

Комусь, хто хоче обдурити, доведеться правильно налаштувати здоров'я та здоров’яЗаповнення, інакше гра може вийти з ладу.

Я думаю, що це ніколи безглуздо намагатися запобігти подібним. Люди успішно створили хаки / чіти для набагато складніших речей, і це просто зайве обмацує ваш код або робить вашу гру гіршою.


12

Ось одну схему я придумав, коли хтось давно просив її на якійсь дошці. Використання відсотків або подвоєних змінних насправді не працює, оскільки ви можете шукати "будь-які" значення та заморожувати їх.

Натомість зробіть монстр типу даних.

Зберігайте важливі значення як структуру:

  • 32 покажчики на біти
  • Для швидкого читання, структура також включить поточне значення як звичайний int

Для маніпуляцій збирайте поточне значення з окремо виділених бітів (що може бути істинним / хибним вступом), змінюйте значення та зберігайте їх назад.

Ось неприємний біт: кожен раз, коли ви маніпулюєте цінністю, звільняйте та виділяйте біти знову. Виділення має відбуватися у випадковому порядку , тому дані перестрибують у пам'яті і їх не можна легко заморозити.

Додатковими гарантіями було б зберігати контрольні суми значень (а також "звичайний" int) та порівнювати їх під час викликів маніпуляцій. Якщо невідповідність виявлена, зробіть щось тонке, як-от видаліть випадковий ключ, необхідний для розблокування дверей для просування в грі.

Редагувати: Для подальшого переміщення в пам'яті переконайтеся, що виділили нові "біти", перш ніж звільнити старі.

Редагувати: Для багатокористувацьких ігор також можна серіалізувати структуру даних, стискати її та надсилати по мережі. Не найефективніше використання мережі, але, безумовно, складніше це з'ясувати через нюхання пакетів.


9

Як щодо зберігання стану здоров'я, доповненого випадковим значенням, що генерується кожного разу, коли ви його зберігаєте. Це хоча б переможе простий механізм пошуку збільшення / зменшення значень у пам'яті, щоб знайти здоров'я.

class Player
{
  int m_Health;
  int m_RandomHealth;
  Random m_Rnd = new Random();

  public int Health {
    get
    {
      return m_Health ^ m_RandomHealth;
    }

    set
    {
      m_RandomHealth = m_Rnd.Next();
      m_Health = value ^ m_RandomHealth;
    }
  }
}

Крім того, можливо, ви захочете скинути значення кожного кадру, навіть якщо стан здоров'я не зміниться. Це заважатиме людям шукати змінені адреси, коли їхнє здоров'я змінюється, а ті, що залишаються незмінними, коли стан здоров'я залишається незмінним.

Бонус: Створюйте новий об’єкт щоразу, коли він змінюється, щоб змінилася адреса пам'яті, і налаштовуйте здоров'я змінювати випадкове число, значення xored та адресу в пам'яті кожного разу, коли ви читаєте його:

class Player
{
  int [] m_HealthArray; // [0] is random int, [1] is xored health
  Random m_Rnd = new Random();

  public Player() {
    this.Health = 100;
  }

  public int Health {
    get
    {
      int health = m_HealthArray[0] ^ m_HealthArray[1];
      Health = health; // reset to move in memory and change xor value
      return health;
    }

    set
    {
      m_HealthArray = new int[2];
      m_HealthArray[0] = m_Rnd.Next();
      m_HealthArray[1] = m_HealthArray[0] ^ value;
    }
  }
}

8

Хоча я зробив перший коментар, поставивши під сумнів питання про погіршення досвіду частини вашої аудиторії без очевидних вигод, я все ж вважаю цікавим питання з технічної точки зору.

У мене щойно була така ідея: те, що роблять шахраї - це значити значення, які їх змінюють і заморожують. Після цього пошук відбуватиметься лише між смертьми або подіями, які змінили здоров'я гравця. Більше того, шахрай може вдосконалити пошук, відфільтрувавши те, що змінилося, коли він "не вмирав".

Що робити, якщо лічильник "здоров'я" весь час змінюється? Зробіть його вказівником і перерозподіліть його в кожному кадрі або в кожному N кадрах, якщо показник продуктивності занадто великий. Або XOR це з випадковим значенням, яке змінює кожен кадр (XORing знову проти того ж значення для розшифровки перед шифруванням з новим випадковим значенням).

Якщо у вас є інші дані в грі, які також змінюються весь час (включаючи позиції x і y персонажа гравця або лічильник часу), це може ускладнити з'ясування того, що з усіх змін даних - це стан здоров'я. І заморожування всього ігрового стану - це не для шахраїв.

Для подальшого введення в оману, ви можете фактично зберігати здоров'я у звичайній змінній, що записується лише як медовий горщик.

Редагувати :

Все-таки шахрай може спробувати знайти, яка із змінних, що змінюється весь час, - це та, яка замерзне через проби та помилки. Можливим рішенням було б з'єднання змінних разом.

Приклад:

Замість того, щоб зберігати здоров'я (h) і позицію (x), ви зберігаєте їх у двох змінних a і b, з яких ви можете отримати значення пізніше:

a = x+h; b = x-h
x = (a+b)/2; h = (a-b)/2

Таким чином, якщо шахрай заморожує лише одну з них, а потім пересуває персонажа, позиція впливає і, залежно від того, хто з них був застиглий, h переходить у негативний (миттєва смерть). Ви можете перемикатися між наведеними формулами та:

a = x-h; b = x+h
x = (a+b)/2; h = (b-a)/2

У послідовних кадрах, і ви гарантуєте, що щонайменше за 2 кадри після замороження будь-якої зі змінних стан здоров’я перетвориться на 0 момент, коли х зміниться. Пам’ятайте, що ви зберігаєте лише a і b. Поєднайте це з безперервним XOR, як згадувалося вище. Результат - це сукупність змінних, які змінюють кожен кадр на здавалося б випадкові значення, і заморожування будь-якого одного або їх підмножини створює лише небажані побічні ефекти в грі, миттєва смерть є однією з них.


7

Я думаю, що можливий варіант (я не надто знайомий з цими інструментами обману): не приховуйте цього. Виконайте свої операції та очікуйте певних результатів. Після операції (можливо, наступного кадру) перевірте, чи є результати такими, якими ви їх очікуєте. Якщо ви віднімаєте здоров'я та перевіряєте його, тільки щоб знайти здоров'я, яке ніколи не змінювалося, ви можете бути впевнені (за умови, що у вас немає явної помилки), що він був заблокований.

Якщо ви виявите обман, тепер ви можете змінювати правила гри, як вважаєте за потрібне для максимального горя, якщо це ваш намір. Якщо ви маєте намір ігнорувати обман і змусити гру продовжувати працювати, перерозподіліть здоров'я в іншому місці в пам’яті та змініть свої покажчики, щоб нове значення звикло, а старе було проігноровано. Повторіть ad infinitum.


6

Будь-які спроби простого затухання теоретично зазнають краху, але на практиці потрібно просто зробити досить важким, щоб зламати те, що виклик стає менш веселим, ніж успіх у грі. Я не знаю, що це за ваша гра, тому я не ризикую запропонувати методи обфускування даних, тим більше, як вважаю, що вони безглузді.

Це сказало, і вам, мабуть, це не сподобається, я вважаю, що ви шукаєте завіси пам'яті , що є концепцією довірених обчислень .


3

Один дуже ефективний прийом, який використовують деякі шахраї (DoomRL, Brogue), - це маскування фактичних змінних. Це означає, що замість того, щоб здоров'я показувати як "2/10", показуйте його як "20%".

Пам’ятайте, більшість редакторів пам'яті добре працює з певним значенням пошуку / фільтрації. Якщо ви не знаєте конкретного значення, ви все одно можете його відстежувати (наприклад, пошук змінених / зменшених значень після падіння здоров'я гравця), хоча це зробить набагато більше часу.

Я також пропоную зворотній зв'язок проти шахрайства. Наприклад, якщо у вас є гра, в якій гравець отримує непозитивні збитки, а їх здоров'я не впало, ви можете легко і точно перевірити це і знати, що гравець обманює. Зробіть щось цікаве, як нерест навколо нього ворогів убер :)


2

Напишіть драйвер дзвінка 0, який підключає SSDT і записує / блокує, коли у вашій програмі викликається ReadProcessMemory / WriteProcessMemory. Було б краще просто увійти, щоб ви могли повільно змінювати їх ігрову поведінку з часом, а не просто виходити з ладу.


Це здається, що ви говорите про деталі реалізації низького рівня (API API?) Я запитую про загальні стратегії високого рівня.
зола999

2

Чому б ви заважали гравцям обманювати себе (на що доводиться обман в одній грі)? У багатокористувацькому середовищі стоїть завдання сервера виявляти неприродні зміни та протидіяти їм (як правило, або ігноруючи вхід, або повністю блокуючи винуватця з сервера), але в середовищі для одного гравця нічого не відбувається, крім того, що шахрай робить сам сервіс.

IOW, якщо ви не створюєте багатокористувацьку гру, це марно витрачайте гроші, і якщо ви думаєте про загартовування не на тому місці.


2

Вивчіть відомі інструменти обману - і часто перевіряйте, чи виявлено будь-який із найпоширеніших інструментів запуску (перевірити назви процесів?)

Якщо будь-які виявлені, нехай гравець обманює (якщо в автономному режимі це нешкідливо), але переконайтеся, що ніякі бали / домовленості не будуть розміщені в будь-якій системі онлайн-лідерів / домовленостей - просто змусьте це мовчки вийти з ладу?

Не зупинить більш рішучих хакерів, але зменшить ймовірність, щоб випадковіші чити зіпсували ваші лідери.

(Можливо, роздратуйте кодери, у яких інструменти розробників відкриті та мінімізовані для законних цілей та роблять ігрову перерву, хоча ...)


7
Я був великим шанувальником Steam як платформи дистрибуції і грав багато Team Team Fortress II пару років тому. Одного разу ввечері я взяв перерву від тривалого сеансу кодування і під час гри відпустив Visual Studio і налагоджувач. Я виявив, що заборонений на TF2 за "обман". Жодної апеляції, жодної рамки для скасування заборони. Одне "правопорушення", і воно є постійним для обліку. Я досі не маю поняття, чому - і повірте, я розпався - хіба що я побачив, що заглиблений у FAQ, що відкриття "редактора пам'яті" під час гри грало на обман і його заборонили. Ого.

1

Я думаю, що найпростішим рішенням цього є реалізація накрутки. Вимкнути забивання під час чит-опції.

Ще одна гарна ідея, що я не маю уявлення, як би ви реалізували. Це вимкнути гру, коли є заморожена змінна пам'ять або щось подібне :)

Удачі)


3
Реалізація чітів - хороший варіант. Вимкнення гри, не стільки ... (уявіть, якщо ви помилитесь, і
закрийте
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.