Защита игр от взлома

         

P-код


Термин p-код восходит к интерпретатору Visual Basic'а, однако, в хакерских кругах означает нечто большее и подразумевает любой интерпретируемый код произвольной виртуальной машины (не путать с VMWare). Непосредственное дизассемблирование в этом случае становится невозможно и приходится прибегать к декомпиляции, а для этого необходимо проанализировать алгоритм работы интерпретатора, написать (и отладить!) декомпилятор, что требует пива и времени. Правда, разработка (и отладка!) интерпретатора тоже даром не обходится и нам ним приходится попыхтеть (Джа в помощь!). К тому же разработка языка тянет за собой кучу вспомогательного инструментария (в первую нам понадобиться отладчик), иначе как на нем программировать?!

Все это выливается в солидный проект, который может быть использован всего один раз, в одной-единственной программе, да и то после выхода нескольких версий ядро интерпретатора желательно слегка изменять, чтобы написанный хакером декомпилятор перестал работать. Что поделаешь! Защита требует жертв и больших вложений. Ладно бы только вложений! Производительность интерпретируемого кода плетется в самом хвосте, отставая от динамической расшифровки и обфускации, но... может быть, есть возможность реализовать на p-коде только защитные модули? Нет! Тогда их отломают не глядя! На p-коде должна быть реализована вся программа целиком, в том числе и защитный механизм, тогда без декомпилятора его будет не хакнуть. Но это — в теории. На практике же, полностью загнать программу в p-код не удается по причине производительности и критичные к быстродействую функции пишутся на языке высокого уровня или даже ассемблере. А вот вызываются они уже из p-кода, в котором сосредоточена основная логика по типу "если нельзя, то все-таки".

Кстати говоря, большинство игровых миров управляются своим собственным скрпитовым языком, описывающим движение облаков, поведение мячика и характер разных монстров. На чистом Си никакую игру сложнее "тетриса" не запрограммировать! А раз мы уже имеем скриптовый язык, то почему бы не включить в него несколько защитных функций? Тогда чтобы взломать программу, хакеру придется разобраться в работе скрипиового движка.


Чаще всего разработчики используют Паскаль- или Бейсик-подобные языки, что не самый лучший выбор с точки зрения защищенности. Программа на p-коде при этом представляет собой последовательность ключевых слов (операторов языка) с аргументами и очень просто декомпилируется. На другом конце шкалы сложности находится Машина Тьюринга, Сети Петри, Стрелка Пирса и прочие примитивные виртуальные машины, реализующие фундаментальные логические операции, в результате чего даже такая конструкция как "IF THEN ELSE" распадается на сотни микрокоманд! Солнце погаснет прежде, чем хакер их проанализирует или… все-таки не погаснет? Существует множество продвинутых способов наглядной визуализации таких алгоритмов и к тому же… мы совсем забыли о производительности! Реализовать crackme на базе Машины Тьюринга еще можно, а вот коммерческое приложение — едва ли.

Хорошая идея — приложить к этому делу Форт. Вот его преимущества: простота реализации Форт-машины, компактность p-кода, довольно высокая производительность, сложность декомпиляции и ни на что не похожесть. Форт стоит особняком от всех языков, совсем не стремясь соответствовать человеческим привычкам, "здравому смыслу" и "логике". Разобраться в его идеологии с нуля — будет непросто. Хакеру придется нарыть кучу литературы и запастись терпением. Даже если ему не наскучит, разработчик защиты получит хорошую фору по времени, ну а там… мыщъх что-нибудь придумает!

Ниже приведен код Форт-машины, выдранный из программы see.exe, поставляемой вместе с Interrupt List'ом Ральфа Брауна.

seg000:1F29 loc_1F29:                           ; CODE XREF: start+39B9vj

seg000:1F29   call   sub_1F04

seg000:1F2C   mov    word_A5C, bx

seg000:1F30   mov    si, dx

seg000:1F32   mov    bp, [bx+38h]

seg000:1F35   mov    sp, [bx+36h]

seg000:1F38   lodsw

seg000:1F39   mov    bx, ax

seg000:1F3B   jmp    word ptr [bx]


Содержание раздела