aboutsummaryrefslogtreecommitdiff
path: root/help/ru/recommendations.htm
diff options
context:
space:
mode:
Diffstat (limited to 'help/ru/recommendations.htm')
-rw-r--r--help/ru/recommendations.htm233
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&lt;&amp;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>