驱动下完美获取网卡信息方法
笔记是在写CyberInterceptor时为了UDP发包而写下的。
获取物理网卡方法:
1。遍历 注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
2。判断是否为物理网卡
判断方法1:,有miniport的时候,可以查看miniport->SymbolicLinkName
+0x0c0 SymbolicLinkName : _UNICODE_STRING "\??\PCI#VEN_11AB&DEV_4364&SUBSYS_303A17AA&REV_14#4&38d2602c&0&00E1#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{E8F7C668-870F-4C4C-BAE4-0795A3481D4A}"
如果\??\PCI打头的则为物理网卡,还有一种的是\??\usb,这种也是网卡,不过是USB无线网卡
判断方法2:就是遍历注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
下的所有位置即是物理网卡,取得GUID,如{4C3B9528-B1D7-40E6-BD83-22A7097EC44D}后,构造成\\.\\来打开设备
然后下发OID_GEN_PHYSICAL_MEDIUM,判断返回值,如果是NdisPhysicalMediumWirelessLan,即为无线网卡。
windbg //发现一般的网卡不支持OID_GEN_PHYSICAL_MEDIUM,这个OID,DeviceIoControl返回无效参数,现象是网卡的里面是NdisPhysicalMediumUnspecified,所以如果返回无效参数倒也可以认定是一般的网卡。
注:如想查看网卡支持哪些例程,可发送OID:OID_GEN_SUPPORTED_LIST,返回一个ULONG 数组,每个元素表示一个OID
网卡有3种状态要关心:
1。正常使用
2。是未连接(如网卡没有成功配置IP啥的,右下角网络连接图标打了交叉)
3。是禁用
无论处于哪种状态,上面搜索物理网卡的方法1都一样。但方法2肯定就不同了,因为当网卡禁用的时候,驱动下面根本就没miniport
驱动下最完美搜集网上信息的做法其实是:
首先用方法1搜索注册表得到物理网卡,得到其GUID,这个GUID也是对应网卡的设备名。
之后ZwOpenFile打开,如果返回不存在,其实可以断定是网卡被禁用了,或者根本不能使用的。
此时可得到禁用状态的网卡,接着给设备发OID_GEN_MEDIA_CONNECT_STATUS查询连接状态。
判断返回值NdisMediaStateConnected。是否连接。至此,网卡状态完美获取。
注:在HOOK的时候,不同Media 类型的网卡数据,会使用不同的回调接收回调,如有fddi,eth以太类型等。这个可以再发OID_GEN_MEDIA_IN_USE 这个OID获取Media 类型,这样就能HOOK相应例程
网卡没连接上的话,自然就没法用了。此类网卡略过。
有时候在获取了网卡这些状态后,还需要获取它的属性,如IP地址,MAC,方法如下:
(以下方法是通过注册表获取,可以得到本机IP地址,本机MAC地址,和网关MAC)
得到网卡GUID ={E8F7C668-870F-4C4C-BAE4-0795A3481D4A}后,
组成注册表路径 “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{E8F7C668-870F-4C4C-BAE4-0795A3481D4A}”,在里面读取IP地址,网关IP地址。
(在这个键下,EnableDHCP字段区分是否为DHCP,如果开启DHCP,DhcpIPAddress才是IP地址,DhcpDefaultGateway是网关。
否则就是静态,这个到IPAddress取IP地址,DefaultGateway取网关地址。)
获取物理网卡方法:
1。遍历 注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
2。判断是否为物理网卡,可以查看miniport->SymbolicLinkName
+0x0c0 SymbolicLinkName : _UNICODE_STRING "\??\PCI#VEN_11AB&DEV_4364&SUBSYS_303A17AA&REV_14#4&38d2602c&0&00E1#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{E8F7C668-870F-4C4C-BAE4-0795A3481D4A}"
如果\??\PCI打头的则为物理网卡,还有一种的是\??\usb,这种也是网卡,不过是USB无线网卡
网卡有3种状态要关心:
1。正常使用
2。是未连接(如网卡没有成功配置IP啥的,右下角网络连接图标打了交叉)
3。是禁用
无论处于哪种状态,上面搜索物理网卡的方法1都一样。但方法2肯定就不同了,因为当网卡禁用的时候,驱动下面根本就没miniport
驱动下最完美搜集网上信息的做法其实是:
首先用方法1搜索注册表得到物理网卡,得到其GUID,这个GUID也是对应网卡的设备名。
之后ZwOpenFile打开,如果返回不存在,其实可以断定是网卡被禁用了,或者根本不能使用的。
此时可得到禁用状态的网卡,接着给设备发OID_GEN_MEDIA_CONNECT_STATUS查询连接状态。
判断返回值NdisMediaStateConnected。是否连接。至此,网卡状态完美获取。
注:在HOOK的时候,不同Media 类型的网卡数据,会使用不同的回调接收回调,如有fddi,eth以太类型等。这个可以再发OID_GEN_MEDIA_IN_USE 这个OID获取Media 类型,这样就能HOOK相应例程
网卡没连接上的话,自然就没法用了。此类网卡略过。
有时候在获取了网卡这些状态后,还需要获取它的属性,如IP地址,MAC,方法如下:
(以下方法是通过注册表获取,可以得到本机IP地址,本机MAC地址,和网关MAC)
得到网卡GUID ={E8F7C668-870F-4C4C-BAE4-0795A3481D4A}后,
组成注册表路径 “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{E8F7C668-870F-4C4C-BAE4-0795A3481D4A}”,在里面读取IP地址,网关IP地址。
(在这个键下,EnableDHCP字段区分是否为DHCP,如果开启DHCP,DhcpIPAddress才是IP地址,DhcpDefaultGateway是网关。
否则就是静态,这个到IPAddress取IP地址,DefaultGateway取网关地址。)
关于网卡MAC地址,正如上面提到的发送OID_GEN_MEDIA_CONNECT_STATUS查询网卡状态方法一样,使用打开设备对象,然后发OID来查询:
取得{4C3B9528-B1D7-40E6-BD83-22A7097EC44D}后,构造成\\.\\来打开设备
接着发OID来获取即可。
nOid = OID_802_3_CURRENT_ADDRESS;
status = ZwDeviceIoControlFile(hDev,
NULL,
NULL,
NULL,
&IoStatusBlock,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&nOid,
sizeof(nOid),
pAIEX->pAI[uCounter].macAddress,
uTmp);
===========================
typedef enum _NDIS_MEDIUM
{
NdisMedium802_3,
NdisMedium802_5,
NdisMediumFddi,
NdisMediumWan,
NdisMediumLocalTalk,
NdisMediumDix, // defined for convenience, not a real medium
NdisMediumArcnetRaw,
NdisMediumArcnet878_2,
NdisMediumAtm,
NdisMediumWirelessWan,
NdisMediumIrda,
NdisMediumBpc,
NdisMediumCoWan,
NdisMedium1394,
NdisMediumInfiniBand,
NdisMediumMax // Not a real medium, defined as an upper-bound
} NDIS_MEDIUM, *PNDIS_MEDIUM;
//
// Physical Medium Type definitions. Used with OID_GEN_PHYSICAL_MEDIUM.
//
typedef enum _NDIS_PHYSICAL_MEDIUM
{
NdisPhysicalMediumUnspecified,
NdisPhysicalMediumWirelessLan,
NdisPhysicalMediumCableModem,
NdisPhysicalMediumPhoneLine,
NdisPhysicalMediumPowerLine,
NdisPhysicalMediumDSL, // includes ADSL and UADSL (G.Lite)
NdisPhysicalMediumFibreChannel,
NdisPhysicalMedium1394,
NdisPhysicalMediumWirelessWan,
NdisPhysicalMediumNative802_11,
NdisPhysicalMediumBluetooth,
NdisPhysicalMediumMax // Not a real physical type, defined as an upper-bound
} NDIS_PHYSICAL_MEDIUM, *PNDIS_PHYSICAL_MEDIUM;
===========================
typedef enum _NDIS_MEDIUM
{
NdisMedium802_3,
NdisMedium802_5,
NdisMediumFddi,
NdisMediumWan,
NdisMediumLocalTalk,
NdisMediumDix, // defined for convenience, not a real medium
NdisMediumArcnetRaw,
NdisMediumArcnet878_2,
NdisMediumAtm,
NdisMediumWirelessWan,
NdisMediumIrda,
NdisMediumBpc,
NdisMediumCoWan,
NdisMedium1394,
NdisMediumInfiniBand,
NdisMediumMax // Not a real medium, defined as an upper-bound
} NDIS_MEDIUM, *PNDIS_MEDIUM;
//
// Physical Medium Type definitions. Used with OID_GEN_PHYSICAL_MEDIUM.
//
typedef enum _NDIS_PHYSICAL_MEDIUM
{
NdisPhysicalMediumUnspecified,
NdisPhysicalMediumWirelessLan,
NdisPhysicalMediumCableModem,
NdisPhysicalMediumPhoneLine,
NdisPhysicalMediumPowerLine,
NdisPhysicalMediumDSL, // includes ADSL and UADSL (G.Lite)
NdisPhysicalMediumFibreChannel,
NdisPhysicalMedium1394,
NdisPhysicalMediumWirelessWan,
NdisPhysicalMediumNative802_11,
NdisPhysicalMediumBluetooth,
NdisPhysicalMediumMax // Not a real physical type, defined as an upper-bound
} NDIS_PHYSICAL_MEDIUM, *PNDIS_PHYSICAL_MEDIUM;