How to discover the MAC address of machines in a network?

Solution 1:

You will have to access the information available on your managed switches. If you have an unmanaged network, I don't see a way to do that.

This is assuming the target computers are capable of Wake-on-LAN (WoL). In this case, a link to the server is established (look for the flashy link LED), and the network card is listening to WoL broadcasts. AFAIK, the card does not answer to anything in this state. If there isn't any WoL, the card most probably is off (no link LED), and it won't work at all.

Solution 2:

If the machines are not powered up, this is impossible.

If they are powered up, I would guess this is impossible as well, as you need a minimal network stack to at least answer things like ARP queries etc, which isn't working without an OS installed.

What might work (I don't know and can't test right now) is that the NIC and the switch communicate when the NIC is plugged in or powered up and the switch learns the MAC address this way. If this is the case you would need a manageable switch and query it for connected mac addresses.

Solution 3:

You can use Nmap to do a very quick ARP scan using the following syntax.

nmap -sn -PR -oX nmap.xml 192.168.1.0/24

This uses ARP ping (only ARP requests, no ICMP, UDP or TCP, no port scanning) to scan the specified IP address range and record the IP address/MAC address/Hostname responses in an XML file (nmap.xml).

I wrote a PowerShell script that munges the XML file and spits out a CSV file. This also filters out the down hosts. I find this easier to use in Excel than the XML file. Here's the script if anyone is interested.

# Define nmap input file
$NmapXMLFile = ".\nmap.xml"

# Initialize object array
$HostItems = @()

# Initialize index
$x = 0

# Load XML
[xml]$NmapXML = Get-Content $NmapXMLFile

# Loop through XML
ForEach ($HostNode in $NmapXML.nmaprun.host) {

  # Check host status
  If ($HostNode.status.state -eq "up") {

    # Create host object
    $HostObj = "" | Select-Object ID, Hostname, 'IP Address', 'MAC Address', Vendor

    # Store ID and increment index
    $HostObj.ID = $x += 1

    # Store hostname
    $HostObj.Hostname = $HostNode.hostnames.hostname.name

    # Loop through addresses
    foreach ($HostAddress in $HostNode.address) {

      # Check IP address
      If ($HostAddress.addrtype -eq "ipv4") {

        # Store IP address
        $HostObj.'IP Address' = $HostAddress.addr
      }

      # Check MAC address
      If ($HostAddress.addrtype -eq "mac") {

        # Store MAC address
        $HostObj.'MAC Address' = $HostAddress.addr

        # Store vendor
        $HostObj.Vendor = $HostAddress.vendor
      }
    }

    # Append host object to array
    $HostItems += $HostObj
  }
}

# Print host items
$HostItems

# Export host items to CSV
$HostItems | Export-CSV -NoType .\nmap.csv

Solution 4:

From a Unix machine, listening to the no-OS computers on the same LAN, and if possible via a Hub (not a Switch), you can try

arp
cat /proc/net/arp

Also you may want to try wireshark (from a OS-ed machine). Again, better to use a Hub in order to catch any communications from the BIOS machines, including broadcasts.