赵斌

赵斌的博客

他的个人主页  他的博客

获取系统MAC的方法(*nux & Windows)

赵斌  2009年08月15日 星期六 01:09 | 2055次浏览 | 0条评论

原文通过blogbus2zeuux工具同步发布:http://antmanler.blogbus.com/logs/43836750.html

文章发布时间:2009/3/17/14/13

由于系统限制,代码贴不完整,需要请与我联系

PS:这几天抽空做一个写一个(linux读管道,从arp或者ifconfig匹配字符串等有2种方法,Windows下至少有4种方法,netbios, snmp, getmac, ipconfig, uuid, VBscript, JavaScript)所以比较乱,等都搞好了,再好好整理。
获取MAC地址有很多方法,总体都比较容易,今天抽了半个小时,先在Linux下实验了一下,其实方法很简单,就是通过ioctl从一个可用的socket中查询MAC地址就可以了。ioctl是设备驱动程序中对设备的I/O通道进行管理的函数, 是一个十分强大的函数,在linux下用gethostbyname获得不了本地的ip(返回是回环lo的地址)也可以用ioctl查询eth0,wlan0的ip(如果激活的话)
具体实现:
#include


#include
#include
#include
#include
#include
int
get_mac(unsigned char *mac, const char *ifname ){
/*
* This routine executes only in *nix, which support the "ioctl"
* mac : return the mac address of the device specified by ifname
* ifname : specify which device is to retrieve ( ect. eth0, wlan0 )
* Return :
* if succeed return 0, self nonzero is returned
* Author : Ant-man (Bin Zhao)
* */
int i = 0 ;

struct ifreq ifr ;
int sock_no ;
if ( (sock_no = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("error occurs when creating socket") ;
return 2 ;
}
strcpy(ifr.ifr_name, ifname) ;
if (ioctl(sock_no, SIOCGIFHWADDR, &ifr, sizeof(ifr) ) < 0) {
perror("error occurs when query the mac address") ;
return 3 ;
}
close(sock_no) ;
for(; i<6; i++ ) {
sprintf( mac+2*i, "%02x", (unsigned char)ifr.ifr_hwaddr.sa_data) ;
}
return 0 ;
}
------------------------------------------
在Python中更直接一点,虽然方法都一样
#!/usr/bin/python
import sys
import socket
import fcntl
import struct
def get_hw_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('16s16s', ifname, ''))
hwaddr = []
s.close()
ignore1, ignore2, addr_high, addr_low = struct.unpack('>16sHHL8x', info)
addr = (long(addr_high)<<32) + addr_low
b0 = addr & 0xFF
b1 = (addr >> 8) & 0xFF
b2 = (addr >> 16) & 0xFF
b3 = (addr >> 24) & 0xFF
b4 = (addr >> 32) & 0xFF
b5 = (addr >> 40) & 0xFF
return "%02X:%02X:%02X:%02X:%02X:%02X" % (b5, b4, b3, b2, b1, b0)
if __name__ == '__main__' :
print get_hw_address( sys.argv[1] )

====================================================================================================
Windows中的方法已经说了有很多了
1 一种是通过外部调用getmac或者ipconfig来获得MAC地址,步骤如下:
首先 CreateProcess 一个进程(getmac或ipconfig),并且 重定向 其标准输出设备句柄(设置进程启动信息实现)
之后读入进程的输出信息,过滤字符串获得MAC地址。这种方法比较可靠(只要没人BT的把getmac和ipconfig和谐掉)
2 还有一种方法是COM组件产生UUID时(准确说是UUID1)会使用MAC地址,此方法也可以获得MAC地址
3 如果操作系统是Windows2000即以上,还可以使用SendARP来得到MAC地址。
===================================================================================================
4 另外可以通过调用NetBios的API获得系统MAC地址,缺点是系统要安装相应协议, 而且当网线被拔掉之后无法获得正确的MAC地址,所以不是很通用。
====================================================================================================
5 对于98-Vista以及NT SP4的系统如果只有TCP/IP协议,可以使用IP Helper API的方法,并且这个方法比较简单 :
IP Helper : The Internet Protocol Helper (IP Helper) API enables the retrieval andmodification of network configuration settings for the local computer.
The IP Helper API is applicable in any computing environment whereprogrammatically manipulating TCP/IP configuration is useful. Typicalapplications include IP routing protocols and Simple Network ManagementProtocol (SNMP) agents
GetAdaptersAddresses Function :The GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer.ULONG WINAPI GetAdaptersAddresses(
__in ULONG Family,
__in ULONG Flags,
__in PVOID Reserved,
__inout PIP_ADAPTER_ADDRESSES AdapterAddresses,
__inout PULONG SizePointer
);
但是对于98的SDK还是使用的GetAdaptersInfo,所以为了兼容,还是选择GetAdaptersInfo实现
具体实现:

