以下代码可以取得系统特征码(网卡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;
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
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_data 0x0007c088
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;
ulong ulcurrentsectorcapacity;
ushort wmultsectorstuff;
ulong ultotaladdressablesectors;
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
dword cbuffersize; // size of bbuffer in bytes
driverstatus driverstatus; // driver status structure.
byte bbuffer[1]; // buffer of arbitrary length in which to store the data read from the // drive.
} sendcmdoutparams, *psendcmdoutparams, *lpsendcmdoutparams;
typedef struct _srb_io_control
ulong headerlength;
uchar signature[8];
ulong timeout;
ulong controlcode;
ulong returncode;
ulong length;
} srb_io_control, *psrb_io_control;
typedef struct _ideregs
byte bfeaturesreg; // used for specifying smart "commands".
byte bsectorcountreg; // ide sector count register
byte bsectornumberreg; // ide sector number register
byte bcyllowreg; // ide low order cylinder value
byte bcylhighreg; // ide high order cylinder value
byte bdriveheadreg; // ide drive/head register
byte bcommandreg; // actual ide command.
byte breserved; // reserved for future use. must be zero.
} ideregs, *pideregs, *lpideregs;
typedef struct _sendcmdinparams
dword cbuffersize; // buffer size in bytes
ideregs irdriveregs; // structure with drive register values.
byte bdrivenumber; // physical drive number to send
// command to (0,1,2,3).
byte breserved[3]; // reserved for future expansion.
dword dwreserved[4]; // for future use.
byte bbuffer[1]; // input buffer.
} sendcmdinparams, *psendcmdinparams, *lpsendcmdinparams;
typedef struct _getversionoutparams
byte bversion; // binary driver version.
byte brevision; // binary driver revision.
byte breserved; // not used.
byte bidedevicemap; // bit map of ide devices.
dword fcapabilities; // bit mask of driver capabilities.
dword dwreserved[4]; // for future use.
} getversionoutparams, *pgetversionoutparams, *lpgetversionoutparams;
//////////////////////////////////////////////////////////////////////
//结构定义
typedef struct _unicode_string
ushort length;//长度
ushort maximumlength;//最大长度
pwstr buffer;//缓存指针
} unicode_string,*punicode_string;
typedef struct _object_attributes
ulong length;//长度 18h
handle rootdirectory;// 00000000
punicode_string objectname;//指向对象名的指针
ulong attributes;//对象属性00000040h
pvoid securitydescriptor; // points to type security_descriptor,0
pvoid securityqualityofservice; // points to type security_quality_of_service,0
} object_attributes;
typedef object_attributes *pobject_attributes;
//函数指针变量类型
typedef dword (__stdcall *zwos )( phandle,access_mask,pobject_attributes);
typedef dword (__stdcall *zwmv )( handle,handle,pvoid,ulong,ulong,plarge_integer,psize_t,dword,ulong,ulong);
typedef dword (__stdcall *zwumv )( handle,pvoid);
bool winnthdserialnumasscsiread( byte* dwserial, uint* puseriallen, uint umaxseriallen )
bool binfoloaded = false;
for( int icontroller = 0; icontroller < 2; ++ icontroller )
handle hscsidriveioctl = 0;
char szdrivename[256];
// try to get a handle to physicaldrive ioctl, report failure
// and exit if can't.
sprintf( szdrivename, "\\\\.\\scsi%d:", icontroller );
// windows nt, windows 2000, any rights should do
hscsidriveioctl = createfile( szdrivename,
generic_read | generic_write,
file_share_read | file_share_write, null,
open_existing, 0, null);
// if (hscsidriveioctl == invalid_handle_value)
// printf ("unable to open scsi controller %d, error code: 0x%lx\n",
// controller, getlasterror ());
if( hscsidriveioctl != invalid_handle_value )
int idrive = 0;
for( idrive = 0; idrive < 2; ++ idrive )
char szbuffer[sizeof( srb_io_control ) + sendidlength] = { 0 };
srb_io_control* p = ( srb_io_control* )szbuffer;
sendcmdinparams* pin = ( sendcmdinparams* )( szbuffer + sizeof( srb_io_control ) );
dword dwresult; http://www.it55.com/
p->headerlength = sizeof( srb_io_control );
p->timeout = 10000;
p->length = sendidlength;
p->controlcode = ioctl_scsi_miniport_identify;
strncpy( ( char* )p->signature, "scsidisk", 8 );
pin->irdriveregs.bcommandreg = ide_ata_identify;
pin->bdrivenumber = idrive;
if( deviceiocontrol( hscsidriveioctl, ioctl_scsi_miniport,
szbuffer,
sizeof( srb_io_control ) + sizeof( sendcmdinparams ) - 1,
sizeof( srb_io_control ) + sendidlength, it资讯之家 http://www.it55.com
&dwresult, null ) )
sendcmdoutparams* pout = ( sendcmdoutparams* )( szbuffer + sizeof( srb_io_control ) );
idsector* pid = ( idsector* )( pout->bbuffer );
if( pid->smodelnumber[0] )
{
if( * puseriallen + 20u <= umaxseriallen )
{
// 序列号
copymemory( dwserial + * puseriallen, ( ( ushort* )pid ) + 10, 20 );
// cut off the trailing blanks
for( uint i = 20; i != 0u && ' ' == dwserial[* puseriallen + i - 1]; -- i )
{}
* puseriallen += i;
// 型号
copymemory( dwserial + * puseriallen, ( ( ushort* )pid ) + 27, 40 );
for( i = 40; i != 0u && ' ' == dwserial[* puseriallen + i - 1]; -- i )
* puseriallen += i; it55.com
binfoloaded = true;
}
else
::closehandle( hscsidriveioctl );
return binfoloaded;
}
}
::closehandle( hscsidriveioctl );
return binfoloaded;
}
bool doidentify( handle hphysicaldriveioctl, psendcmdinparams pscip,
psendcmdoutparams pscop, byte bidcmd, byte bdrivenum,
pdword lpcbbytesreturned )
// set up data structures for identify command.
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;
// calc the drive number.
pscip->irdriveregs.bdriveheadreg = 0xa0 | ( ( bdrivenum & 1 ) << 4 );
// the command can either be ide identify or atapi identify.
pscip->irdriveregs.bcommandreg = bidcmd;
pscip->bdrivenumber = bdrivenum;
pscip->cbuffersize = identify_buffer_size;
return deviceiocontrol( hphysicaldriveioctl, dfp_receive_drive_data,
( lpvoid ) pscip,
sizeof( sendcmdinparams ) - 1,
( lpvoid ) pscop,
sizeof( sendcmdoutparams ) + identify_buffer_size - 1,
lpcbbytesreturned, null );
bool winnthdserialnumasphysicalread( byte* dwserial, uint* puseriallen, uint umaxseriallen )
#define dfp_get_version 0x00074080
for( uint udrive = 0; udrive < 4; ++ udrive )
handle hphysicaldriveioctl = 0;
// and exit if can't.
char szdrivename [256];
sprintf( szdrivename, "\\\\.\\physicaldrive%d", udrive );
// windows nt, windows 2000, must have admin rights
hphysicaldriveioctl = createfile( szdrivename,
file_share_read | file_share_write, null, open_existing, 0, null);
if( hphysicaldriveioctl != invalid_handle_value )
getversionoutparams versionparams = { 0 };
dword cbbytesreturned = 0;
// get the version, etc of physicaldrive ioctl
if( deviceiocontrol( hphysicaldriveioctl, dfp_get_version,
null,
0,
&versionparams,
sizeof( getversionoutparams ),
&cbbytesreturned, null ) )
// if there is a ide device at number "i" issue commands
// to the device
if( versionparams.bidedevicemap != 0 )
{
byte bidcmd = 0; // ide or atapi identify cmd
sendcmdinparams scip = { 0 };
// now, get the id sector for all ide devices in the system.
// if the device is atapi use the ide_atapi_identify command,
// otherwise use the ide_ata_identify command
bidcmd = ( versionparams.bidedevicemap >> udrive & 0x10 ) ? ide_atapi_identify : ide_ata_identify;
byte idoutcmd[sizeof( sendcmdoutparams ) + identify_buffer_size - 1] = { 0 };
if( doidentify( hphysicaldriveioctl,
&scip,
( psendcmdoutparams )&idoutcmd,
( byte )bidcmd,
( byte )udrive,
&cbbytesreturned ) )
{ if( * puseriallen + 20u <= umaxseriallen )
copymemory( dwserial + * puseriallen, ( ( ushort* )( ( ( psendcmdoutparams )idoutcmd )->bbuffer ) ) + 10, 20 ); // 序列号
for( uint i = 20; i != 0u && ' ' == dwserial[* puseriallen + i - 1]; -- i ) {}
copymemory( dwserial + * puseriallen, ( ( ushort* )( ( ( psendcmdoutparams )idoutcmd )->bbuffer ) ) + 27, 40 ); // 型号
for( i = 40; i != 0u && ' ' == dwserial[* puseriallen + i - 1]; -- i ) {}
::closehandle( hphysicaldriveioctl );
closehandle( hphysicaldriveioctl );
return binfoloaded;
uint findawardbios( byte** ppbiosaddr )
byte* pbiosaddr = * ppbiosaddr + 0xec71;
byte szbiosdata[128];
copymemory( szbiosdata, pbiosaddr, 127 );
szbiosdata[127] = 0;
int ilen = lstrlen( ( char* )szbiosdata );
if( ilen > 0 && ilen < 128 )
//award: 07/08/2002-i845g-ite8712-jf69vd0cc-00
//phoenix-award: 03/12/2002-sis645-p4s333
if( szbiosdata[2] == '/' && szbiosdata[5] == '/' )
byte* p = szbiosdata;
while( * p )
if( * p < ' ' || * p >= 127 )
break;
++ p;
if( * p == 0 )
* ppbiosaddr = pbiosaddr;
return ( uint )ilen;
}
return 0;
uint findamibios( byte** ppbiosaddr )
byte* pbiosaddr = * ppbiosaddr + 0xf478;
// example: "ami: 51-2300-000000-00101111-030199-"
if( szbiosdata[2] == '-' && szbiosdata[7] == '-' )
byte* p = szbiosdata;
* ppbiosaddr = pbiosaddr;
uint findphoenixbios( byte** ppbiosaddr )
uint uoffset[3] = { 0x6577, 0x7196, 0x7550 };
for( uint i = 0; i < 3; ++ i )
{
byte* pbiosaddr = * ppbiosaddr + uoffset[i];
byte szbiosdata[128];
copymemory( szbiosdata, pbiosaddr, 127 );
szbiosdata[127] = 0;
int ilen = lstrlen( ( char* )szbiosdata );
if( ilen > 0 && ilen < 128 )
// example: phoenix "nitelt0.86b.0044.p11.9910111055"
if( szbiosdata[7] == '.' && szbiosdata[11] == '.' )
byte* p = szbiosdata;
while( * p )
if( * p < ' ' || * p >= 127 )
break;
++ p;
if( * p == 0 )
* ppbiosaddr = pbiosaddr;
return ( uint )ilen;