Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 11631
Последний выпуск: 19.06.2015

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

Автор: C0ffe1n
11 марта 2009 года

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

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

Таблица:

Поле/ФСFATFAT32NTFS
Метка тома0x2B0x47?
Файловая система0x360x520x3
Серийный номер0x270x430x48

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

  • 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("Не указан диск или серийный номер!","Внимание");
}

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

Рабочий пример: скачать (4 Кб).

Рекомендуемые статьи для прочтения:

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
54K
31 октября 2009 года
predator21
0 / / 31.10.2009
Мне нравитсяМне не нравится
31 октября 2009, 20:41:01
а можите вы сами сделать это на моей флешке! заранее спасибо! я не программист!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог