序列号
当前位置:首页 > 其他范文 > 序列号 > 列表页

c获取硬盘序列号

小草范文网  发布于:2017-04-21  分类: 序列号 手机版

篇一:VC++获取网卡MAC、硬盘序列号、CPU+ID、BIOS编号

VC++获取网卡MAC、硬盘序列号、CPU ID、BIOS编号

以下代码可以取得系统特征码(网卡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;

}

}

else

{

uErrorCode = 0xF0000000U + dwResult;

}

VERIFY( HeapFree( GetProcessHeap( ), 0, piai ) );

}

else

{

return FALSE;

}

}

else

{

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 Server 2003...

return FALSE;

}

else

{

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 );

}

}

// 完毕, 系统特征码已取得。

以下是其中用到的某些结构及函数的定义:

#define FILE_DEVICE_SCSI 0x0000001b

#define IOCTL_SCSI_MINIPORT_IDENTIFY ( ( FILE_DEVICE_SCSI << 16 ) + 0x0501 )

#define IOCTL_SCSI_MINIPORT 0x0004D008

#define IDENTIFY_BUFFER_SIZE 512

#define SENDIDLENGTH ( sizeof( SENDCMDOUTPARAMS ) + IDENTIFY_BUFFER_SIZE )

#define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI.

#define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA.

#define DFP_RECEIVE_DRIVE_DATA0x0007c088

typedef struct _IDSECTOR

{

USHORT wGenConfig;

USHORT wNumCyls;

USHORT wReserved;

USHORT wNumHeads;

USHORT wBytesPerTrack;

USHORT wBytesPerSector;

USHORT wSectorsPerTrack;

USHORT wVendorUnique[3];

CHAR sSerialNumber[20];

USHORT wBufferType;

USHORT wBufferSize;

USHORT wECCSize;

CHAR sFirmwareRev[8];

CHAR sModelNumber[40];

USHORT wMoreVendorUnique;

USHORT wDoubleWordIO;

USHORT wCapabilities;

USHORT wReserved1;

USHORT wPIOTiming;

USHORT wDMATiming;

USHORT wBS;

USHORT wNumCurrentCyls;

USHORT wNumCurrentHeads;

USHORT wNumCurrentSectorsPerTrack;

ULONGulCurrentSectorCapacity;

USHORT wMultSectorStuff;

ULONGulTotalAddressableSectors;

USHORT wSingleWordDMA;

USHORT wMultiWordDMA;

BYTE bReserved[128];

} IDSECTOR, *PIDSECTOR;

typedef struct _DRIVERSTATUS

