Programming, philosophy, pedaling.

Exploring Square's S6 reader at DEF CON

Aug 10, 2019

Tags: security, reverse-engineering

This will be a stream of consciousness as I take a look at Square's S6 reader. I'm not a hardware person whatsoever, so it'll be a pretty superficial exploration.

First steps

The S6 is pretty inconspicuous looking:

S6 reader

The FCC ID (2AF3K-1SQHW) is the only identifier on it, apart from a (presumably) unique serial number.

I tried plugging it in, with some initial results in lsusb and dmesg:

S6 lsusb output

S6 dmesg output

USB experimentation

Based on the hiddev/hidraw registration, I figured that I might get lucky and get some output during a card read by directly pulling from /dev/hidraw0:

sudo dd if=/dev/hidraw0 of=/tmp/foo

But no luck: it's probably waiting for something from the host first.


A quick search for "Square reader linux" yielded some initially promising results: a blog post by Andy Bromberg and a paper presented at Black Hat 2015 (?).

Unfortunately, both are about the "original"1 3.5mm jack-type reader, which is magstripe only and a lot simpler internally (see Bromberg's photos). Bromberg's post also contains this concerning phrase:

Unfortunately, Square moved from a very simple circuit design to a larger, encrypted version before I got mine.

So there might be some device signing going on. Sigh.

More research

Square's Secure Data Encryption page isn't very helpful — it's mostly PCI-DSS filler.

A 2012 Verge article says that Square's readers include "hardware encryption", but that doesn't mean that the device itself requires signing with a known client.

This spammy-looking site says that Square accounts are linked to their POS2 application, not to a particular reader. That's good, at least.

Permutations on {"Square reader", "encryption", "s6", "signing", "driver", "linux"} don't turn up anything new.

Looking up the FCC ID yielded some helpful component images, and im_eningeer pointed out some test points to yours truly.

The images aren't high-res enough to see the numbers on the Square-branded chip, but the other one says:


Which appears to be a Kinetis K21 with 512KB of flash.


New idea: download Square's Android POS app and see if it contains anything helpful. I wasn't hopeful since Square hints that their Android app only supports BLE3, but who knows.

I downloaded v5.17 from this sketchy site and used apktool to unpack it:

apktool d 'Square Point of Sale POS_v5.17_apkpure.com.apk'
cd 'Square Point of Sale POS_v5.17_apkpure.com'

The manifest offers a hint:

<activity android:name="com.squareup.hardware.UsbAttachedActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar">
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
    <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/usb_device_filter"/>
<receiver android:name="com.squareup.hardware.UsbDetachedReceiver">
        <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
    <meta-data android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" android:resource="@xml/usb_device_filter"/>

And greping for android.hardware.usb.action.USB_DEVICE_ATTACHED in the smali yielded some interesting calls and namespaces:

.method private a(Lcom/starmicronics/starioextension/u;)V
    .locals 3

    iget-boolean v0, p0, Lcom/starmicronics/starioextension/StarIoExtManager;->o:Z

    if-eqz v0, :cond_0

    new-instance v0, Lcom/starmicronics/starioextension/t;

    sget-object v1, Lcom/starmicronics/starioextension/t$a;->c:Lcom/starmicronics/starioextension/t$a;

    invoke-direct {v0, v1, p1}, Lcom/starmicronics/starioextension/t;-><init>(Lcom/starmicronics/starioextension/t$a;Lcom/starmicronics/starioextension/u;)V

    iget-object p1, p0, Lcom/starmicronics/starioextension/StarIoExtManager;->u:Landroid/os/Handler;

    invoke-virtual {p1, v0}, Landroid/os/Handler;->post(Ljava/lang/Runnable;)Z


    new-instance v0, Landroid/content/IntentFilter;

    invoke-direct {v0}, Landroid/content/IntentFilter;-><init>()V

    const-string v1, "android.hardware.usb.action.USB_DEVICE_ATTACHED"

    invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V

    const-string v1, "android.hardware.usb.action.USB_DEVICE_DETACHED"

    invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V

    iget-object v1, p0, Lcom/starmicronics/starioextension/StarIoExtManager;->n:Landroid/content/Context;

    iget-object v2, p0, Lcom/starmicronics/starioextension/StarIoExtManager;->A:Landroid/content/BroadcastReceiver;

    invoke-virtual {v1, v2, v0}, Landroid/content/Context;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;

    const/4 v0, 0x1

    iput-boolean v0, p0, Lcom/starmicronics/starioextension/StarIoExtManager;->o:Z

    new-instance v0, Lcom/starmicronics/starioextension/StarIoExtManager$1;

    invoke-direct {v0, p0, p1}, Lcom/starmicronics/starioextension/StarIoExtManager$1;-><init>(Lcom/starmicronics/starioextension/StarIoExtManager;Lcom/starmicronics/starioextension/u;)V

    invoke-virtual {v0}, Ljava/lang/Thread;->start()V

.end method

It looks like Star Micronics is a POS company, which was initially promising. However, searching for more strings suggests that starioextension et al. are part of a (receipt) printing SDK, not card reading. So probably a dead end.

Next steps

I've run out of time. Maybe I'll pick this up again. If I do, these are probably the next steps:

  1. I don't actually know if this is the original Square reader model. 

  2. Point-of-sale. 

  3. Or at least I thought; can't find that link now.