Sending a Wake-On-LAN (WOL) Magic Packet with PowerShell

Recently, I’ve had the opportunity to learn more about how WOL magic packets work. That got me thinking about how to create my own magic packet via PowerShell.

Up until this point, I hadn’t really put much thought into sending individual Wake-on-LAN (WOL) packets to individual machines in our network, seeing as it is super easy to do that by using PDQ Inventory and PDQ Deploy.

Wake-on-LAN and the Magic Packet

The format of a Wake-on-LAN (WOL) magic packet is defined as a byte array with 6 bytes of value 255 (0xFF) and 16 repetitions of the target machine’s 48-bit (6-byte) MAC address. (See Wikipedia article)

Wake-on-LAN works by broadcasting the magic packet to all network devices in a network. The network device that has a matching MAC address is instructed to be woken up, should they be configured to handle Wake-on-LAN requests.

Bytes and Byte Arrays

PowerShell is able to easily create a byte array with all this information that you can then broadcast to your target machine.

To create a byte or byte array in PowerShell, it’s a good practice to explicitly tell PowerShell that you want a value or variable to be treated as a byte/byte array. This is known as casting. If you don’t cast your bytes and byte arrays, PowerShell will often try and convert your values while manipulating them.

Here’s an example of explicitly casting a byte variable called $Byte and a byte array called $ByteArray:

[Byte] $Byte = 0x1A
[Byte[]] $ByteArray = 0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F

Since we are going to be using the MAC address of a machine to send a WOL magic packet, we’ll need to be able to convert the MAC address to a byte array. Since MAC addresses are 6 hexadecimal octets, this is really simple in PowerShell. We will just follow the example of the previous byte array:

If the MAC address was: 1A:2B:3C:4D:5E:6F

The associated byte array would be made (in PowerShell) like this:

[Byte[]] $ByteArray = 0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F

This makes constructing the WOL magic packet really simple and straightforward.

The WOL magic packet is a byte array with 6 bytes of value 255 and then 16 repetitions of the MAC address. If you wanted to write this entirely out by hand, the byte array would look something like this:

[Byte[]] $ByteArray =
   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
   0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F

That is rather repetitive and prone to error should you want to ever modify it for another MAC address.

Putting it All Together

Fortunately, there is a much easier way to write that in PowerShell. This assumes that your $Mac value uses either colons or hyphens to separate the hex values:

$Mac = "1A:2B:3C:4D:5E:6F"
$MacByteArray = $Mac -split "[:-]" | ForEach-Object { [Byte] "0x$_"}
[Byte[]] $MagicPacket = (,0xFF * 6) + ($MacByteArray  * 16)

If you’re wondering about that comma in (,0xFF * 6), there’s a good explanation on Array Literals at the Windows PowerShell blog (link here).

Now that we’ve got our official magic packet array, we need to be able to broadcast that to our subnet in order to wake up the appropriate target machine.

In order to do that, we will use .NET to create a UdpClient object which we can then use to find the broadcast address and send our magic packet. The information on the UdpClient class and methods can be found – here.

Here’s the full example of Wake-on-LAN using a magic packet and the UdpClient .net class:

$Mac = "1A:2B:3C:4D:5E:6F"
$MacByteArray = $Mac -split "[:-]" | ForEach-Object { [Byte] "0x$_"}
[Byte[]] $MagicPacket = (,0xFF * 6) + ($MacByteArray  * 16)
$UdpClient = New-Object System.Net.Sockets.UdpClient
$UdpClient.Connect(([System.Net.IPAddress]::Broadcast),7)
$UdpClient.Send($MagicPacket,$MagicPacket.Length)
$UdpClient.Close()

That wraps up this blog post. Good luck with your magic packets!