查询网卡的物理地址

作者:

在

包括出厂时的地址,以及管理员指定的地址(如果不存在,则与出厂地址相同)。

用 C++ 编译的话要给函数原型声明都加上 EXTERN_C(或者 extern “C”)。(或者干脆用 EXTERN_C 把所有的声明都包括起来( EXTERN_C { … }。)。)

(NDMP18 展示了当出厂 MAC 跟管理员指定的 MAC 不同时的输出。)

We're checking device \Device\NDMP1:
Its permanent physical address is: 12-34-56-78-90-12
Its current physical address is: 12-34-56-78-90-12

We're checking device \Device\NDMP2:
Its permanent physical address is: 11-22-33-44-55-66
Its current physical address is: 11-22-33-44-55-66

We're checking device \Device\NDMP3:
We failed to open that device, status = 0xC0000001

We're checking device \Device\NDMP4:
We failed to query its permanent physical address, status = 0xC000000D
We failed to query its current physical address, status = 0xC000000D

We're checking device \Device\NDMP5:
We failed to query its permanent physical address, status = 0xC000000D
We failed to query its current physical address, status = 0x80000005

We're checking device \Device\NDMP6:
Its permanent physical address is: AA-BB-CC-DD-EE-FF
Its current physical address is: AA-BB-CC-DD-EE-FF

We're checking device \Device\NDMP7:
Its permanent physical address is: AB-CD-EF-AB-CD-EF
Its current physical address is: AB-CD-EF-AB-CD-EF

We're checking device \Device\NDMP8:
Its permanent physical address is: 00-00-00-00-00-00
Its current physical address is: 00-00-00-00-00-00

We're checking device \Device\NDMP9:
We failed to open that device, status = 0xC0000001

We're checking device \Device\NDMP10:
We failed to query its permanent physical address, status = 0xC000000D
We failed to query its current physical address, status = 0x80000005

We're checking device \Device\NDMP11:
We failed to query its permanent physical address, status = 0xC000000D
We failed to query its current physical address, status = 0x80000005

We're checking device \Device\NDMP12:
We failed to query its permanent physical address, status = 0xC000000D
We failed to query its current physical address, status = 0x80000005

We're checking device \Device\NDMP13:
We failed to query its permanent physical address, status = 0xC000000D
We failed to query its current physical address, status = 0x80000005

We're checking device \Device\NDMP14:
We failed to query its permanent physical address, status = 0xC000000D
We failed to query its current physical address, status = 0x80000005

We're checking device \Device\NDMP15:
Its permanent physical address is: 12-34-56-78-9A-BC
Its current physical address is: 12-34-56-78-9A-BC

We're checking device \Device\NDMP16:
We failed to open that device, status = 0xC0000001

We're checking device \Device\NDMP17:
We failed to open that device, status = 0xC0000001

We're checking device \Device\NDMP18:
Its permanent physical address is: FE-DC-BA-AB-CD-EF
Its current physical address is: AB-CD-EF-FE-DC-BA

We're checking device \Device\NDMP19:
We failed to query its permanent physical address, status = 0xC000000D
We failed to query its current physical address, status = 0xC000000D

请按任意键继续. . .

#include
#include

//
// 用到的宏 / 例程等的声明。
//

#define IOCTL_NDIS_QUERY_GLOBAL_STATS 0x00170002

#define OID_802_3_PERMANENT_ADDRESS 0x01010101
#define OID_802_3_CURRENT_ADDRESS 0x01010102

#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L)
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)

typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

NTSYSAPI
VOID
NTAPI
RtlInitUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString
);

typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

#define OBJ_CASE_INSENSITIVE 0x00000040L

#define InitializeObjectAttributes(p,n,a,r,s) { \
(p)->Length = sizeof(OBJECT_ATTRIBUTES); \
(p)->RootDirectory = (r); \
(p)->Attributes = (a); \
(p)->ObjectName = (n); \
(p)->SecurityDescriptor = (s); \
(p)->SecurityQualityOfService = NULL; \
}

typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

#define FILE_OPEN 0x00000001

NTSYSAPI
NTSTATUS
NTAPI
ZwCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength
);

NTSYSAPI
NTSTATUS
NTAPI
ZwDeviceIoControlFile(
IN HANDLE DeviceHandle,
IN HANDLE Event OPTIONAL,
IN PVOID UserApcRoutine OPTIONAL,
IN PVOID UserApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferSize
);

NTSYSAPI
NTSTATUS
NTAPI
ZwClose(
IN HANDLE Handle
);

//
// MAC 地址长度。(6字节)
//

#define PHYSICAL_ADDRESS_LENGTH 6

//
// 打开设备。
//

NTSTATUS ObtainDeviceHandle(
__out PHANDLE DeviceHandle,
__in PUNICODE_STRING DeviceName
)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE LocalDeviceHandle;
NTSTATUS Status;

//
// 初始化 OBJECT_ATTRIBUTES。
//

InitializeObjectAttributes(&ObjectAttributes, DeviceName, OBJ_CASE_INSENSITIVE,
NULL, NULL);

//
// 尝试打开设备。
//

