
用api函數讀取硬盤的序列號
關于盤序列號有兩種:
硬盤序列號: 英文名 Hard Disk Serial Number, 該號是出廠時生產廠家為
區別產品而設置的, 是唯一的, 是只讀的, 利用硬盤序列號的
加密往往是利用其唯一和只讀的特性, 大多是針對有序列號的
IDE HDD而言, 對于沒有序列號或SCSI HDD硬盤則無能為力,
這也是利用它進行加密的局限性.
卷的序列號: 英文名 Volume Serial Number, 該號既可指軟磁盤要得, 如:
A:盤和B:盤的, 又可以指硬盤的邏輯盤, 如: C:, D:...的,
是高級格式化時隨機產生的, 是可以修改的, 所以利用其進行
加密,
在寫程序時我們想對每一臺計算機都生成一個唯一的標識,而且在一此共享軟件中我們也看到,軟件在不同的機器上生成了不同的標識,這是如何實現的呢,其實是軟件有一部分程序
讀取了,本地計算機的一部分硬件參數(如硬盤序列號,網卡序列號等等),再通過一系列算法而得到了一個唯一標識,其實我們也可以通過一個api函數生成我們的唯一標識,由于硬盤人人都有,而網卡不一定每個人都有,所以以讀硬盤序列號為例,
下面就先介紹一下我們要用到的api函數
BOOL GetVolumeInformation(
LPCTSTR lpRootPathName, // 硬盤的路徑
LPTSTR lpVolumeNameBuffer, // 硬盤的卷標
DWORD nVolumeNameSize, // 卷標的字符串長度
LPDWORD lpVolumeSerialNumber, // 硬盤的序列號
LPDWORD lpMaximumComponentLength, // 最大的文件長度
LPDWORD lpFileSystemFlags, // 文件系統的一此標志
LPTSTR lpFileSystemNameBuffer, // 存儲所在盤符的分區類型的長指針變量
DWORD nFileSystemNameSize // 分區類型的長指針變量所指向的字符串長度
);
如果上述函數成功就返回一個非0值。
光說不做,是不行了,我們還得實踐一下:// 最大的文件長度
首選用MFC AppWizard建立一個基于Dialog ba的對話框工程,名為GetHardID,點擊finish。
加一個按鈕,雙擊它,點擊ok,并在對應的函數中加入如下代碼:
LPCTSTR lpRootPathName="c:\\"; //取C盤
LPTSTR lpVolumeNameBuffer=new char[12];//磁盤卷標
DWORD nVolumeNameSize=12;// 卷標的字符串長度
DWORD VolumeSerialNumber;//硬盤序列號
DWORD MaximumComponentLength;// 最大的文件長度
LPTSTR lpFileSystemNameBuffer=new char[10];// 存儲所在盤符的分區類型的長指針變量
DWORD nFileSystemNameSize=10;// 分區類型的長指針變量所指向的字符串長度
DWORD FileSystemFlags;// 文件系統的一此標志
::GetVolumeInformation(lpRootPathName,
lpVolumeNameBuffer, nVolumeNameSize,
&VolumeSerialNumber, &MaximumComponentLength,
&FileSystemFlags,
lpFileSystemNameBuffer, nFileSystemNameSize);
CString str;
str.Format("Seria Num is %lx ",VolumeSerialNumber);
AfxMessageBox(str);
編譯,鏈接并運行程序,單擊按鈕,在彈出的對話框中就是我們要的序列號。
對不對我們驗證一下,進入dos窗口,打入"dir c:/p"命令,怎么樣是不是和我們的程序顯示的一模一樣
這樣我們就在功告成了。
=======cpu adapter id ===========
以下代碼可以取得系統特征碼(網卡MAC、硬盤序列號、CPU ID、BIOS編號)
BYTE szSystemInfo[4096]; // 在程序執行完畢后,此處存儲取得的系統特征碼
UINT uSystemInfoLen = 0; // 在程序執行完畢后,此處存儲取得的系統特征碼的長度
// 網卡 MAC 地址,注意: MAC 地址是可以在注冊表中修改的
{
UINT uErrorCode = 0;
IP_ADAPTER_INFO iai;
ULONG uSize = 0;
DWORD dwResult = GetAdaptersInfo( &iai, &uSize );
if( dwResult == ERROR_BUFFER_OVERFLOW )
{
IP_ADAPTER_INFO* piai = ( IP_ADAPTER_INFO* )HeapAlloc( GetProcessHeap( ), 0, uSize );
if( piai != NULL )
{
dwResult = GetAdaptersInfo( piai, &uSize );
if( ERROR_SUCCESS == dwResult )
{
IP_ADAPTER_INFO* piai2 = piai;
while( piai2 != NULL && ( uSystemInfoLen + piai2->AddressLength ) < 4096U )
{
CopyMemory( szSystemInfo + uSystemInfoLen, piai2->Address, piai2->AddressLength );
uSystemInfoLen += piai2->AddressLength;
piai2 = piai2->Next;
}
}
el
{
uErrorCode = 0xF0000000U + dwResult;
}
VERIFY( HeapFree( GetProcessHeap( ), 0, piai ) );
}
el
{
return FALSE;
}
}
el
{
uErrorCode = 0xE0000000U + dwResult;
}
if( uErrorCode != 0U )
{
return FALSE;
}
}
// 硬盤序列號,注意:有的硬盤沒有序列號
{
OSVERSIONINFO ovi = { 0 };
ovi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
GetVersionEx( &ovi );
if( ovi.dwPlatformId != VER_PLATFORM_WIN32_NT )
{
// Only Windows 2000, Windows XP, Windows
return FALSE;
}
el
{
if( !WinNTHDSerialNumASPhysicalRead( szSystemInfo, &uSystemInfoLen, 1024 ) )
{
WinNTHDSerialNumAsScsiRead( szSystemInfo, &uSystemInfoLen, 1024 );
}
}
}
// CPU ID
{
BOOL bException = FALSE;
BYTE szCpu[16] = { 0 };
UINT uCpuID = 0U;
__try
{
_asm
{
mov eax, 0
cpuid
mov dword ptr szCpu[0], ebx
mov dword ptr szCpu[4], edx
mov dword ptr szCpu[8], ecx
mov eax, 1
cpuid
mov uCpuID, edx
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
bException = TRUE;
}
if( !bException )
{
CopyMemory( szSystemInfo + uSystemInfoLen, &uCpuID, sizeof( UINT ) );
uSystemInfoLen += sizeof( UINT );
uCpuID = strlen( ( char* )szCpu );
CopyMemory( szSystemInfo + uSystemInfoLen, szCpu, uCpuID );
uSystemInfoLen += uCpuID;
}
}
// BIOS 編號,支持 AMI, AWARD, PHOENIX
{
SIZE_T ssize;
LARGE_INTEGER so;
so.LowPart=0x000f0000;
so.HighPart=0x00000000;
ssize=0xffff;
wchar_t strPH[30]=L\\device\\physicalmemory;
DWORD ba=0;
UNICODE_STRING struniph;
struniph.Buffer=strPH;
struniph.Length=0x2c;
struniph.MaximUMLength =0x2e;
OBJECT_ATTRIBUTES obj_ar;
obj_ar.Attributes =64;
obj_ar.Length =24;
obj_ar.ObjectName=&struniph;
obj_ar.RootDirectory=0;
obj_ar.SecurityDescriptor=0;
obj_ar.SecurityQualityOfService =0;
HMODULE hinstLib = LoadLibrary("ntdll.dll");
ZWOS ZWopenS=(ZWOS)GetProcAddress(hinstLib,"ZwOpenSection");
ZWMV ZWmapV=(ZWMV)GetProcAddress(hinstLib,"ZwMapViewOfSection");
ZWUMV ZWunmapV=(ZWUMV)GetProcAddress(hinstLib,"ZwUnmapViewOfSection");
//調用函數,對物理內存進行映射
HANDLE hSection;
if( 0 == ZWopenS(&hSection,4,&obj_ar) &&
0 == ZWmapV(
( HANDLE )hSection, //打開Section時得到的句柄
( HANDLE )0xFFFFFFFF, //將要映射進程的句柄,
&ba, //映射的基址
0,
0xFFFF, //分配的大小
&so, //物理內存的地址
&ssize, //指向讀取內存塊大小的指針
1, //子進程的可繼承性設定
0, //分配類型
2 //保護類型
) )
//執行后會在當前進程的空間開辟一段64k的空間,并把f000:0000到f000:ffff處的內容映射到這里
//映射的基址由ba返回,如果映射不再有用,應該用ZwUnmapViewOfSection斷開映射
{
BYTE* PBiosSerial = ( BYTE* )ba;
UINT uBiosSerialLen = FindAwardBios( &pBiosSerial );
if( uBiosSerialLen == 0U )
{
uBiosSerialLen = FindAmiBios( &pBiosSerial );
if( uBiosSerialLen == 0U )
{
uBiosSerialLen = FindPhoenixBios( &pBiosSerial );
}
}
if( uBiosSerialLen != 0U )
{
CopyMemory( szSystemInfo + uSystemInfoLen, pBiosSerial, uBiosSerialLen );
uSystemInfoLen += uBiosSerialLen;
}
ZWunmapV( ( HANDLE )0xFFFFFFFF, ( void* )ba );
}
}
// 完畢, 系統特征碼已取得。