RFID theremin - Turn your implant into a crap musical instrument

Turn your NFC / RFID implant into a theremin!

Well, you also need a Proxmark3, and you mustn’t be too picky about the “music” it generates :slight_smile: But who knows? If you’re feeling creative…

More seriously, it’s actually quite useful to determine quickly the best spot and chip orientation to maximize coupling with the antenna, before doing a write for example. And because it doesn’t actually try to pull data out of the chip, the pitch starts to change several centimeters away from the surface, even with HF implants.

Here’s the Python script:

#!/usr/bin/python3

### Parameters
# Sound output parameters
volume = 1.0
sample_buf_size = 44
sampling_freq = 44100 #Hz

# Frequency generator parameters
min_freq = 200  #Hz
max_freq = 2000 #Hz

# Proxmark3 parameters
pm3_client="/usr/local/bin/proxmark3"
pm3_reader_dev_file="/dev/ttyACM0"
pm3_tune_cmd="hf tune"



### Modules
import numpy
import pyaudio
from select import select
from subprocess import Popen, DEVNULL, PIPE



### Main program
p = pyaudio.PyAudio()

# For paFloat32 sample values must be in range [-1.0, 1.0]
stream = p.open(format=pyaudio.paFloat32,
		channels=1,
		rate=sampling_freq,
		output=True)

# Initial voltage to frequency values
min_v = 100.0
max_v = 0.0
v = 0
out_freq = min_freq

# Spawn the Proxmark3 client 
pm3_proc = Popen([pm3_client, pm3_reader_dev_file, "-c", pm3_tune_cmd],
		bufsize=0, env={}, stdin=DEVNULL, stdout=PIPE, stderr=DEVNULL)
mv_recbuf = ""

# Read voltages from the Proxmark3, generate the sine wave, output to soundcard
sample_buf = [0.0 for x in range(0, sample_buf_size)]
i = 0
sinev = 0
while True:

  # Read Proxmark3 client's stdout and extract voltage values
  if(select([pm3_proc.stdout], [], [], 0)[0]):

    b = pm3_proc.stdout.read(256).decode("ascii")
    for c in b:
      if c in "0123456789 mV":
        mv_recbuf += c
      else:
        mv_recbuf = ""
      if mv_recbuf[-3:] == " mV":
        v = int(mv_recbuf[:-3]) / 1000
        if v < min_v:
          min_v = v - 0.001
        if v > max_v:
          max_v = v

        # Recalculate the audio frequency to generate
        out_freq = (max_freq - min_freq) * (max_v - v) / (max_v - min_v) \
			+ min_freq

  # Generate the samples and write them to the soundcard
  sinevs = out_freq / sampling_freq * numpy.pi * 2
  sample_buf[i] = sinev
  sinev += sinevs
  sinev = sinev if sinev < numpy.pi * 2 else sinev - numpy.pi * 2
  i = (i + 1) % sample_buf_size
  if not i:
    stream.write((numpy.sin(sample_buf) * volume).
					astype(numpy.float32).tobytes())
12 Likes

Love this! Seems like a very impractical theremin, I’d love to see an RFID ‘theremin pin’ as a musical 2nd factor just for the hell of it

1 Like

hahaha very nice! GJ Rosco :slight_smile:

1 Like

Fantastic! This will be something else I will have to do when I get the PM3 :rofl:
Thank you for sharing Rosco!

2 Likes

That is awesome, horrible and helpful all at the same time…

I don’t think too many people know what a Theremin is, so good job on that.

I might have to learn how to play the Midsomer Murders theme song with it.
(wow, looking up the video for it, over 1 million views, I guess more people that I thought know what a theremin is)

2 Likes

I have wanted to learn it for years. Just not enough to actually commit :sweat_smile:

It would need another Proxmark3 at a 90 degree angle to emulate the volume as well, to be a true theremin. That would be an interesting setup :slight_smile: Unfortunately, I only have one Proxmark3.

But the real problem is that coupling between an implant and the antenna is very poor. There’s a half-volt swing between loaded and unloaded in the best of case, and the Proxmark only reports so many voltage values within that half-volt for some reason. As a result, with an implant, there are only 4 or 5 notes available and it sounds horrible.

In comparison, a full-size NFC card creates a 10V swing and a lot more notes. You might have heard it in the video: as soon as I use the card, the pitch variation becomes almost continuous.

For simplicity’s sake, I use the PM client’s “tune” command, which reports the voltage in real-time. But like I said, for some reason, it only reports a discreet number of voltage values. I think maybe I’ll make a LUA script to get the raw values and extract the voltage myself, see if I can get a better granularity. Or possibly fix a bug in the PM software and submit a patch.

1 Like

Could you somehow leverage the seperate antenna? Like LF for pitch and HF for volume? Assuming you have a LF in one hand and a HF in the other. Probably would need to prop the PM up so you could get a hand on each side.

No can do. The PM3’s FPGA code has been split in two parts - HF and LF - and the right code must be uploaded to the PM3 each time you switch mode of operation. That’s why it takes 1 to 2 seconds when you issue a LF command after a HF command and vice-versa. It might have been possible with previous Iceman releases, and possibly with the vanilla firmware, but not with the latest Iceman.

1 Like

Kickstarter?

I don’t think so. Even if it worked (which I doubt - crosstalk between the two fields comes to mind) and even if I manage to get much finer-grained voltage measurements, I can predict the resulting “instrument” would be pretty hopeless :slight_smile:

I’ll try to make it better with just one Proxmark - because plenty of people have a Proxmark, so it won’t cost nothing to try Proxmark artistry. But otherwise it really doesn’t make sense: there are plenty of proper theremin kits for cheap out there, if you really want a theremin.

Okay, I diddled with the PM3’s firmware a bit, to improve the precision of antenna voltage measurements. Now I can control the pitch of my Proxmark “theremin” with my implants much more precisely. Check it out:

Of course, now the problem is, I can’t carry a tune in a bucket. So what comes out of my newfound musical instrument is still awful. But this time it’s my fault. I’ll practice a bit when my S.O. isn’t around, because she’s getting mighty pissed off with the racket :slight_smile:

4 Likes