I've got a couple of pairs of ON Networks' PL 500 HomePlugAV Powerline Adapters and have been playing around with them to see how they compare to the Computrend 902 devices I played around with 5 years ago.
I'm still playing around with the kit, but thought I'd document a very basic example of how to send commands to the devices using Python - the instructions should work for any kit based on Qualcomm's INT6x00 and AR7x00 chipsets (mine use the AR7420/QCA7420) - we'll be changing one of the encryption keys (the NMK) that the devices use
As all management communication is via ethernet frames, we'll need to craft packets using a raw socket. The easiest way to do this is to use scapy.
As we're opening a raw socket, you'll need to run the script as root.
Setting the Encryption Key
As a simple example, we're going to set the Network Management Key (NMK). It forms a good example as we're not expecting a response so can focus on building the request rather than also having to listen for the response.
#!/usr/bin/env python # # Copyright (C) 2014 B Tasker # # import sys # sys.path.append('Scapy') # Uncomment this if you've got Scapy in a subdirectory rather than installed system wide from scapy.all import * from scapy.utils import rdpcap import fcntl, socket, struct iface='eth0' # Which interface should we use # Function from http://stackoverflow.com/questions/159137/getting-mac-address def getHwAddr(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15])) return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1] # We'll set the encryption key (NMK) to 'HomePlugAV' - 50D3E4933F855B7040784DF815AA8DB7 # # To generate a NMK, use hpavkey from open-plc-utils (https://github.com/qca/open-plc-utils) # # hpavkey -M HomePlugAV # 50D3E4933F855B7040784DF815AA8DB7 # # hpavkey -M StrongPassword # 5A11F2E2B1FDA8ABFADA70B4B1B8C674 payload='00:50:a0:00:b0:52:01:50:d3:e4:93:3f:85:5b:70:40:78:4d:f8:15:aa:8d:b7:0f:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00' data_list = payload.split(":") # Break down of payload used above # # '00' - MAC Management header (Version: 1) - they're zero indexed # '50:a0' - Request is AxA050 (Encryption key set request) # 'b0:52' - OUI # '01' - EKS (in this case - Unknown 0x01) # '50:d3:e4:93:3f:85:5b:70:40:78:4d:f8:15:aa:8d:b7' - Desired Crypto key (the NMK) # '0f' - Payload encryption key select (0x0f) # '00:00:00:00:00:00' - Destination Address # '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00' - DAK (empty in this case) # Build and send the packet p = Ether() p.src=getHwAddr(iface) p.dst='00:B0:52:00:00:01'; # Only the nearest HomeplugAV device will respond p.type=0x88e1; # HomeplugAV management frame p.oui='00b052' data=''.join(data_list).decode('hex') b = p/data ls(b) sendp(b,count=1,iface=iface)
If you run the script, the key on your local powerline device should be set to 'HomePlugAV'. Only the local device will have changed as we've used the MAC 00:B0:52:00:00:01. The reason we've done this is that it's far more complicated to change the NMK on a remote powerline device (so the example script would have been much, much longer).
If you watch with tcpdump, you should see something similar to the following
tcpdump -i eth0 ether dst host '00:B0:52:00:00:01' 17:37:46.776878 00:1e:a0:cf:87:18 (oui Unknown) > 00:b0:52:00:00:01 (oui Unknown), ethertype Unknown (0x88e1), length 60: 0x0000: 0050 a000 b052 0150 d3e4 933f 855b 7040 .P...R.P...?.[p@ 0x0010: 784d f815 aa8d b70f 0000 0000 0000 0000 xM.............. 0x0020: 0000 0000 0000 0000 0000 0000 0000 ..............
The key should also have changed on the local powerline device.