#include
#include
#include
#include
#include
int
get_mac(char *mac, const char *ifname )
{
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pCurrAddresses = NULL;
pAdapterInfo=(IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
ULONG bufsize = sizeof(IP_ADAPTER_INFO);
/*save device type and number*/
char dname[32] ;
int type = 6 ;
int no = 0 ;
int count = 0 ;
/*Make an initial call to GetAdaptersAddresses to get the
*size needed into the outBufLen variable*/
if(GetAdaptersInfo(pAdapterInfo,&bufsize)!=ERROR_SUCCESS) {
free(pAdapterInfo);
pAdapterInfo=(IP_ADAPTER_INFO*)malloc(bufsize);
}
/* Make a second call to GetAdapters Addresses to get the
* actual data we want*/
if(GetAdaptersInfo(pAdapterInfo,&bufsize)==NO_ERROR) {
/*parse device type and no*/
strcpy(dname, ifname) ;
/*get number of get device*/
count = strlen(dname) ;
no = dname - '0' ;
dname = '\0' ;
/*get device type*/
if ( strcmp( dname, "eth" ) == 0 ) {
type = 6 ;
} else if ( strcmp( dname, "wlan") == 0 ) {
type = 71 ;
}
count = 0 ;
pCurrAddresses = pAdapterInfo;
while (pCurrAddresses) {
if( pCurrAddresses->Type == type ) {
if ( no == count++ ) {
for(count = 0; count <6; count++ ) {
sprintf( mac+3*count, "%02x%c", (unsigned char)pCurrAddresses->Address, count == 5 ? '\0' : ':') ;
}
free(pAdapterInfo) ;
return 0 ;
}
}
pCurrAddresses = pCurrAddresses->Next;
}
free(pAdapterInfo) ;
return -1 ;
}
free(pAdapterInfo) ;
return -2;
}

====================================================================================================
6 使用VBScript或者JavaScript + WMI,只有记事本就可以通过程序获得本机的Mac地址
具体实现:
随便在哪里建立一个文本文件,扩展名改成vbs,写入以下内容, 保存,之后双击那个文件,OK,you get it
--------------------------------------------------------------------------------------
Set wmi = GetObject("winmgmts://./root/cimv2")
Set adapters = wmi.ExecQuery ("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
MacAdd = ""
LastGet = "" Rem : may get the same address more than once
For Each IP In adapters
If Not IsNull(IP.IPAddress) Then
For I = LBound(IP.IPAddress) To UBound(IP.IPAddress)
If LastGet <> IP.Macaddress(I) Then
MacAdd = MacAdd & Chr(10) & IP.Macaddress(I)
LastGet = IP.Macaddress(I)
End If
Next
End If
Next
If MacAdd<> "" Then
MsgBox( "Your MAC address is :"&MacAdd)
Else
MsgBox( "Can not find your MAC address")
End If
----------------------------------------------------------------------------------------------------
其实这个主要是利用了 WMI(Windows管理规范:Windows Management Instrumentation, 它是Windows标准的系统管理接口,通过它提供的类SQL查询语言,可以很方便的获得系统的一些信息。比如网络适配器的信息:"Win32 classes, such as Win32_NetworkAdapter or Win32_Process , monitor and manage system hardware and features. Generally, these classes are located in the rootcimv2 WMI namespace. The following table lists the Win32 class categories."
具体的大家可以看下: http://msdn.microsoft.com/en-us/library/aa394582.aspx
上面的代码加入了些出错机制,所以使用了19行之多,主要防止重复的获得MAC地址,其实还可以再短些:
Set wmi = GetObject("winmgmts://./root/cimv2")
Set adapters = wmi.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
For Each IP In adapters
MsgBox( "Your MAC address is :"& IP.Macaddress(0))
Next
====================================================================================================
7 其实用批处理也可以

评论

我的评论:

发表评论

请 登录 后发表评论。还没有在Zeuux哲思注册吗?现在 注册 !

暂时没有评论

Zeuux © 2024

京ICP备05028076号