Page 1 of 1
Общие рекомендации по защите программ от взлома
Posted: Thu May 10, 2007 4:33 am
by Admin
Вызов процедуры регистрации
Если вы реализовываете свою схему регистрации, то никогда не выделяйте проверку в отдельную функцию, которая делает только саму проверку правильности ввода ключа и в результате возвращает только флаг проверки (верен или нет введенный регистрационный код).
Рекомендуется вставлять проверку в саму логику работы вашей программы, чтобы невозможно было отделить сам алгоритм проверки регистрационного кода от алгоритма работы вызывающей эту проверку процедуры.
Как делают большинство программистов:
Code: Select all
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;
При таком подходе к регистрации вашей программы крякер не будет разбираться с вашем алгоритмом проверки регистрационного кода (какой бы сложный он не был), а просто изменит код в самом начале CheckRegistration, который всегда будет возвращать True.
Code: Select all
function CheckRegistration(const RegNumber: String): Boolean;
begin
Result:=True;
exit;
...
end;
Рекомендуется "примешивать" логику работы программы в саму проверку регистрационного кода (показан простейший пример, конечная реализация зависит только от фантазии самого разработчика):
Code: Select all
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;
После реализации подобной схемы регистрации программы крякеру нужно будет досканально разобрать работу CheckRegistration чтобы полностью обойти проверку регистрационного кода. Также рекомендуется завиртуализировать (обработать с помощью VMProtect в режиме "Виртуализация" или "Ультра") обе процедуры CheckRegistration и TForm1.Button1Click.
Posted: Sun Sep 16, 2007 1:03 pm
by Admin
Проверка регистрационных ключей
Очень часто программисты допускают грубейшие ошибки при реализации самой проверки правильности регистрационного ключа:
Code: Select all
var ValidRegNumber: String;
...
function CheckRegistration(const RegNumber: String): Boolean;
begin
if RegNumber=ValidRegNumber then
Result:=True
else
Result:=False;
end;
Взломщики не составит труда в процессе трассировки этого участка кода получить значение валидного ключа (просто подсмотрев значение параметров в функции сравнения строк). Поэтому рекомендуется для сравнения использовать хеши ключей:
Code: Select all
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<>0 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.
Суть данного метода состоит в том, что данная хеш функция необратима и по результатам проверки хешей ключей невозможно определить какой должен быть правильный ключ. Взломщику придется потратить гораздо больше времени на нахождение правильного регистрационного ключа, исследуя гораздо больше участков вашей программы, а не только саму проверку правильности ключа.
Posted: Sun Sep 16, 2007 1:22 pm
by Admin
Хранение результата проверки регистрации
Как правило программисты, уделившие много времени на саму процедуру регистрации совершенно забывают о защите самого результата регистрации программы:
Code: Select all
var IsRegistered: Boolean;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
...
if not IsRegistered then
IsRegistered:=CheckRegistration(RegNumber);
if not IsRegistered then
exit;
...
end;
В данном случае перед проверкой проверяется глобальная переменная, хранящая результат проверки, которая может использоваться в различных частях программы.
Найти эту глобальную переменную не составит большого труда (просто просмотрев 2 сегмента данных на изменения ДО и ПОСЛЕ регистрации) - по такому принципу например работает всем известная программа ArtMoney. Рекомендуется все результаты проверок, отвечающих за регистрацию программы, хранить не в статической памяти, а в динамической. В случае хранения глобальных переменных в динамической памяти сканирование секций данных не предмет изменения ячеек памяти ДО и ПОСЛЕ регистрации ничего не даст крякеру.
Простейший пример хранения результата в динамически выделяемой памяти:
Code: Select all
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);
Re: Общие рекомендации по защите программ от взлома
Posted: Sun Jul 29, 2012 7:25 pm
by Игорь
Приветствую
Правильно ли я делаю что бы защитить dll?
В свойствах проекта выставил
Linker/Debugging/Generate Map File = Yes
Linker/Debugging/Generate Debug Info = No
Code: Select all
const char *ValidSerialNumber;
extern "C" __declspec(dllexport)
void __cdecl SetSerialNumber(PCHAR PO)
{
VMProtectBeginUltra("SetSerialNumber Marker");
ValidSerialNumber = PO;
VMProtectEnd();
}
extern "C" __declspec(dllexport)
BOOL __cdecl SomeFunction(PVOID *P0, PVOID P1)
{
VMProtectBeginUltra("SomeFunction Marker");
//Проверяем серийный номер
int Result = VMProtectSetSerialNumber(ValidSerialNumber);
if (Result)
{
return FALSE;
}
BOOL Status = SomeOtherFunction(P0, P1);
VMProtectEnd();
return Status;
}
При запуске программы вызывается SetSerialNumber передавая в dll серийный номер
Code: Select all
SetSerialNumber('jIFSY26szH49ZRupFk/HIb...
дальше в процессе работы будет постоянно вызываться SomeFunction
Что нужно сделать еще что бы максимально защитить dll?
Re: Общие рекомендации по защите программ от взлома
Posted: Sun Jul 29, 2012 8:25 pm
by Admin
1. Совершенно непонятно зачем вы включили MAP файл но при этом используете маркеры.
2. Зачем дергать каждый раз VMProtectSetSerialNumber (его нужно вызывать всего один раз) есть для этого есть VMProtectGetSerialNumberState. Соответственно вот эта штука ValidSerialNumber = PO; будет не нужна.
3. SomeOtherFunction можно привязать к ключу.
Re: Общие рекомендации по защите программ от взлома
Posted: Mon Jul 30, 2012 6:38 am
by Игорь
Admin wrote:1. Совершенно непонятно зачем вы включили MAP файл но при этом используете маркеры.
2. Зачем дергать каждый раз VMProtectSetSerialNumber (его нужно вызывать всего один раз) есть для этого есть VMProtectGetSerialNumberState. Соответственно вот эта штука ValidSerialNumber = PO; будет не нужна.
3. SomeOtherFunction можно привязать к ключу.
Так правильно?
Code: Select all
extern "C" __declspec(dllexport)
void __cdecl SetSerialNumber(PCHAR PO)
{
VMProtectSetSerialNumber(PO);
}
extern "C" __declspec(dllexport)
BOOL __cdecl SomeFunction(PVOID *P0, PVOID P1)
{
int Result = VMProtectGetSerialNumberState();
if (Result)
{
return FALSE;
}
BOOL Status = SomeOtherFunction(P0, P1);
return Status;
}
В VMProtect добавил две функции SetSerialNumber и SomeFunction в список
Маркеры используются для защиты отдельных участков кода, иcпользуя MAP файл мы защищаем всю функцию?
Re: Общие рекомендации по защите программ от взлома
Posted: Mon Jul 30, 2012 8:44 am
by Admin
Ну я думаю снаружи ДЛЛ-ки будет интересно узнать результат VMProtectSetSerialNumber (как минимум можно будет показать сообщение о том, что серийник невалидный):
Code: Select all
extern "C" __declspec(dllexport)
int __cdecl SetSerialNumber(PCHAR PO)
{
return VMProtectSetSerialNumber(PO);
}
А также добавил бы SomeOtherFunction в проект и поставил бы у неё привязку к ключу.
Маркеры используются для защиты отдельных участков кода, иcпользуя MAP файл мы защищаем всю функцию?
Да, все правильно.
Re: Общие рекомендации по защите программ от взлома
Posted: Mon Jul 30, 2012 9:20 am
by Игорь
Admin wrote:А также добавил бы SomeOtherFunction в проект и поставил бы у неё привязку к ключу.
Я поставил привязку к ключу, при неверном серийнике появляется сообщение "This code requires valid serial number to run", а менять текст сообщения можно?
В опциях->Сообщения->Необходим серийный номер меняю на свой текст, но все равно показывается "This code requires valid serial to run"
Re: Общие рекомендации по защите программ от взлома
Posted: Mon Jul 30, 2012 1:38 pm
by Admin
Я поставил привязку к ключу, при неверном серийнике появляется сообщение
Ну видимо привязали к ключу не ту функцию.
Все сообщения можно изменить в опциях.
Re: Общие рекомендации по защите программ от взлома
Posted: Thu Jun 13, 2019 3:37 pm
by postgres
Можете выложить проект для дельфи с кодом рекомендаций?