{

BYTE bDriverError; // Error code from driver, or 0 if no error. BYTE bIDEStatus; // Contents of IDE Error register. // Only valid when bDriverError is SMART_IDE_ERROR. BYTE bReserved[2]; // Reserved for future expansion. DWORD dwReserved[2]; // Reserved for future expansion. } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;

typedef struct _SENDCMDOUTPARAMS

篇二:Linux下获取CPUID、硬盘序列号与 MAC地址

Linux下获取CPUID、硬盘序列号与 MAC地址

在很多系统软件的开发中,需要使用一些系统的唯一性 信息。所以,得到主机的CPUID、硬盘序列号及网卡

的MAC地址,就成个一件很重要的应用。

本人经过一番google即自己的钻研,基本上实现了这几个功能。需要的准备知识有:

1. GCC的嵌入汇编,具体的GCC嵌入汇编知识,请参考相关手册

2. ioctl系统调用,具体的调用方法,请查看手册页

获取CPUID

按照网上提供的说明,CPUID并不是所有的Intel CPU都支持的。如果支持,汇编调用为:eax置0000_0003,调用cpuid。

以下为实现代码(在我的CPU上,并没有得到):

#define cpuid(in,a,b,c,d) asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in)); static int

getcpuid (char *id, size_t max)

{

int i;

unsigned long li, maxi, maxei, ebx, ecx, edx, unused;

cpuid (0, maxi, unused, unused, unused);

maxi &= 0xffff;

if (maxi < 3)

{

return -1;

}

cpuid (3, eax, ebx, ecx, edx);

snprintf (id, max, "%08lx %08lx %08lx %08lx", eax, ebx, ecx, edx);

fprintf (stdout, "get cpu id: %s\n", id);

return 0;

}

获取硬盘序列号

这个的实现,采用的是读取/etc/mtab文件,找到/(即根目录)挂载的设备文件,然后打开它,再用系统调用 ioctl来实现的。

ioctl第二个参数为HDIO_GET_IDENTITY, 获得指定文件描述符的标志号

ioctl的第三个参数为struct hd_driveid *,在linux/hdreg.h中,struct hd_driveid的声明有

struct hd_driveid {

unsigned short config;/* lots of obsolete bit flags */

unsigned short cyls; /* Obsolete, "physical" cyls */

unsigned short reserved2;/* reserved (word 2) */

unsigned short heads; /* Obsolete, "physical" heads */

unsigned short track_bytes; /* unformatted bytes per track */

unsigned short sector_bytes;/* unformatted bytes per sector */

unsigned short sectors; /* Obsolete, "physical" sectors per track */unsigned short vendor0; /* vendor unique */

unsigned short vendor1; /* vendor unique */

unsigned short vendor2; /* Retired vendor unique */

unsigned charserial_no[20]; /* 0 = not_specified */

unsigned short buf_type; /* Retired */

unsigned short buf_size; /* Retired, 512 byte increments

* 0 = not_specified

*/

……

};

, 这其中,serial_no为硬盘的序列号。如果此项为0,则为没有提供。

思路明确了,以下为实现代码:

static int

getdiskid (char *id, size_t(转自:wWw.XiAocAoFanWeN.cOm 小 草 范文网:c获取硬盘序列号) max)

{

int fd;

struct hd_driveid hid;

FILE *fp;

char line[0x100], *disk, *root, *p;

fp = fopen ("/etc/mtab", "r");

if (fp == NULL)

{

fprintf (stderr, "No /etc/mtab file.\n");

return -1;

}

fd = -1;

while (fgets (line, sizeof line, fp) != NULL)

{

disk = strtok (line, " ");

if (disk == NULL)

{

continue;

}

root = strtok (NULL, " ");

if (root == NULL)

{

continue;

}

if (strcmp (root, "/") == 0)

{

for (p = disk + strlen (disk) - 1; isdigit (*p); p --)

{

*p = '\0';

}

fd = open (disk, O_RDONLY);

break;

}

}

fclose (fp);

if (fd < 0)

{

fprintf (stderr, "open hard disk device failed.\n");

return -1;

}

if (ioctl (fd, HDIO_GET_IDENTITY, &hid) < 0)

{

fprintf (stderr, "ioctl error.\n");

return -1;

}

close (fd);

snprintf (id, max, "%s", hid.serial_no);

fprintf (stdout, "get hard disk serial number: %s\n", id);

return 0;

}

获取MAC地址

通过创建一个socket,然后bind特定的IP地址,就可以通过ioctl得到这个套按地绑定的网络接口名称。然 后再通过网络接口名称,得到MAC地址。

如果ioctl的第二个参数为SIOCGIFNAME, 则获得指定网络接口的名称;如果ioctl的第二个参数为SIOCGIFHWADDR,则获得指定网络接口的MAC地址

ioctl的第三个参数为struct ifreq *,在linux/if.h头文件里,struct ifreq声明如下:

struct ifreq

{

#define IFHWADDRLEN 6

union

{

char ifrn_name[IFNAMSIZ];/* if name, e.g. "en0" */

} ifr_ifrn;

union {

struct sockaddr ifru_addr;

struct sockaddr ifru_dstaddr;

struct sockaddr ifru_broadaddr;

struct sockaddr ifru_netmask;

struct sockaddr ifru_hwaddr;

shortifru_flags;

int ifru_ivalue;

int ifru_mtu;

struct ifmap ifru_map;

char ifru_slave[IFNAMSIZ];/* Just fits the size */

char ifru_newname[IFNAMSIZ];

void * ifru_data;

struct if_settings ifru_settings;

} ifr_ifru;

}

, 其中,ifrn_name为网络接口的名称,ifr_ifru.ifru_hwaddr为网络接口的MAC地址。 #ifndef MAX_IFINDEX

# define MAX_IFINDEX 8

#endif

static int

getmacaddr (const char *ip, char *id, size_t max)

{

int i, sockfd;

struct sockaddr_in *loc;

struct ifreq req[1];

sockfd = socket (AF_INET, SOCK_DGRAM, 0);

if (sockfd < 0)

{

fprintf (stderr, "Unable to create socket.\n");

return -1;

}

for (i = 0; i <= MAX_IFINDEX; ++ i)

{

req->ifr_ifindex = i;

if (ioctl (sockfd, SIOCGIFNAME, req) < 0)

{

fprintf (stderr, "ioctl error: %s\n", strerror (errno));

continue;

}

if (ioctl (sockfd, SIOCGIFADDR, req) < 0)

{

fprintf (stderr, "ioctl interface index [%d] error: %s\n", i, strerror (errno)); continue;

}

loc = (struct sockaddr_in *) (&(req->ifr_ifru.ifru_addr));

if (loc->sin_addr.s_addr == inet_addr (ip))

{

fprintf (stderr, "%s bind at %s.\n", ip, req->ifr_name);

break;

}

}

if (i == MAX_IFINDEX)

{

fprintf (stderr, "input IP error.\n");

close (sockfd);

return -1;

}

if (ioctl (sockfd, SIOCGIFHWADDR, req) < 0)

{

fprintf (stderr, "ioctl error: %s\n", strerror (errno));

close (sockfd);

return -1;

}

close (sockfd);

snprintf (id, max, "%02X%02X%02X%02X%02X%02X",

req->ifr_hwaddr.sa_data[0] & 0xff,

req->ifr_hwaddr.sa_data[1] & 0xff,

req->ifr_hwaddr.sa_data[2] & 0xff,

req->ifr_hwaddr.sa_data[3] & 0xff,

req->ifr_hwaddr.sa_data[4] & 0xff,

req->ifr_hwaddr.sa_data[5] & 0xff);

fprintf (stdout, "MAC address of %s: [%s].\n", req->ifr_name, id);

return 0;

}

篇三:VC获得硬盘序列号

VC 之获取硬盘序列号

上一回,一帆风给大家讲了讲如何读取计算机的MAC地址,这次聊聊怎么获取硬盘序列号。硬盘物理序列号是硬盘的出厂序列号,它是全球都是唯一的,不会随着系统的安装、硬盘的格式化等操作而改变,跟mac地址一样都具有唯一性。 1,第一步:创建设备对象,得到设备句柄,设备为硬盘。

{

CString sFilePath;

sFilePath.Format("\\\\.\\PHYSICALDRIVE%d", driver);

HANDLE hFile=::CreateFile(sFilePath,

GENERIC_READ | GENERIC_WRITE,

FILE_SHARE_READ | FILE_SHARE_WRITE,

NULL, OPEN_EXISTING,

0, NULL);

DWORD dwBytesReturned;

GETVERSIONINPARAMS gvopVersionParams;

DeviceIoControl(hFile, //向设备对象发送SMART_GET_VERSION设备请求,获取硬盘属性

SMART_GET_VERSION,

NULL,

0,

&gvopVersionParams,

sizeof(gvopVersionParams),

&dwBytesReturned, NULL);

if(gvopVersionParams.bIDEDeviceMap <= 0) return -2;

2。第二步,发送SMART_RCV_DRIVE_DATA设备请求,获取硬盘详细信息。 // IDE or ATAPI IDENTIFY cmd

int btIDCmd = 0;

SENDCMDINPARAMS InParams;

int nDrive =0;

btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;

// 输出参数

BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];

if(DoIdentify(hFile,

&InParams,

(PSENDCMDOUTPARAMS)btIDOutCmd,

(BYTE)btIDCmd,

(BYTE)nDrive, &dwBytesReturned) == FALSE) return -3;

::CloseHandle(hFile);

DWORD dwDiskData[256];

USHORT *pIDSector; // 对应结构IDSECTOR,见头文件

pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer; for(int i=0; i < 256; i++) dwDiskData[i] = pIDSector[i];

// 取系列号

ZeroMemory(szSerialNumber, sizeof(szSerialNumber));

strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));

