Это старая версия документа!
FSC, ну логично слямздить идею у работающих проэктов. Не помню где но встречал прогу которая запускалась при наличие флэшки с файлами. Но там был не перезаписуемый флэш накопитель. Ну а вам можно просто в обычную флэш закинуть файлик и проверять дату его изменения (что бы не накопировали гору таких флэш) или спрятать на флэшке какой нибудь файлик и всё. А потом при запуске проги сканировать все корневые каталоги дисков на наличие вашего файла.
нашел пример, которая вытаскивает аппаратный серийный номер флешки (наконец-то) не постесняюсь выложить код. Честно говоря у меня было такое ощущение, что люди постеснялись выложить код
но одна проблема встала: как мне серийный номер привязать к букве флешки?
Код C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
—————————————————————————
#include <vcl.h>
#pragma hdrstop
#include <stdio.h>
#include <windows.h>
#include <Setupapi.h>
#include <devguid.h>
#include «conio.h»
#include «tchar.h»
#include <devguid.h>
DEFINE_GUID( GUID_DEVCLASS_USB,0x36FC9E60, 0xC465, 0x11CF, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 );
#include «Unit1.h»
—————————————————————————
#pragma package(smart_init)
#pragma resource «*.dfm»
TForm1 *Form1;
—————————————————————————
fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
—————————————————————————
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HDEVINFO deviceInfoSet;
GUID *guidDev = (GUID*) &GUID_DEVCLASS_USB;
deviceInfoSet = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
TCHAR buffer [4000];
int memberIndex = 0;
while (true)
{
SP_DEVINFO_DATA deviceInfoData;
ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex, &deviceInfoData) == FALSE)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
{
break;
}
}
DWORD nSize=0 ;
SetupDiGetDeviceInstanceId (deviceInfoSet, &deviceInfoData, buffer, sizeof(buffer), &nSize);
buffer [nSize] ='\0';
_tprintf (_T(«%s\n»), buffer);
memberIndex++;
Label1→Caption=String(buffer);
if (String(buffer).SubString(1,8)==«USB\\VID_»)
ShowMessage(String(buffer)); AnsiString dsa; dsa=dsa.SubString(dsa.Pos(«USB\\»),)
}
if (deviceInfoSet)
{
SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
}
—————————————————————————
программа возвращает VID, PID и серийный номер в виде USB\VID_XXXX_PID_YYYY\ZZZZ, где XXXX-VID, YYYY-PID, ZZZZ-Серийный номер (Аппаратный!!!!!! который я так долго искал)
Программный серийный номер можно легко достать функцией GetVolumeInformation
Код C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
char FindFlash() ищет флешку и если находит возвращает букву диска
{ char charRootPath[10];
bool bHave;
UINT dt;
for (charRootPath[0] = TEXT('c'); charRootPath[0] ⇐ TEXT('z'); charRootPath[0]++)
{
ищем флэшку
charRootPath[1] = TEXT(':');
dt = GetDriveType(charRootPath);
if (dt == DRIVE_REMOVABLE)
{
bHave = TRUE;
break;
} else bHave = FALSE;
}
if (bHave==true)
{
если нашли то получаем информацию о флэшки
char VolumeName[50];
char FSName[50];
GetVolumeInformation(charRootPath, VolumeName, 50, NULL, NULL, NULL, FSName, 50);
char word[10];
char m_csFlashName[50];
int m_dwTotalSizeFlash;
int m_dwFreespaceFlash;
bool bEndTheard;
word[0] = charRootPath[0];
word[1]+=«\0»;
DWORD SecPerClaster, BytesPerSec, NumFreeClaster, TotalNumClaster;
GetDiskFreeSpace(word, &SecPerClaster, &BytesPerSec, &NumFreeClaster, &TotalNumClaster);
int freesize= (SecPerClaster * BytesPerSec * NumFreeClaster)/1024;
int totalsize = (SecPerClaster * BytesPerSec * TotalNumClaster)/1024;
if (VolumeName[0]==' ') strcpy(VolumeName, «NONAME»);
m_csFlashName[0] = VolumeName[0];
m_dwTotalSizeFlash = totalsize;
m_dwFreespaceFlash = freesize;
bEndTheard = FALSE;
bool bStartStore;
bStartStore=TRUE;
return word[0];
}
else return NULL;
}
Привязка к железу
Автор: C0ffe1n
дата: 11 марта 2009 года
сайт: http://z.alko-net.ru
Иногда в программах необходимо использовать возможность проверки типа носителя или его серийный номер. Причины могут быть разными от банального контроля устройств в системе до средств защит использующих привязку к железу. Сейчас я вам покажу как с помощью API реализовать эту простую задачу.
Нам понадобится всего 2 API - функции:
GetDriveType - определяет и возвращает тип носителя;
GetVolumeInformation - определяет информацию о носителе, среди которой содержится серийный номер.
Рассмотрим описание этих функций для С++ и Delphi. Первой будет функция GetDriveType, она очень простая и использует всего один параметр - указатель на том. Например «c:\»,«a:\» и т.д. Функция возвращает одно из следующих значений:
DRIVE_UNKNOWN - 0 : диск неопределен/не существует
DRIVE_NO_ROOT_DIR - 1 : неверный путь/ путь не указывает на том
DRIVE_REMOVABLE - 2 : тип устройства определяется как съемный (дискета, флешка и т.д.)
DRIVE_FIXED - 3 : тип устройства - фиксированный диск (жесткий диск)
DRIVE_REMOTE - 4 : тип устройства - удаленный(сетевой) диск
DRIVE_CDROM - 5 : это устройство CD-ROM
DRIVE_RAMDISK - 6 : виртуальный диск, созданный в оперативной памяти
C/C++
UINT WINAPI GetDriveType(
LPCTSTR lpRootPathName путь к диску
);
Delphi
function GetDriveType(
lpRootPathName: PChar путь к диску
): UINT; stdcall;
Замечание: Если в качестве параметра указать для С/С++ NULL, а для Delphi - nil то тип устройства будет определяться для текущего диска (с которого была запущена программа).
А теперь взглянем на функцию GetVolumeInformation. Тоже достаточно простая функция, однако использует параметров значительно больше.
C/C++
BOOL WINAPI GetVolumeInformation(
LPCTSTR lpRootPathName, путь к сетевому или локальному
тому (пример: «\\MyServer\MyShare\» или «C:\».
LPTSTR lpVolumeNameBuffer, буфер - в котором будет храниться
имя тома
DWORD nVolumeNameSize, размер буфера
LPDWORD lpVolumeSerialNumber, серийный номер тома
LPDWORD lpMaximumComponentLength, размер тома
LPDWORD lpFileSystemFlags, тип файловой системы
LPTSTR lpFileSystemNameBuffer, название файловой системы
DWORD nFileSystemNameSize размер буфера под название ФС
);
Delphi
function GetVolumeInformation(
lpRootPathName: PChar; путь к сетевому или локальному
тому (пример: «\\MyServer\MyShare\» или «C:\».
lpVolumeNameBuffer: PChar; буфер - в котором будет храниться
имя тома
nVolumeNameSize: DWORD; размер буфера
lpVolumeSerialNumber: PDWORD; серийный номер тома
var lpMaximumComponentLength, lpFileSystemFlags: DWORD; размер
тома и тип файловой системы
lpFileSystemNameBuffer: PChar; название файловой системы
nFileSystemNameSize: DWORD размер буфера под название ФС
): BOOL; stdcall;
Замечание: Если в качестве первого параметра указать для С/С++ NULL, а для Delphi - nil то функция будет выполняется для текущего диска (с которого была запущена программа).
Ну а теперь собственно для пущего интересу приведу пример, как привязать программу к устройству. В данном примере будем привязывать программу к флешке. Смотрим пример:
C/C++
#include
#include
#include
#include
using namespace std;
int main() {
Получаем тип носителя с которого запущена программа
unsigned int drive_type = GetDriveType( NULL );
char VolumeNameBuffer[100];
char FileSystemNameBuffer[100];
DWORD sz,fs;
unsigned long drive_sn;
GetVolumeInformationA(
NULL,
VolumeNameBuffer,
100,
&drive_sn,
sz,
fs,
FileSystemNameBuffer,
100
);
cout « «Volume serial number:\t»;
if(drive_sn == 1018821877) сравниваем серийный номер
cout « «correct» « endl;
else
cout « «invalid» « endl;
cout « «Drive type:\t»;
if(drive_type == DRIVE_REMOVABLE)
cout « «correct» « endl;
else
cout « «invalid» « endl;
getch();
}
Delphi
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,windows;
var
SerialNum,dtyp:DWORD;
a,b:DWORD;
Buffer,disk :Array[0..255]of char;
begin
dtyp:=GetDriveType(nil);
if dtyp = DRIVE_REMOVABLE then
writeln('Disk(type): Yes')
else
writeln('Disk(type): No');
GetVolumeInformation(
nil,
Buffer,
sizeof(Buffer),
@SerialNum,
a,
b,
nil,
0);
if SerialNum = 1018821877 then сравниваем серийный номер
writeln('S\N: Yes')
else
writeln('S\N: No');
readln;
end.
Замечание: Может возникнуть вопрос, а как узнать серийник диска, чтобы знать с чем сравнивать? Очень просто, для этого пишем тестовую прогу, в которой пишем следующий код:
C/C++
…
GetVolumeInformationA(NULL, VolumeNameBuffer,100,
&drive_sn,sz,fs,FileSystemNameBuffer,100);
…
Delphi
…
GetVolumeInformation(nil,Buffer,sizeof(Buffer),
@SerialNum, a,b, nil, 0);
writeln('S/N drive: ',SerialNum);
readln;
…
Первое, что приходит на ум, это привязка к MBR. А туда в неиспользуемую область можно еще пару байт записать, а в проге проверить всё совпадает или нет.
Проверять, что программа запускается с removable device, + сверять вендора, продукт ид и серийник флешки с эталонными. Только это все лишь до тех пор, пока кому-нибудь действительно не понадобится запустить программу с другого носителя :)
Есть книжка Агурова. Там все написано, даже исхъодник есть.
хранить прогу в зашифрованом виде, ключ - какая-нибудь строка в служебной области - бутсекторе, мбр и др. или серийник флэшки. и написать запускальщик, который будет ее расшифровывать и запускать, а дождавшись завершения - затирать и удалять.
Инструменты страницы
