Python Systemd Daemon for Unlocking Linux System with Implant

I finished a new project recently that lets me unlock my computer using my blinky XSIID implant. The script also passes data scanned to a website if needed, so I can also badge into custom websites I build. I’m using a few basic python packages, as well as systemd, i3lock, and the MIRKOE2540 NFC USB dongle. This seems to be the only USB device I’ve been able to find that will scan my implant.

To use this, install Python and i3lock. Replace tokens and text_tokens with the ID and text written to the implant or NFC card. Install this script with a virtual environment in an encrypted home directory, and add the below daemons to systemd. Install the MIKROE2540 linux example in /etc/nxp. (use the product page, or this link: https://www.nxp.com/doc/SW4335)

tokens = ['00 00 00 00 00 00 00']
text_tokens = ['<randomly generated text on the implant here>']

lock_at_seconds = 60 * 60

for token in tokens:
    token = token.replace(':', ' ')
    token = 'NFCID = ' + token

for token in text_tokens:
    token = token.replace(':', ' ')
    token = 'Text record: ' + token

import logging
from websocket_server import WebsocketServer

server = WebsocketServer(host='localhost', port=13254, loglevel=logging.INFO) #, key="key.pem", cert="cert.pem")

def run():
    global server
    server.run_forever()

import os, subprocess, time, threading, multiprocessing

thread = threading.Thread(target=run)
thread.start()

from datetime import datetime

def count_to_lock():
    while True:
        seconds = (datetime.now() - (datetime.now().replace(minute=0))).total_seconds()
        lock_at_seconds = 60 * 60
        while seconds < lock_at_seconds:
            time.sleep(1)
            seconds += 1
        subprocess.Popen(['/usr/bin/i3lock'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        seconds = 0

def run_process(client):
    ls = None
    op = None
    lock_at_seconds = 60 * 60
    seconds = (datetime.now() - (datetime.now().replace(minute=0))).total_seconds()
    while not op or 'No such' in op:
        ls = subprocess.Popen(['/usr/bin/ls', '/dev/hidraw2'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        op = str(ls.stdout.readline().rstrip(), encoding='utf-8')
        print('NFC Daemon Active')
        seconds += 1
        if not seconds < lock_at_seconds:
            subprocess.Popen(['/usr/bin/i3lock'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            seconds = 0
        time.sleep(1)
    subprocess.Popen(['/usr/bin/sudo', 'chmod', 'a+rw', '/dev/hidraw2'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    import asyncio
    async def main():
        primary_index = -1
        secondary_index = -2
        proc = await asyncio.create_subprocess_exec(
            'stdbuf', '-o0', "/etc/nxp",
            stdout=asyncio.subprocess.PIPE,
        )
        process = multiprocessing.Process(target=count_to_lock)
        process.start()
        line = await proc.stdout.readline()
        while line:
            print(line.decode())
            line = await proc.stdout.readline()
            decoded = line.decode()
            for token in tokens:
                if token in decoded:
                    primary_index = tokens.index(token)
            for token in text_tokens:
                if token in decoded:
                    secondary_index = text_tokens.index(token)
            if primary_index == secondary_index:
                subprocess.Popen(['/usr/bin/killall', 'i3lock'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                primary_index = -1
                secondary_index = -2
            client.send_message_to_all(decoded)
        process.terminate()
    asyncio.run(main())

while True:
    seconds = (datetime.now() - (datetime.now().replace(minute=0))).total_seconds()
    lock_at_seconds = 60 * 60
    while seconds < lock_at_seconds:
        run_process(server)
        time.sleep(3)
        seconds += 3
    subprocess.Popen(['/usr/bin/i3lock'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    seconds = 0

This configuration runs the NFC python file at boot.
/etc/systemd/system/nfc.service

[Unit]
Description=nfc daemon for auth
After=network.target

[Service]
User=root
Group=users
WorkingDirectory=/home/daisy/Documents/nfc
ExecStart=/home/daisy/Documents/nfc/venv/bin/python /home/daisy/Documents/nfc/nfc.py

# Not sure if should use 'on-failure' or 'always'. 
Restart=on-failure

[Install]
WantedBy=default.target

This simple configuration locks the computer when it goes to sleep, replace display with the name of your display (get this with “echo $DISPLAY”)
/etc/systemd/system/wake_sleep.service

[Install]
WantedBy=sleep.target

[Unit]
After=systemd-suspend.service systemd-hybrid-sleep.service systemd-hibernate.service

[Service]
Type=forking
ExecStart=/bin/bash -c 'i3lock'
User=daisy
Environment=DISPLAY=:0.0

Make sure to enable and start both services

sudo systemctl enable nfc
sudo systemctl enable wake_sleep
sudo systemctl start nfc
sudo systemctl start wake_sleep

I also happened to need a cron job to start the service once logged in or in the event of a crash, but this should be possible with .profile too, so add a “sudo systemctl sttart nfc” in .profile and crontab if necessary.
Other than this, you will need to enable automatic login and disable the password prompt for login (we replaced it with I3lock, which can now be killed simply by plugging in an NFC dongle scanning an implant).

I hope this is useful to you. I wish you the best of luck in all your experiments and endeavours using these awesome MIFARE 1K/2K cards for authentication. Have a great day, and happy new year!

Update: I changed WantedBy= from multi-user.target to default.target in order to run the daemon on login instead of at boot, this should make sure everything works properly in an encrypted home directory (which I recommend)

(below) A photo of my setup, unlocking my computer like this.

8 Likes

This is awesome! Thank you for sharing your work! :heart_on_fire::raised_hands:

2 Likes

Of course! Let me know if you have any questions.

1 Like

It looks like some of you guys are scanning tags on your computers with an ACR1252U USB NFC reader so I’m wrong about the MIKROE being the only one that can scan chip implant cards. I just wasn’t able to get the ACR122U (the smaller, previous generation reader) to work. I recently picked up an ACR1252U and I’m going to try it out and see how it works, it seems to be higher power and enough to light up and scan the XSIID. Or maybe the ACR122U I bought was faulty? Should I return it? Let me know your thoughts. I really can’t get mine to scan my implant, it will scan my USB FIDO Key, coin cards, and standard credit card sized chip cards just fine. Just not my implant. I’ll try again with the ACR1252U and update. The MIKROE2540 works great though, it’s the perfect handheld solution and a good price too at $29 on DigiKey.

1 Like

Probably not faulty but a knockoff that performs like garbage. The company ACS that makes the ACR series discontinued the 122U a few years ago in part because a ton of Chinese factories started putting out knockoffs that have really underwhelming performance. Send photos of the front and back. Most font bother to put the ACS logo on the front and have garbage labels on the back.

The design of a legitimate 122u internal antenna is quite impressive actually because they use a sandwich design where the actual coil traces sit between ground planes on both sides… but somehow it reads exceptionally well.

X-series implants read well in this orientation;

The acr1252u actually doesn’t perform quite as well as a legitimate 122u, but it still works.

1 Like

I’ll send photos when I get home from work, appointments and errands this evening. You’re probably right it’s a knockoff, I’ll see about returning it too. I got it on Temu with the welcome deal for about $16.50. For now I have a used ACR1252U on the way which should be authentic.

1 Like

I had to look it up, and the ground planes are designed exactly how I expected.

As long as the shielding does not form a closed loop around the antenna, it shouldn’t interfere. Many years ago I was into building DIY metal detectors and shielded coils are the norm in that area.

are these photos of the legit acs 122u?

1 Like

Congrats!!
And thanks for Sharing!

That is a really good work you did there! ^^

I was hoping you would have found a way to avoid i3lock… I don’t like to rely on it, but am also using the same thing on my setup for lack of a better alternative. :stuck_out_tongue_winking_eye:

Besides what @amal already mentioned, there’s also another issue.

ACR122u readers do some “pre handling” and interface with the computer in a very specific, highly windows-friendly, way which is not well handled by most of the python packages you would run on Linux. Hence they do require either a custom driver or some annoying steps to be taken by your code to work as one would expect it to…

Unless you got some new/updated python package that handles it well. which Might be the case since last time I used it was a good 2 or 3 years ago.

I did write something about that issue here it in this forum when I did, though, so if @Pilgrimsmaster can run their magic and unearth that, would be great! (Because right now I’m highly sleep deprived and yet on a rush to leave… and I don’t know how to search for my own posts where I mentioned “ACR122” ).

Regardless, Great job again! and thanks for the post!

3 Likes

This is my legit one (bought from DT)


This one?

FYI

Also, great to see you back @eyeux

2 Likes

Yeah, I was trying to get the ACR122U working with the same software on Windows for a background NFC daemon to relay NFC data over a websocket, but I wasn’t able to find the proper Linux software to interface with the reader. I tried something I found on Ubuntu apt with WSL but wasn’t able to read the ID in a proper format, if anyone knows how to read ACS ACR scanner data using Linux, please let me know. I am able to mount the device and see it’s connected I just haven’t found a good app to read the data from it to a shell. Thanks for your support!

1 Like

It’s a version of the 122u yes. The basic acr122u doesn’t have the sim card connector hardware inside. This version allows the reader to also basically have a constant contact interface which is used by special applications to identify the reader itself as some sort of legitimate application reader.

1 Like

Were you able to read it in any kind of format, or were you not able to get any kind of read?

I’m pretty sure you need to use PC/SC APDUs to communicate with the PCD and PICC.

Yeeees!!
Knew we could count on you!! :grin:

Legend as always!
I’ll try not to vanish so much! :stuck_out_tongue_winking_eye:

By “and interface with the computer in a very specific, highly windows-friendly, way”, I meant that the ACR122u uses/“enforces” PCSCD… Which is not ideal to handle within most Linux environments (given how many packages and default kernell stuff tends to approach it)

Also… Thanks again, @Pilgrimsmaster !! I didn’t knew the @ would work that way In the Search!!

Neither did I… or at least not a good one.
I found some scripts that work, but they conflict with how the default Kernell sets up pcscd (I’m on Arch, but had the same issues on Debian, CentOS (RIP), Alma and Raspbian).

So then I had to either manually start up the scripts (which defeats the purpose of a solution to work from boot), or I had to completely prevent the system from trying to handle pcscd… Which then borks up everything else that depends on pcscd…

I assume you mean on Linux, but you did mention a Windows attempt on that same post, so just for clarity… on Windows or on Linux?

If so…
Which Distro?
and by “app”, would you be happy with a shell script?
And by Data, you mean NDEF? ID? Blocks?

if so, have you tested with NFCPY?
If you download the whole project (GitHub - nfcpy/nfcpy: A Python module to read/write NFC tags or communicate with another NFC device.), there’s a directory called “examples” with some good working scripts there.

IF I recall correctly (last time I messed with this was over a good year ago), listen.py might do what you want.
You can also pipe it through other stuff, even cat.

If not, take a look on sense.py or tagtool.py (both also in the same “examples” folder)

That said, nfcpy does complain a lot about ACR122u… (just as every python package I used so far in Linux… and c++ libs I found also needed tweaking to the point I had to write a new driver for it)

Which is why Sony’s RC-S380 became my go-to reader:

Anyhow…

Sorry for the limited help but I won’t have access to my PC until Monday, and no decent access until Wednesday anyway… Then I can double check stuff and run whatever tests you need!

3 Likes

Oh, before I forget…

That is: “FOR LINUX” usage… :sweat_smile:
in case that hadn’t been clear!

for anything else, ACR122u are still a top choice… :wink:

1 Like

I’ll look into this. I was able to read the tag, but the bytes read didn’t look right. I’ll have to try again with a new reader and libnfc. I’m not sure I was using the right software, thanks for pointing me in the right direction.

Thanks for the help! I’ll try out nfcpy when I get my new reader in, that should work better. I am just looking to read the ID and data on the card, being a URL and randomly generated data written to the card using the NDEFReader JavaScript API. Really I just need a script similar to the MIKROE2540 example code that purely reads the data from the card including fields written to the tag and ID, and then I can use this script with stdbuf -o0 in Unix and pass it through a local websocket to a webpage, parse it on the webpage, and post it to a server to authenticate with my website without using the NDEFReader which doesn’t work on desktop.

1 Like