First of all, thank Jzyhummel (blade [federation]) Brothers provide some information ^ _ ^
The concept of the NIC address is a bit confusing. Because there are two addresses, MAC addresses, and physical addresses, I usually say the network card address, I refer to the physical address, I don't know how others see? The physical address refers to the address of the ROM of the storage address on the NIC. The MAC address is this. The address used when the block card works, in general, the two addresses are the same, so many people are mixed, even don't know the difference --_- #
When the NIC works, an Ethernet frame 60 to 1514 (excluding CRC), the Crc of the frame is automatically added, and the preamble is automatically added. The NIC destination address and source address are driver added. So what address is used when the NIC work is used as a working address is determined by the driver :) Therefore, we can use it without changing the physical address of the NIC. The software method changes the work address of the specific NIC.
The MAC address is typically saved in the registry, which can be modified, so there is a question:
First, you can use the IP of the impulse.
2nd, you can break some garbage encryption software ...
Many software is encrypted through the NIC address, there are two different. Some of the better than the physical address is encrypted. Some are encrypted by work addresses. The address obtained by working address encryption is a MAC address. This method can generally be cracked. It is a bit difficult to encrypt through physical address, but it is not no way.
Take three ways to obtain the network card MAC address in the system
Author: QinJia
The first method uses Microsoft's NetBIOS API. This is a set of commands that provide underlying networks through Winsock. The biggest disadvantage using NetBIOS is that you must have a NetBIOS service in your system (if you enable file sharing in your Windows network, this is not a problem). In addition, this method is fast and accurate.
The NetBIOS API only includes a function, just called NetBIOS. This function uses the Network Control Block structure as a parameter, which tells the function to do. The definition of the structure is as follows:
Typedef struct _ncb {
UCHAR NCB_COMMAND;
Uchar NCB_RETCODE;
Uchar NCB_LSN;
Uchar NCB_NUM;
PuChar NCB_Buffer;
Word NCB_LENGTH;
Uchar ncb_callname [ncbnamsz];
Uchar NCB_NAME [NCBNAMSZ];
Uchar ncb_rto;
Uchar ncb_sto;
Void (Callback * NCB_POST) (Struct _ncb *);
Uchar NCB_LANA_NUM;
UCHAR NCB_CMD_CPLT;
#ifdef_win64
Uchar NCB_RESERVE [18];
#ELSE
Uchar NCB_RESERVE [10];
#ENDIF
Handle NCB_EVENT;
} NCB, * PNCB;
The focus is on NCB_COMMAND members. This member tells NetBIOS what should I do. We use three commands to detect the MAC address. They are defined in MSDN as follows:
Command description:
NcBenum Windows NT / 2000: Enumerally listing the number of network cards in the system. After using this command, the NCB_BUFFER member points to the buffer filled by the LANA_ENUM structure.
Ncbenum is not a standard NetBIOS 3.0 command.
Ncbreset reset the network card. The NIC must reset before accepting the new NCB command.
NCBastat accepts the status of the local or remote interface card. After using this command, the NCB_Buffer member points to the buffer filled by the Adapter_status structure, followed by an array of Name_Buffer structures.
Below is the step of getting your system MAC address:
1 "Click all interface cards.
2 "Reset each card to obtain its correct information.
3 "Query the interface card, get the MAC address and generate a standard colonial separation format. Here is an example source program.
#include
#include
#include
#include
#include
Using namespace std;
#define Bzero (Thing, SZ) MEMSET (Thing, 0, SZ)
Bool getAdapterInfo (int adapter_num, string & mac_addr)
{
// Reset the NIC, so that we can query
NCB NCB;
MEMSET (& NCB, 0, SIZEOF (NCB));
Ncb.ncb_command = ncbreset;
Ncb.ncb_lana_num = adapter_num;
IF (NetBIOS (& NCB)! = nrc_goodret) {
Mac_addr = "BAD (NCBRESET):"
Mac_addr = String (ncb.ncb_retcode);
Return False;
}
// Prepare the status block of the interface card
Bzero (& NCB, SIZEOF (NCB);
Ncb.ncb_command = ncbastat;
Ncb.ncb_lana_num = adapter_num;
STRCPY ((char *) ncb.ncb_callname, "*");
Struct astat
{
Adapter_Status Adapt;
Name_Buffer NameBuff [30];
Adapter;
Bzero (& Adapter, SizeOf (Adapter);
Ncb.ncb_buffer = (unsigned char *) & adapter;
Ncb.ncb_length = sizeof (adapter);
// Get information on the network card, and if the network card is working properly, return to the standard colonial separation format.
IF (NetBIOS (& NCB) == 0)
{
CHAR ACMAC [18];
Sprintf (ACMAC, "% 02x:% 02x:% 02x:% 02x:% 02x:% 02x",
Int (adapter.adapt.adapter_address [0]),
Int (adapter.adapt.adapter_address [1]),
Int (adapter.adapt.adapter_address [2]),
Int (adapter.adapt.adapter_address [3]),
Int (adapter.adapt.adapter_address [4]),
Int (Adapter.Adapt.adapter_address [5])));
Mac_ADDR = ACMAC;
Return True;
}
Else
{
Mac_addr = "BAD (NCBastat):";
Mac_addr = String (ncb.ncb_retcode);
Return False;
}
}
int main ()
{
// get a list of network cards
LANA_ENUM AdapterList;
NCB NCB;
MEMSET (& NCB, 0, SIZEOF (NCB));
Ncb.ncb_command = ncbenum;
Ncb.ncb_buffer = (unsigned char *) & adapterlist;
Ncb.ncb_length = sizeof (adapterlist); NetBIOS (& NCB);
/ / Get the address of the local Ethernet card
String mac_addr;
For (int i = 0; i { IF (getAdapterInfo (AdapterList.lana, Mac_ADDR)) { COUT << "adapter" << int (adapterlist.lana) << "'s MAC IS" << Mac_ADDR << Endl; } Else { CERR << "failed to get mac address! do you" << ENDL; CERR << "HAVE THE NetBIOS Protocol installed?" << endl; Break; } } Return 0; } Second method - use COM Guid API This method uses the COM API to create a GUID (globally unique identifier) and inherit the MAC address there. GUID is usually used to identify COM components and other objects in the system. They are calculated from the MAC address (combined with other things), and the MAC address on the surface is included there. I said that the surface is because it doesn't contain it. I provide this approach to more than a brock. You may use this method to get the MAC address, but sometimes you only get a random hexadecimal value. The following example is very simple, there is no need to talk more. We use CocreateGuid to create a GUID and place the last six bytes in a string. They may be a MAC address, but it is not necessarily. #include #include #include Using namespace std; int main () { COUT << "Mac Address IS:" / / A UUID to COM. If there is an Ethernet card in the machine, // UUID The last six bytes (2-7 bytes of DATA4) should be the MAC address of the local Ethernet card. Guid UUID; CocreateGuid (& UUID); // Spit the address OUT Char mac_addr [18]; Sprintf (Mac_ADDR, "% 02x:% 02x:% 02x:% 02x: 02x:% 02x", UUID.DATA4 [2], UUID.DATA4 [3], uuid.data4 [4], UUID.DATA4 [5], UUID.DATA4 [6], UUID.DATA4 [7]); Cout << mac_addr << Endl; Getch (); Return 0; } Third Method - Extended API using SNMP The third method I want to discuss is to use the Windows SNMP (Simple Network Management Protocol) to achieve the MAC address. In my experience, this agreement is simple. The code is also forwarded. Basic steps and NetBIOS: 1 "Get a list of network cards 2 "Query the type and MAC address of each card 3 "Save the current network card I personally know much about SNMP, but if I just said, the code is very clear. #include #include #include Typedef Bool (WinApi * psnmpextensioninit) In DWord Dwtimezeroreference, Out Handle * HpollFortrapevent, Out asnobjectiDentifier * advtededView); Typedef Bool (WinAPI * PsnmpextensionTrap) ( Out asnobjectiDentifier * Enterprise, Out asninteger * genericTrap, Out Asninteger * Specifictrap, Out asntimeticks * TimeStamp, Out RFC1157VARBINDLIST * VARIABIBINDINGS); Typedef Bool (WinApi * PsnmpextensionQuery) In Byte RequestType, In out RFC1157VARBINDLIST * VARIABLEBINDINGS, Out asninteger * Errorstatus, Out asninteger * errorindex); TypedEf Bool (WinApi * PsnmpextensionInitex) Out asnobjectiDentifier * advtededView); void main () { Hinstance m_hinst; PSNMPEXTENSIONIT M_INIT; PSNMPEXTENSIONITEX M_INITEX; PSNMPEXTENSIONQUERY M_QUERY; PSNMPEXTENSIONTRAP M_TRAP; Handle pollfortrapevent; AsnObjectidentifier supportedView; Uint oid_ifentrytype [] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3}; Uint oid_ifentrynum [] = {1, 3, 6, 1, 2, 1, 2, 1}; Uint Oid_ipmacentaddr [] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6}; AsnObjectidentifier MIB_IFMACENTADDR = {SIZEOF (OID_IPMACENTDR) SIZEOF (UINT), OID_IPMACENTDR}; AsnObjectIdentifier MIB_IFENTRYTYPE = {SIZEOF (OID_IFENTRYTYPE) SIZEOF (UINT), OID_IFENTRYTYPE}; AsnObjectIdentifier MIB_IFENTRYNUM = {SizeOf (OID_IFENTRYNUM) SIZEOF (UINT), OID_IFENTRYNUM}; RFC1157VARBINDLIST VARBINDLIST; RFC1157VARBIND VARBIND [2]; Asninteger Errorstatus; Asninteger Errorindex; AsnObjectidentifier MIB_NULL = {0, 0}; int R; INT DTMP; INT i = 0, j = 0; Bool Found = false; CHAR TEMPETHERNET [13]; m_init = NULL; m_initex = NULL; m_Query = null; m_trap = NULL; / * Load SNMP DLL and get an instance handle * / m_hinst = loadingLibrary ("inetmib1.dll"); IF (M_HINST <(Hinstance) Hinstance_ERROR) { M_HINST = NULL; Return; } m_init = (PSNMPEXTENSIONIT) GetProcaddress (M_HINST, "SNMPEXTensionInit"); m_initex = (PSNMPEXTENSIONITEX) GETPROCADDRESS (M_HINST, "Snmpextensioninitex"); m_query = (PSNMPEXTensionQuery) getProcaddress (m_hinst, "SnmpextensionQuery"); m_trap = (PSNMPEXTENSIONTRAP) GetProcaddress (M_HINST, "SNMPEXTensionTrap"); M_init (GetTickCount (), & supportView; / * Initialization to receive variable lists of M_Query query results * / Varbindlist.list = varbind; Varbind [0] .name = mib_null; Varbind [1] .name = mib_null; / * Copy in OID and look up the number of portals in the interface table * / VarbindList.len = 1; / * Only Retrieving One Item * / SNMP_OIDCPY (& Varbind [0] .name, & mib_ifentrynum); Ret = M_Query (asn_rfc1157_getnextRequest, & varbindlist, & errostatus, & Errorindex); PRINTF ("# of adapters in this system:% in", Varbind [0] .value.asnvalue.number; VarbindList.len = 2; / * Copy OID IFTYPE-Interface Type * / SNMP_OIDCPY (& Varbind [0] .Name, & MIB_IFENTRYTYPE); / * Copy OID IFPHYSADDRESS- Physical Address * / SNMP_OIDCPY (& Varbind [1] .Name, & MIB_IFMACENTDR); DO { / * Submit the query, and the result will be loaded into VarbindList. It can be expected that the number of cyclic calls and the number of interface cards in the system are equal. * / Ret = M_Query (asn_rfc1157_getnextRequest, & varbindlist, & errostatus, & Errorindex); IF (! RET) Ret = 1; Else / * Confirm the correct return type * / Ret = snmp_oidncmp (& varbind [0] .name, & mib_ifenTrytype, MIB_IFENTRYTYPE.IDLENGTH); IF (! RET) { J ; DTMP = varbind [0] .value.asnvalue.number; Printf ("Interface #% I Type:% IN", J, DTMP); / * Type 6 Describes Ethernet Interfaces * / IF (DTMP == 6) { / * Confirm that we have obtained the address here * / Ret = SNMP_OIDNCMP (& Varbind [1] .name, & mib_ifmacentaddr, mib_ifmacentaddr.idlength; IF ((! Ret) && (Varbind [1] .value.asnvalue.address.Stream! = null)) { IF (varbind [1] .value.asnvalue.address.Stream [0] == 0x44) && (Varbind [1] .Value.asnvalue.address.Stream [1] == 0x45) && (VARBIND [1] .value.asnvalue.address.stream [2] == 0x53) && (VARBIND [1] .value.asnvalue.address.Stream [3] == 0x54) && (VARBIND [1] .Value.asnvalue.address.Stream [4] == 0x00)) { / * Ignore all dial-up network interface cards * / Printf ("Interface #% i is a dun adaptern", j); CONTINUE; } IF ((varbind [1] .value.asnvalue.address.Stream [0] == 0x00) && (Varbind [1] .value.asnvalue.address.Stream [1] == 0x00) && (VARBIND [1] .value.asnvalue.address.Stream [2] == 0x00) && (Varbind [1] .value.asnvalue.address.Stream [3] == 0x00) && (VARBIND [1] .value.asnvalue.address.Stream [4] == 0x00) && (VARBIND [1] .Value.asnvalue.address.Stream [5] == 0x00)) { / * Ignore the NULL address returned by other network interface cards * / Printf ("Interface #% i is a null addressn", j); CONTINUE; } Sprintf (Tempethernet, "% 02x% 02x% 02x% 02x% 02x% 02x", Varbind [1] .value.asnvalue.address.Stream [0], Varbind [1] .value.asnvalue.address.Stream [1], Varbind [1] .value.asnvalue.address.Stream [2], Varbind [1] .value.asnvalue.address.Stream [3], Varbind [1] .value.asnvalue.address.Stream [4], Varbind [1] .value.asnvalue.address.Stream [5]); Printf ("Mac Address of Interface #% i:% SN", J, Tempethernet; } } } While (! RET); / * Error termination. * / Getch (); Freelibrary (m_hinst); / * Release binding * / SNMP_FREEVARBIND (& Varbind [0]); SNMP_FREEVARBIND (& Varbind [1]); } The method of getting a physical address is different for different network cards, but it is to operate the IO port, the specific address of the port should see the specification of the specific chip. Encryption software should get a physical address and cannot use this method. In general, it is obtained by NDISREQUEST in the core state. A method of applying a layer is provided here. If you want to pull NDisRequest, you have to travel, or stop ... NDIS specification, the NIC driver supports the ioctl_ndis_query_stats interface: The parameters are as follows: OID_802_3_Permanent_Address: Physical Address OID_802_3_current_address: MAC Address So our approach is obtained. First, look at the registry, find a few pieces of network card, what equipment name is it. The specific location is related to the OS, 2000 under HLM / Software / Microsoft / Windows NT / Current Version / NetworkCards. Then CreateFile (DeviceName, ...) pay attention to use LinkName, so Also add ".//device//". Then DeviceioControl (hmac, ioctl_ndis_query_stats, OID_802_3_Permanent_Address / OID_802_3_current_address ...) Specific cases can see DDK OID_802_3_current_address entry. So we got the MAC address and physical address. -------------------------------------------------- ------------------------------ Jzyhummel (Blade [Braided]) said: About how to modify the MAC address, there is not much necessary, anyway, and the registry, how to modify the network card physical address, etc. You can read or modify directly from EEPROM (eg 8029as. 93C 46 chip) However, the chip of the NIC is different, and the reading method is different. If you read 8029as EEPROM's OFFSet 0001H; actual Address I / O 01 The MAC is deposited in the Address 1H, 2H, 3H in EEPROM; Read 8139C (L) EEPROM 93C 46) 里 OFFSET 0050H; actual I / O 0x50 The MAC is deposited in EEPROM, ADDRESS 7H, 8H, 9H; The system actually used in the REGISTER of 8139chin, the offset address is 0000H, 0001H, 0002H, 0003H, 0004H, 0005H