As part of our preparations for our upcoming RingZer0 “Q Division” Training, I have been working on making a software image for the FriendlyArm NanoPi R1S Single Board Computer (SBC) that we’ll be using to demonstrate some close quarters techniques. I will detail the process of configuring an R1S by installing the Armbian distribution as well as P4wnP1 ALOA. We will also take a quick look at getting USBProxy configured to act as a keylogger.
First we’re going to configure the R1S as a platform for USB attacks, making use of MaMe82‘s P4wnP1. While originally created for the Raspberry Pi Zero W, there is nothing intrinsically limiting it to that. All we really need is an SBC with a USB Device Controller (UDC), and some way of communicating with it other than over that Device Controller! The R1S fits this description perfectly, having 2 Gigabit Ethernet ports that we can use initially while setting up, but we’ll be dedicating those for Ethernet attacks eventually (which will be detailed in Part 2 of this blog post series). The R1S also has built-in WiFi, although it is not a particularly good chipset! Nonetheless, we can use it as an Access Point to allow remote access to our dropbox. We can also use the USB host port for an LTE modem or other network interfaces for longer range. But to start with, we’ll get connected using the Serial Console that Armbian provides on the USB port by default.
We’ll be building on the Armbian Buster current release (Armbian_20.02.1_Nanopi-r1_buster_current_188.8.131.52z). Download it, extract the .img file, and write it to a microSD card following the instructions on the Armbian site. I generally do something like the following, but make sure that the device you use is correct for your setup!
mount | grep mmcblk0 | while read dev rest; do sudo umount $dev done && (pv Armbian_20.02.1_Nanopi-r1_buster_current_5.4.20.img | sudo dd of=/dev/mmcblk0 bs=2048)
When that is finished, insert the micro SD card into the R1S, and connect the R1S to your computer using a microUSB cable. Make sure that the cable you choose is a data cable, not just a charging cable! After a few minutes, you should see a serial port enumerate on your host (which happens after the R1S has booted and expanded the filesystem to fill the SD card). If you don’t see a new serial port, check your cable!
You should be able to connect to the serial port using your preferred terminal emulator (I like picocom, and I believe that Putty on Windows works quite well too). You shouldn’t have to worry about the baud rate, but 115200 should be fine. Using a Linux host, the serial port enumerates as a ttyACM device, e.g. /dev/ttyACM0. Once connected, you should be greeted by the initial Armbian login/setup screen. Log in as “root” with password “1234”, then reenter the password “1234” to start changing it to a new password. Remember your new root password! You probably don’t need to create an unprivileged user, but you can if you really want to!
After interrupting (or completing the “new user account” creation process), log out, then log back in as the root user (or sudo -s from your unprivileged user if you prefer). For our bootstrapping process, we’ll connect an ethernet cable from our local network to the WAN port of the R1S. A few seconds later, the R1S should have an IP address allocated.
Now we can SSH to our R1S. I also copied my ssh public key, to make future connections simpler.
Before we get P4wnP1 running, we need to disable the USB Serial console so that P4wnP1 can manage the USB Device Controller. First, stop systemd from starting a login prompt on the device:
systemctl disable serial-getty@ttyGS0.service systemctl stop serial-getty@ttyGS0.service
Then stop the serial device from being created automatically, by preventing the g_serial module from being loaded (we’ll both unload it immediately and prevent it from being loaded again in the future):
rm /etc/modules rmmod g_serial
Now clone the P4wnP1 ALOA repo, and copy the necessary (prebuilt) parts to the right places. Ideally we’d build from scratch, but there are some errors currently in the build process. Fortunately the binaries that were built for the Raspberry Pi Zero W run just fine on the NanoPi R1S!
apt install -y dnsmasq git clone https://github.com/RoganDawes/P4wnP1_aloa cd P4wnP1_aloa mkdir -p /usr/local/P4wnP1 cp build/P4wnP1_* /usr/local/bin/ cp -r dist/* /usr/local/P4wnP1/ cp build/webapp* /usr/local/P4wnP1/www mv /usr/local/P4wnP1/P4wnP1.service /etc/systemd/system/ systemctl enable P4wnP1.service systemctl start P4wnP1.service
Now that P4wnP1 is running, you should be able to reach the P4wnP1 web interface at the same IP that you are SSH’d to, on port 8000. i.e. http://nanopi-r1:8000/. There is no authentication, because it is assumed that the network that P4wnP1 is exposed to is a trusted network.
This is a good time to test that the USB configuration is working. You should be able to choose one or more USB classes to implement using the checkboxes on the right-hand side. I typically like to implement a keyboard and mouse, and the Custom HID Device. Then make sure that USB is Enabled in the top left corner, and click Deploy.
You should see a new USB device detected by the computer that the R1S is connected to. For example, using ‘dmesg’ on your host, you should see something like:
[2316641.797152] usb 1-5: new high-speed USB device number 40 using xhci_hcd
[2316641.809806] usb 1-5: New USB device found, idVendor=1d6b, idProduct=1347, bcdDevice= 1.00
[2316641.809808] usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[2316641.809810] usb 1-5: Product: P4wnP1 by MaMe82
[2316641.809811] usb 1-5: Manufacturer: MaMe82
[2316641.809812] usb 1-5: SerialNumber: deadbeef1337
[2316641.815378] input: MaMe82 P4wnP1 by MaMe82 as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.0/0003:1D6B:1347.0028/input/input85
[2316641.867750] hid-generic 0003:1D6B:1347.0028: input,hidraw0: USB HID v1.01 Keyboard [MaMe82 P4wnP1 by MaMe82] on usb-0000:00:14.0-5/input0
[2316641.868575] input: MaMe82 P4wnP1 by MaMe82 Mouse as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.1/0003:1D6B:1347.0029/input/input86
[2316641.868921] hid-generic 0003:1D6B:1347.0029: input,hidraw1: USB HID v1.01 Mouse [MaMe82 P4wnP1 by MaMe82] on usb-0000:00:14.0-5/input1
[2316641.869892] hid-generic 0003:1D6B:1347.002A: hiddev96,hidraw2: USB HID v1.01 Device [MaMe82 P4wnP1 by MaMe82] on usb-0000:00:14.0-5/input2
If you want this USB configuration to be deployed on startup, you can click on Store, and type “startup” as the profile name. Alternatively, it can be deployed as and when necessary, under manual control.
At this point, you should have a functional P4wnP1 device, and can follow the various tutorials on the Internet on actually using the USB capabilities to attack connected devices.
NB: I found P4wnP1 to be very flaky when configured (within P4wnP1) to connect to an existing Access Point. If this is what you need, I would rather suggest using NetworkManager for this sort of configuration. In which case, I would recommend ignoring the next paragraph, as well as disabling the WiFi configuration in P4wnP1, and saving that as a startup profile.
If you do want to make use of the hotspot capabilities of the built-in Wi-Fi interface for remote access, you may wish to let P4wnP1 manage that for you, just because it doesn’t seem trivial to configure this using NetworkManager. If so, you will need to tell NetworkManager to ignore the interface, so there are no conflicts of ownership. You can do this by editing /etc/NetworkManager/NetworkManager.conf, and adding the following two lines at the bottom:
Now you can configure P4wnP1 to operate the Wi-Fi interface as an Access Point, using the “WiFi Settings” tab in the web interface. Store it as part of the “startup” profile to have it configured automatically on startup.
This can be useful when the device will be deployed in the field, and there is no familiar Wi-Fi network for it to connect to. Hiding the SSID can be useful to help keep it under the radar, so to speak. Although of course, once you start associating with it, any local Wireless IDS will spot you pretty quickly! As an alternative, you could choose to connect using an LTE dongle, or some other less obvious communications mechanism, such as a Bluetooth or 802.15.4 radio. Setting that up will not be covered here, though!
P.S.: As a bonus feature, I thought I would try setting up a keylogger, using USBProxy. Although it is marked as a “legacy” product, it still works reasonably well! The idea is that it “mirrors” a USB device plugged in to the R1S via the USB-A connector by creating identical USB gadget descriptors, and simply copying packets from one side to the other. It is probably most interesting for researching USB protocols, but out of the box it can also act as a keylogger.
I won’t go into all the details of compiling it, other than to say that you need to make sure that the libusb and libusb-dev packages are installed first. Also, by default, the keylogger functionality comes tied to a ROT13 filter, so whatever you type on the keyboard comes out transposed by 13 characters. So, before compiling, you probably want to comment out line 153, where the
PacketFilter_ROT13 plugin is added. While you are there, you should also change the
fopen call on line 143 to append to the log file, rather than open it for reading only, by changing the
"r+" parameter to
"a+". The main reason is that if the output file doesn’t yet exist, then the execution will fail. An alternative workaround is to
touch outputfile before execution.
Once compiled, you can run
usb-mitm -k to start the keylogger. This will dump the observed keystroked to stderr, which is probably not really that helpful. You can also pass an optional argument to the
-k switch, specifying a file to write to:
usb-mitm -kkeystrokes. This will record the observed keystrokes in the output file.
To conclude, we have created a USB attack platform, which can be used to inject keystrokes and mouse movements into the connected victim, as well as executing a variety of other USB attacks, such as bringing up a USB network interface, with priority routing. We can also use it as a USB keyboard sniffer, if there is an existing external USB keyboard that can be plugged via the R1S. In the next post in this series, we will look at how the R1S can also be used as an Ethernet Person in the Middle, plugged between an authorized victim and their upstream switch. In this configuration, we can make use of the victim computer’s ability to pass any Network Authentication Control mechanisms, while “hijacking” their IP and MAC addresses to make it appear that any traffic generated by the R1S actually came from the victim.