篇一: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;
}