diff options
Diffstat (limited to 'help/ru/recommendations.htm')
-rw-r--r-- | help/ru/recommendations.htm | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/help/ru/recommendations.htm b/help/ru/recommendations.htm new file mode 100644 index 0000000..b459b3a --- /dev/null +++ b/help/ru/recommendations.htm @@ -0,0 +1,233 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <link rel="Stylesheet" type="text/css" href="default.css" /> + <meta http-equiv="Content-Type" content= + "text/html; charset=utf-8" /> + + <title>Рекомендации по защите</title> +</head> + +<body> + <h1>Рекомендации по защите</h1> + + <p>Программа VMProtect представляет собой надежный инструмент + защиты кода приложения от изучения и взлома. Однако его + эффективное использование возможно лишь в том случае, если + встроенные в приложение защитные механизмы спроектированы по + определенным правилам и не содержат типичных ошибок. Рассмотрим + некоторые моменты, связанные с созданием защитных механизмов + приложения.</p> + + <h3>Процедура регистрации</h3> + + <p>Типичной ошибкой программистов, разрабатывающих собственную + схему регистрации экземпляра приложения, является вынос процедуры + проверки корректности введенного регистрационного ключа в + отдельную функцию c понятным возвращаемым значением:</p> + <pre class="indent code">function CheckRegistration(const RegNumber: String): Boolean; +begin + if RegNumber='123' then + Result:=True + else + Result:=False; +end; + +procedure TForm1.Button1Click(Sender: TObject); +begin + ... + if not CheckRegistration(RegNumber) then + exit; + Application.CreateForm(TForm2, Form2); + Form2.ShowModal; + ... +end; +</pre> + + <p>При подобном подходе к проверке регистрационного кода + взломщику нет необходимости вникать в алгоритм проверки ключа, а + будет достаточно изменить код в начале процедуры проверки таким + образом, чтобы она всегда возвращала значение, + соответствующее корректному регистрационному ключу:</p> + <pre class="indent code">function CheckRegistration(const RegNumber: String): Boolean; +begin + Result:=True; + exit; + ... +end; +</pre> + + <p>Гораздо более эффективным способом является встраивание + проверки корректности регистрационного кода в логику работы + программы таким образом, чтобы невозможно было отделить алгоритм + проверки регистрационного кода от алгоритма работы вызывающей эту + проверку процедуры. Также рекомендуется "примешивать" логику + работы программы в процедуру проверки регистрационного кода так, + чтобы "обход" регистрационной процедуры приводил к ошибкам в + работе приложения. Для примера, приведенного выше, это можно + сделать следующим образом:</p> + <pre class="indent code">function CheckRegistration(const RegNumber: String): Boolean; +begin + if RegNumber='123' then + begin + Application.CreateForm(TForm2, Form2); + Result:=True + end + else + Result:=False; +end; + +procedure TForm1.Button1Click(Sender: TObject); +begin + ... + Form2:=nil; + if not CheckRegistration(RegNumber) then + exit; + Form2.ShowModal; + ... +end; +</pre> + + <p>При подобной реализации функции CheckRegistration для "обхода" + проверки регистрационного ключа взломщику будет необходимо + досконально разбирать работу всей функции проверки ключа. При + защите данного приложения с помощью VMProtect рекомендуется + выполнить виртуализацию не только функции CheckRegistration, но и + процедуры TForm1.Button1Click. Для еще большего усложнения + процесса взлома приложения можно воспользоваться <a href="project_functions.htm#CompilationTypes">режимом защиты + "Ультра"</a>, сочетающим мутацию кода приложения с его последующей + виртуализацией.</p> + + <h3>Проверка регистрационных ключей</h3> + + <p>Очень часто программисты допускают грубейшие ошибки при + реализации самой проверки правильности регистрационного ключа, + производя сравнение введенного ключа с его корректным значением. + При подобной реализации взломщик легко сможет подобрать + корректное значение ключа, просмотрев в процессе трассировки + аргументы, с которыми вызывается функция сравнения строк:</p> + <pre class="indent code">var ValidRegNumber: String; +... +function CheckRegistration(const RegNumber: String): Boolean; +begin + if RegNumber=ValidRegNumber then + Result:=True + else + Result:=False; +end; +</pre> + + <p>Для исключения подобной ситуации при сравнении введенного + значения ключа с его допустимым значением рекомендуется + использовать их хеши, а не реальные значения. По своей сути + хеш-функция необратима, а значит, по результатам проверки хешей + невозможно определить значение допустимого ключа. При взломе + приложения будет необходимо потратить гораздо больше времени на + изучение программы, так как придется исследовать гораздо больше + участков кода, а не только процедуру проверки корректности + введенного ключа:</p> + <pre class="indent code">var + HashOfValidRegNumber: Longint; +... +// Пример использования обобщенного алгоритма хеширования Питера Вейнбергера (PJW) +function HashPJW(const Value: String): Longint; +var I:Integer; + G:Longint; +begin + Result:=0; + for I:=1 to Length(Value) do + begin + Result:=(Result shl 4)+Ord(Value[I]); + G:=Result and $F0000000; + if G<&gt0 then + Result:=(Result xor (G shr 24)) xor G; + end; +end; + +function CheckRegistration(const RegNumber: String): Boolean; +begin + if HashPJW(RegNumber)=HashOfValidRegNumber then + Result:=True + else + Result:=False; +end; +... +initialization + HashOfValidRegNumber:=HashPJW(ValidRegNumber); + +end. +</pre> + + <p>При защите программы с помощью VMProtect целесообразно + защитить функции HashPJW и CheckRegistration для усложнения + работы взломщика.</p> + + <h3>Хранение результата проверки регистрации</h3> + + <p>Как правило, программисты, затратившие много времени на + реализацию самой процедуры регистрации, не уделяют достаточного + внимания защите самого результата регистрации программы. В + приведенном ниже примере перед вызовом функции проверки + корректности регистрационного номера контролируется состояние + глобальной переменной, хранящей результат проверки регистрации. + Для взломщика поиск глобальной переменной не представляет + трудностей - достаточно будет сравнить сегменты данных ДО и ПОСЛЕ + регистрации. Кстати, аналогичный принцип лежит в основе работы + известной программы ArtMoney.</p> + <pre class="indent code">var IsRegistered: Boolean; +... +procedure TForm1.Button1Click(Sender: TObject); +begin + ... + if not IsRegistered then + IsRegistered:=CheckRegistration(RegNumber); + if not IsRegistered then + exit; + ... +end; +</pre> + + <p>Для исключения подобной ситуации рекомендуется результаты всех + проверок, отвечающих за регистрацию программы, хранить в + динамической памяти, так как в этом случае сканирование секций + данных на предмет изменения ячеек памяти ДО и ПОСЛЕ регистрации + окажется бесполезным. Простейший пример, демонстрирующий хранение + результата в динамически выделяемой памяти, приведен ниже.</p> + <pre class="indent code">type PBoolean = ^Boolean; + +var IsRegistered: PBoolean; +... +procedure TForm1.Button1Click(Sender: TObject); +begin + ... + if not IsRegistered^ then + IsRegistered^:=CheckRegistration(RegNumber); + if not IsRegistered^ then + exit; + ... +end; +... +initialization + New(IsRegistered); +</pre> + + <p>Выше приведены простейшие примеры реализации встроенных в + приложение механизмов защиты. Варианты реальной реализации + процедуры регистрации, функции проверки регистрационного ключа + или организации хранения результата проверки регистрационного + ключа ограничены только фантазией разработчика. Однако в любом + случае при разработке механизмов защиты приложения следует знать + о возможных ошибках и не повторять их.</p><br /> + <br /> + <br /> + <br /> + <br /> + <hr noshade="noshade" size="1" /> + + <div align="center"> + © 2006-2015 Copyright VMProtect Software + </div> +</body> +</html> |