C@T | Дата: Воскресенье, 02.12.2012, 01:11 | Сообщение # 1 |
Авторитетный
Зарегистрирован: 06.03.2010
Группа: Модераторы
Сообщений: 265
Статус: Offline
| Предисловие
данная статья не была заранее подготовленной, идея ее написать появилась у меня сегодня после того как увидел один пост на форуме и вспомнил как с друзьями мы убирали привязку у программ друг друга статья написано как можно более понятно, так как большинство посетителей нашего форума новички в программировании, и прошу не серчать за излишнюю подробность думаю вам будет интересно почитать
на форуме один из посетителей сделал прозьбу о том как сделать привязку программке итак начнем, первое правда что мне пришлось сделать это скачать дэлфи, так как, увы, давно на нем не писал, а наш ресурс узко специализированн
после того как устанавили дэлфи нужна программка которую мы будем привязывать и мы ее пишем Code unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(Edit1.text); end;
end.
дальше нам нужна программка которая скажет нам наш HardID , на который мы будем привязывать, в данном примере будем привязывать к ID логического диска, правда да, оно при переустановке системы меняется, но все же, пойдет
Code unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var VSNum, dw1, dw2: DWORD; szTemp: array[0..MAX_PATH] of char; begin GetWindowsDirectory(szTemp,MAX_PATH); GetVolumeInformation(PAnsiChar(szTemp[0]+':\'), nil, 0, @VSNum, dw1, dw2, nil, 0); Edit1.Text := IntToHex(VSNum,16); end;
end.
суть привязки в том что бы просто сравнить прописанный в проге HardID с HardID на запущенной системе и если ID не совпадают, то завершить программу пишем процедуру которая будет это делать
Code procedure pegging(); // спасибо гуглу за перевод var myID:DWORD; VSNum, dw1, dw2: DWORD; szTemp: array[0..MAX_PATH] of char; begin myID := $003C7FD842;
GetWindowsDirectory(szTemp,MAX_PATH); GetVolumeInformation(PAnsiChar(szTemp[0]+':\'), nil, 0, @VSNum, dw1, dw2, nil, 0); if( VSNum <> myID) then begin TerminateProcess(GetCurrentProcess(), 0); end; end;
вызываем ее при запуске программы
Code procedure TForm1.FormCreate(Sender: TObject); begin pegging(); end;
в итоге если мы запустим программу на другом компьютере она завершится но не все так хорошо насколько кажется, ведь если сделать такую привязку в реальном программном продукте, то привязку очень быстро уберут если мы откроем наш ехе файл дэбагерром(например OllyDbg) , то сможем легко найти импорт функции TerminateProcess и увидить где он вызывается
дальше если взглянуть выше по коду будет видно прыжок, а точнее условный переход на вызов TerminateProcess Code CMP EBX,DWORD PTR SS:[EBP-4] JE SHORT crack.00453882 сразу становится понятно что это сравнение нашего ключа с ключем на локальной систем, если ключ подходит, то продолжается выполнение программы, если же нет, то программа завершается прыжок происходит командой JE , для того что бы убрать привязку достаточно лишь изменить условие перехода на обратное, а т.е JE поменять на JNZ(или JNE)
для того что бы усложнить поиск нужного участка кода, который отвечает за проверку на HardID можно избавится от вызова TerminateProcess, например
Code procedure pegging(); var myID:DWORD; VSNum, dw1, dw2: DWORD; szTemp: array[0..MAX_PATH] of char; begin myID := $003C7FD822;
GetWindowsDirectory(szTemp,MAX_PATH); GetVolumeInformation(PAnsiChar(szTemp[0]+':\'), nil, 0, @VSNum, dw1, dw2, nil, 0);
asm mov eax,myID mov ebx,dw2 sub eax,VSNum
push offset @metka add esp,eax ret @metka: end;
end;
в данном примере отсутствует даже сравнение как таковое, здесь все происходит так,в регистр eax записывается ID с которым нужно сравнивать(айди компьютера на котором программа должна запустится) в регист ebx заносится ID локального компьютера дальше считается разница между eax b ebx (между первым и вторым ID) , и результат записывается в eax, в итоге если первый и второй ID равны то в eax окажется ноль, иначе какое то число дальше в стек заносится адрес метки завершения привязки и к регистру esp добавляется значение регистра eax, и получается если eax не равен нулю то работа программы будет нарушена, и дальше при выполнении команды ret программа вызовет исключение, ошибку, а если в eax будет 0 то программа как работала так и будет работать в данном коде можно даже убрать все что идет после add esp,eax , и привязка все равно будет работать
такую привязку будет чу чуть сложнее найти и вылечить, но все равно возможно, для большего усложнения ее обнаружения можно убрать GetVolumeInformation из импортов и сделать поиск адреса функции через GetProcAddr но все равно это не даст надежной защиты и программу можно будет взломать в течении пары часов по моему самым лучшим способом привязать программу это совместить привязку и крипт, что бы для того что бы найти код привязки его и весь остальной код программы нужно было бы еще расшифровать, а этот процесс достаточно долгий для пошагового выполнения вручную
|
|
| |