Status = ZwCreateFile(&LocalDeviceHandle, FILE_READ_ACCESS, &ObjectAttributes,
&IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0);

if (!NT_SUCCESS(Status)) {
return Status;
}

//
// 将句柄返回给调用方。
//

*DeviceHandle = LocalDeviceHandle;

return Status;
}

//
// 获取网卡信息。
//

NTSTATUS QueryNdisDeviceInformation(
__in HANDLE DeviceHandle,
__in ULONG ObjectIdentifier,
__out_bcount_opt(OutputBufferSize) PVOID OutputBuffer,
__in SIZE_T OutputBufferSize
)
{
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;

//
// 发起请求。
//

Status = ZwDeviceIoControlFile(DeviceHandle, NULL, NULL, NULL, &IoStatusBlock,
IOCTL_NDIS_QUERY_GLOBAL_STATS, (PVOID)&ObjectIdentifier, sizeof(ULONG),
OutputBuffer, OutputBufferSize);

if (!NT_SUCCESS(Status)) {
return Status;
}

return Status;
}

//
// 获取网卡 MAC 地址。
//
// 网卡 MAC 地址可以是出厂时的 MAC 地址,也可以是管理员指派的 MAC 地址。
//
// 输出参数 PhysicalAddress 至少需要 PHYSICAL_ADDRESS_LENGTH 个字节大小。
//(MAC 地址占 PHYSICAL_ADDRESS_LENGTH 字节。)
//

NTSTATUS QueryNdisDevicePhysicalAddress(
__out PUCHAR PhysicalAddress,
__in HANDLE DeviceHandle,
__in BOOLEAN PermanentPhysicalAddress
)
{
//
// 向设备查询网卡地址。
//

return QueryNdisDeviceInformation(DeviceHandle,
(PermanentPhysicalAddress ? OID_802_3_PERMANENT_ADDRESS : OID_802_3_CURRENT_ADDRESS),
(PVOID)PhysicalAddress, PHYSICAL_ADDRESS_LENGTH);
}

//
// 显示网卡信息。
//

VOID DumpNdisDevicePhysicalAddress(
__in PUNICODE_STRING DeviceName
)
{
HANDLE DeviceHandle;
BOOLEAN PermanentPhysicalAddressCandidates[] = {TRUE, FALSE};
LPCSTR PhysicalAddressDescriptions[] = {"permanent physical address", "current physical address"};
ULONG Index;
NTSTATUS Status;

//
// 打开网卡设备。
//

Status = ObtainDeviceHandle(&DeviceHandle, DeviceName);

if (!NT_SUCCESS(Status)) {
printf("We failed to open that device, status = 0x%08X\n", Status);

return;
}

//
// 对所有 PermanentPhysicalAddress 可能的取值分别查询其对应的物理地址。
//

for (Index = 0; Index < _countof(PermanentPhysicalAddressCandidates); Index++) { UCHAR PhysicalAddress[PHYSICAL_ADDRESS_LENGTH]; ULONG AddressIndex; // // 查询物理地址。 // Status = QueryNdisDevicePhysicalAddress(PhysicalAddress, DeviceHandle, PermanentPhysicalAddressCandidates[Index]); if (!NT_SUCCESS(Status)) { printf("We failed to query its %s, status = 0x%08X\n", PhysicalAddressDescriptions[Index], Status); continue; } // // 输出物理地址。 // printf("Its %s is: ", PhysicalAddressDescriptions[Index]); for (AddressIndex = 0; AddressIndex < _countof(PhysicalAddress); AddressIndex++) { if (AddressIndex) { printf("-"); } printf("%02X", PhysicalAddress[AddressIndex]); } printf("\n"); } // // 释放设备。 // ZwClose(DeviceHandle); return; } // // 判断设备是否存在。 // BOOLEAN IsDeviceExists( __in PUNICODE_STRING DeviceName ) { HANDLE DeviceHandle; NTSTATUS Status; // // 尝试打开设备。 // Status = ObtainDeviceHandle(&DeviceHandle, DeviceName); if (NT_SUCCESS(Status)) { ZwClose(DeviceHandle); } return Status != STATUS_OBJECT_NAME_NOT_FOUND; } int main() { const static WCHAR DeviceNameFormat[] = L"\\Device\\NDMP%d"; const static ULONG MaximumDeviceIndex = 10000; WCHAR DeviceNameBuffer[sizeof(DeviceNameFormat) + 12]; // ULONG 转换为十进制不会超过 12 位。 ULONG DeviceIndex; // // 枚举设备。 // DeviceIndex = 1; for (DeviceIndex = 1; DeviceIndex < MaximumDeviceIndex; DeviceIndex++) { UNICODE_STRING DeviceName; // // 构造设备名。 // wsprintfW(DeviceNameBuffer, DeviceNameFormat, DeviceIndex); RtlInitUnicodeString(&DeviceName, DeviceNameBuffer); if (!IsDeviceExists(&DeviceName)) { continue; } // // 查询设备的物理地址。 // printf("We're checking device %ls:\n", DeviceName.Buffer); DumpNdisDevicePhysicalAddress(&DeviceName); printf("\n"); } return 0; }

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注