// 取模型号

ZeroMemory(szModelNumber, sizeof(szModelNumber));

strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));

return 0;

}

BOOL __fastcall DoIdentify( HANDLE hPhysicalDriveIOCTL,

PSENDCMDINPARAMS pSCIP,

PSENDCMDOUTPARAMS pSCOP,

BYTE btIDCmd,

BYTE btDriveNum,

PDWORD pdwBytesReturned)

{

pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;

pSCIP->irDriveRegs.bFeaturesReg = 0;

pSCIP->irDriveRegs.bSectorCountReg = 1;

pSCIP->irDriveRegs.bSectorNumberReg = 1;

pSCIP->irDriveRegs.bCylLowReg = 0;

pSCIP->irDriveRegs.bCylHighReg = 0;

pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;

pSCIP->irDriveRegs.bCommandReg = btIDCmd;

pSCIP->bDriveNumber = btDriveNum;

pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;

return DeviceIoControl( hPhysicalDriveIOCTL,

SMART_RCV_DRIVE_DATA,

(LPVOID)pSCIP,

sizeof(SENDCMDINPARAMS) - 1,

(LPVOID)pSCOP,

sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,

pdwBytesReturned, NULL);

}

char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)

{

static char szResBuf[1024];

char ss[256];

int nIndex = 0;

int nPosition = 0;

for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)

{

ss[nPosition] = (char)(dwDiskData[nIndex] / 256);

nPosition++;

// Get low BYTE for 2nd character

ss[nPosition] = (char)(dwDiskData[nIndex] % 256);

nPosition++;

}

// End the string

ss[nPosition] = '\0';

int i, index=0;

for(i=0; i<nPosition; i++)

{

if(ss[i]==0 || ss[i]==32) continue; szResBuf[index]=ss[i];

index++;

}

szResBuf[index]=0;

return szResBuf;

}

本文已影响