Yvision.kz
kk
Разное
Разное
399 773 постов42 подписчика
Всяко-разно
0
09:33, 03 февраля 2013

Смена серийного номера тома

В статье “WinAPI: Определение типа носителя и его серийного номера” я показывал простой пример как реализовать защиту программ путем привязки к железу. Но все бы хорошо, да только бывают моменты когда просто необходимо “отвязаться” от железки. С такой проблемой столкнулся sansan. Собственно, благодаря ему и была написана эта статья.

Ну а теперь от слов к делу. Вся информация для корректной работы накопителя хранится в его загрузочной области. Нас будет интересовать используемая файловая система, от которой зависит расположения нужных байт относительно начала загрузочной области. Поэтому основная наша задача это определить тип файловой системы, и сместившись на нужный адрес переписать значение серийного номера. Всё просто ;). Изучим таблицу.

Таблица:
Поле/ФС                     FAT   FAT32   NTFS
Метка тома             0×2B   0×47    ?
Файловая система    0×36   0×52   0×3
Серийный номер       0×27   0×43    0×48

В приведенной таблице показаны основные файловые системы и соответствующие для них смещения. Оперируя этой информацией мы и будем реализовывать нашу программу. На необходимо реализовать следующие функции:
• DiskOpen - открыть диск
• DiskClose - закрыть диск
• ReadSector - прочитать сектор
• WriteSector - записать сектор
Реализовывать нашу программу мы будем С++ под семейство Windows NT. В частности, в среде разработки С++ Builder 6. Нам понадобиться глобальная переменная, в которой будем хранить указатель на используемый диск:

HANDLE hD;


Начнем c описания функции DiskOpen():

bool DiskOpen(char *vol)
{
char szDrive[10];
sprintf(szDrive, ".%c:", vol[0]);
hD = CreateFile(
szDrive,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
return hD != INVALID_HANDLE_VALUE;
}


Данной функции в качестве параметра передаётся буква диска, которому нужно сменить серийный номер. С помощью API-функции CreateFile(), мы получаем указатель на диск (подробней о CreateFile можно прочитать в статье “WinAPI: Работа с файлами (основные функции)“). В случае успеха возвращает “истину”, иначе - “ложь”.
Далее опишем функцию DiskClose():

void DiskClose()
{
if (hD != INVALID_HANDLE_VALUE)
CloseHandle(hD);
}


Эта функция достаточно простая, она освобождает используемый указатель на диск.
Следующая функция ReadSector():

bool ReadSector (DWORD sector, char *Buffer, int sectorSize)
{
DWORD read = 0;

if (SetFilePointer(hD, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return false;

if (!ReadFile(hD, Buffer, sectorSize, &read, NULL))
return false;
return true;
}


Эта функция уже посложней. Исользует 3 параметра:
• первый - указатель на диск.
• второй - буфер, куда будут записаны данные, считанные из загрузочной области.
• третий - размер загрузочной области, а следовательно и буфера.
Функция переводит указатель смещения в файле на нужную позицию с помощью API-функции SetFilePointer(), а потом с помощью ReadFile() считывает в буфер данные из загрузочной области (подробней о ReadFile() можно прочитать в статье “WinAPI: Работа с файлами (основные функции)“). В случае успеха возвращает “истину”, иначе - “ложь”.
И последняя функция WriteSector():

bool WriteSector(DWORD sector, char *Buffer, int sectorSize)
{
DWORD wrote = 0;

if (SetFilePointer(hD, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return false;

if (!WriteFile(hD, Buffer, sectorSize, &wrote, NULL))
return false;

return true;
}


Эта функция аналогична предыдущей. Только вместо API-функции ReadFile() используется WriteFile() (подробней о WriteFile() можно прочитать в статье “WinAPI: Работа с файлами (основные функции)“). В случае успеха возвращает “истину”, иначе - “ложь”.
Ну что, базовые функции мы реализовали, пора приступить и к завершающей стадии. Скинем на форму 1 кнопку, 1 поле ввода (сюда будем вводить новый серийный номер), и 1 ComboBox (определим выбор основных букв дисков). И для кнопки опишем следующий код:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
//проверяем не пусты ли необходимые поля
if ((ComboBox1->Text !="") && (Edit1->Text !=""))
{
DWORD newSerial = StrToInt(Edit1->Text);
const max_pbsi = 3;
//определяем структуру для сигнатуры загрузочной области
struct partial_boot_sector_info
{
LPSTR Fs; // название файловой системы
DWORD FsOffs; // смещение системного имени в загрузочной области
DWORD SerialOffs; // смещение серийного номера в загрузочной области
};
//описываем часто используемые сигнатуры
partial_boot_sector_info pbsi[max_pbsi] =
{
{"FAT32", 0x52, 0x43},
{"FAT", 0x36, 0x27},
{"NTFS", 0x03, 0x48}
};
//инициализируем необходимые переменные
TCHAR Drive[12]={0};
char Sector[512];
DWORD i;
sprintf(Drive, "%s:", ComboBox1->Text);
//открываем диск
if (!DiskOpen(Drive))
{//если ошибка оповещаем пользователя и выходим из процелуры
Application->MessageBoxA("Невозможно открыть диск!","Ошибка");
return;
}

// читаем загрузочную область
if (!ReadSector(0, Sector,512))
{
Application->MessageBoxA("Невозможно считать данные","Ошибка");
return;
}

// посик сигнатуры загрузочной области
for (i=0;i= max_pbsi)
{
Application->MessageBoxA("Невозможно сменить номер для этой файловой системы!","Ошибка");
return;
}

// меняем номер
*(PDWORD)(Sector+pbsi[i].SerialOffs) = newSerial;

// записываем в загрузочную область
if (!WriteSector(0, Sector,512))
{
Application->MessageBoxA("Невозможно записать на диск!","Ошибка");
return;
}
DiskClose();
Application->MessageBoxA("Серийный номер успешно изменен! Необходимо перезагрзить компьютер.","Внимание");
}else
Application->MessageBoxA("Не указан диск или серийный номер!","Внимание");
}


Если Вы меняете серийный номер тома флешки, то компьютер перезагружать не обязательно, достаточно отключить и заново подключить флешку. В других случаях результат буде виден только после перезагрузки. На этом всё, замечания и вопросы можете высказать на форуме. Спасибо за внимание! ;)
Рабочий пример скачать (http://depositfiles.com/files/3vg3psz21).
Рекомендуемые статьи для прочтения:
WinAPI: Работа с файлами (основные функции).
WinAPI: Определение типа носителя и его серийного номера.

Обучение взлому и программированию

0
648
0