When dealing with network devices that only have BIOS (no OS), traditional discovery methods like ARP or ping won't work. We need low-level network scanning techniques that can detect devices at the hardware level.
Here are several reliable approaches to discover MAC addresses in various network scenarios:
1. Using ARP Scanning (For OS-Enabled Devices)
For machines with an operating system, ARP scanning is the most straightforward method:
import scapy.all as scapy
def arp_scan(ip_range):
answered = scapy.arping(ip_range, verbose=False)[0]
devices = []
for sent, received in answered:
devices.append({'ip': received.psrc, 'mac': received.hwsrc})
return devices
print(arp_scan("192.168.1.1/24"))
2. DHCP Server Logs Inspection
Checking DHCP server logs can reveal MAC addresses of all devices that requested IP addresses:
# For Linux DHCP servers:
cat /var/log/dhcpd.log | grep "DHCPDISCOVER"
3. Wake-on-LAN Packet Detection
For BIOS-only machines, sending WoL packets can help identify devices:
from wakeonlan import send_magic_packet
def discover_wol_devices(mac_prefix, ip_range):
# Implement your discovery logic here
pass
For devices without an OS, we need to use more sophisticated methods:
1. Network Switch MAC Address Tables
Most managed switches maintain MAC address tables:
# Cisco switches:
show mac address-table
2. Using nmap for Raw Packet Scanning
Nmap can perform various low-level scans:
nmap -sn -PR 192.168.1.0/24
3. Custom UDP Broadcast Probes
Creating custom broadcast probes can elicit responses from BIOS devices:
import socket
def send_bios_probe():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.sendto(b"BIOS_DISCOVERY_PROBE", ('255.255.255.255', 9))
# Implement response handling
When performing network scans:
- Always get proper authorization
- Limit scan frequency to avoid network congestion
- Be aware of legal implications in your jurisdiction
For BIOS machines intended for network booting, PXE servers maintain MAC records:
# Typical PXE config file location:
/etc/dhcp/dhcpd.conf
When dealing with machines in PXE boot state (only BIOS active), traditional network scanning methods often fail. These machines typically:
- Don't respond to ICMP ping requests
- Lack ARP cache entries until network boot initiates
- Have no listening TCP/UDP services
Here are three reliable approaches to discover MAC addresses in such scenarios:
1. DHCP Server Log Inspection
Most enterprise DHCP servers log MAC addresses of PXE clients. For ISC DHCP servers:
# Sample ISC DHCP log entry
tail -f /var/log/dhcpd.log | grep "DHCPDISCOVER"
# Output format: DHCPDISCOVER from aa:bb:cc:dd:ee:ff via eth0
2. ARP Cache Monitoring During PXE Boot
Trigger ARP discovery during the brief window when PXE clients communicate:
# Linux script to capture ARP entries
#!/bin/bash
while true; do
ip -s -s neigh flush all
sleep 2
arp -an | grep -v incomplete
done
3. Packet Sniffing with tcpdump
Capture DHCP/BOOTP packets which always contain MAC addresses:
# Capture PXE-related traffic
tcpdump -i eth0 -nn -v port bootpc or port bootps
# Filter for MAC addresses
tcpdump -i eth0 -nn -e -q | grep -E 'BOOTP|DHCP' | awk '{print $2,$8}'
Here's a complete Python solution using scapy:
from scapy.all import sniff, DHCP, BOOTP
import sys
def handle_dhcp(pkt):
if pkt.haslayer(DHCP):
mac = pkt[BOOTP].chaddr[:6].hex(':')
print(f"Discovered MAC: {mac} via DHCP Option {pkt[DHCP].options[0][1]}")
print("Starting DHCP monitor...")
sniff(filter="udp and (port 67 or 68)", prn=handle_dhcp, store=0)
For large deployments, consider:
- Wireshark's TShark for continuous monitoring
- Custom ELK stack integration with DHCP logs
- SNMP polling of network switches' bridge tables
Always cross-verify discovered MACs with:
# Compare with switch MAC tables
show mac address-table dynamic | include [VLAN_ID]