Back to Projects

Modifying a Cheap Shock Buttplug

Turning a cheap RF shock and vibrating buttplug into a web-controlled device with a Flipper Zero and a little Node.js.

Electronics Sub-GHz Node.js

This guide is a work in progress and deliberately simplified.

The idea

I wanted to see how far I could push a twenty euro toy. Most cheap shock and vibrating plugs ship with a little wireless remote, and that remote is where the fun (and the security hole) lives. So I captured what the remote was saying, learned to say it myself, and then wired that up to a web app running on a small server in my apartment. The end result is a plug I can drive from a browser, using a Flipper Zero as the radio between the internet and the toy.

Disclaimer: this was purely an experiment in tech hacking. I am not responsible for any unintended zaps or rogue vibrations, and there are real security risks in broadcasting control signals for intimate devices. Only ever do this with your own gear, on yourself, with consent, and start gentle.

What went into it

Cheap RF plug a budget shock and vibrating plug whose remote runs on 433MHz, not Bluetooth
Flipper Zero the radio in the middle: Sub-GHz read, save, and replay
Node.js server small always-on bridge between the web page and the Flipper
USB serial link the server talks to the Flipper over its serial CLI
A plain web page a grid of buttons anyone with the link can press
Multimeter + patience for poking at voltages I probably should have left alone

How the toy actually listens

The plug has no brains of its own. It sits on 433MHz waiting for one of a handful of fixed bursts, and it will happily obey whoever sends them.

Vibrate up
steps the motor intensity up one level
Vibrate down
steps it back down
Shock
fires the estim pulse, the one to respect
Mode
cycles through the built-in patterns
Off
kills everything, the important one

Step 1: Finding the right toy

The trick is picking a toy that uses plain radio rather than encrypted Bluetooth. A lot of budget vibrating gear talks over simple RF, which is shockingly easy to listen in on. I found a model on AliExpress whose remote ran on 433MHz, which is the sweet spot: cheap, common, and wide open to snooping. The giveaway is a remote with no pairing step at all. If it just works the moment you put batteries in, there is almost certainly no encryption to get past.

Step 2: Sniffing with the Flipper Zero

I put the Flipper into Sub-GHz read mode and pressed each button on the remote while it captured the raw signal. Every function (vibrate up, vibrate down, shock, off) has its own little burst. I read them one at a time, in a quiet RF spot so nothing else muddied the capture, and saved each as its own file. That gave me a clean library of exactly what the plug expects to hear, one button per file.

Step 3: Decoding and replaying

I decoded the pattern, confirmed it was a static code with no rolling counter, and replayed each one straight from the Flipper to check the toy would take orders from something other than its own remote. It did, instantly. Fun side effect: nudging the timing and frequency of the captured signal could actually bump the vibration intensity past what the remote itself allowed.

Step 4: Putting it on the web

Then I wired it up. A small Node.js server talks to the Flipper over its serial CLI and exposes a simple web page with the controls. Each button press hits an endpoint, the server tells the Flipper which saved signal to broadcast, and the toy reacts a fraction of a second later. Because the server is reachable over the internet, it can be driven from anywhere, which is fun and a little unwise.

Step 5: Opening it up (do not do this)

Out of curiosity I cracked the plug open and put a multimeter across the estim output to understand how the shock stage was driven. This is the part I genuinely would not repeat. There is a step-up circuit in there that pushes the voltage way up, the readings are not friendly, and poking at it with hand tools is a bad idea. I had my look, and then I closed it back up.

A peek at the bridge

The whole thing is basically a lookup table: a button name maps to a saved Sub-GHz file, and the server tells the Flipper to fire it.

// bridge.js  ยท  web button -> Flipper -> toy
import { SerialPort } from 'serialport';
import express from 'express';

const flipper = new SerialPort({ path: '/dev/ttyACM0', baudRate: 115200 });
const SIGNALS = {
  vibe_up:   'subghz tx_from_file /ext/subghz/vibe_up.sub',
  vibe_down: 'subghz tx_from_file /ext/subghz/vibe_down.sub',
  shock:     'subghz tx_from_file /ext/subghz/shock.sub',
  off:       'subghz tx_from_file /ext/subghz/off.sub',
};

const app = express();
app.post('/cmd/:name', (req, res) => {
  const cmd = SIGNALS[req.params.name];
  if (!cmd) return res.status(404).end();       // never trust the button blindly
  flipper.write(cmd + '\r\n');                   // Flipper re-broadcasts the captured burst
  res.json({ sent: req.params.name });
});
app.listen(8090);

What I learned

  • Budget intimate tech has essentially no security worth the name
  • A static 433MHz code can be replayed by anyone in range in minutes
  • Sub-GHz capture and replay is a great, tangible intro to RF
  • Serial control of a Flipper makes it a neat little web-to-radio bridge

Rules I set myself

  • Only ever my own gear, on myself, with consent
  • Always start at the lowest setting and have a hard off
  • Never leave the shock function reachable without a person watching
  • Treat the whole thing as a hack, not a product

The eye opener here is how little security these devices have. If I can replay the remote in an afternoon, so can anyone in range, so be picky about what intimate tech you let onto the airwaves. It was a great crash course in Sub-GHz radio, and it is staying firmly in the "for me, at home, carefully" pile.

Fen is at Darklands!
Check out the live schedule, gear map & control panel
Go