天天看点

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;

            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;