Nyan Box · Volume 9
Nyan Box Volume 9 — Programming and Custom Firmware Development
The open-source path, the closed-source path, host-side analysis scripts, what's worth customizing
Contents
1. About this volume
Vol 9 covers programming the nyanBOX. The honest framing: for most users, including tjscientist, this volume is mostly theoretical — the nyanBOX is a use-the-stock-firmware device (Vol 8 § 6), and its value is in features that exist only in that stock firmware. Custom firmware development matters in a few narrow cases (§ 6), and the path depends entirely on the open-vs-closed source question (Vol 8 § 2).
What is universally useful, regardless of the firmware question: host-side analysis scripts (§ 4) — pulling data off the nyanBOX over USB-serial and processing it on a real computer. That’s the part of this volume that earns its keep for everyday use.
2. The fork-readiness decision
Can you do custom firmware development on the nyanBOX?
═══════════════════════════════════════════════════════
STEP 0 — Check the vendor GitHub (linked from
nyandevices.com). Is the firmware source
actually published?
│
┌───────┴────────┐
YES NO
│ │
▼ ▼
§3 — open path §5 — closed path
(fork, build, (RE the binary, or
PlatformIO) base off Marauder,
or just don't)
This is STEP 0 for a reason. The DEVELOPMENT.md says
it directly: "Don't fork until you've confirmed the
source is published." Many ESP32-pentest vendor
firmwares are binary-only. Assume closed until you've
personally verified open.
3. If the source is open — the build path
If the vendor publishes the firmware source, custom development is straightforward ESP32-Arduino work.
3.1 Toolchain
# Install PlatformIO (one-time)
pip install platformio
# Clone the published source
git clone <vendor repo URL — from nyandevices.com GitHub>
cd nyan-box-firmware
# Build for the ESP32-WROOM-32U
pio run -e nyan_box -t upload
# (exact env name depends on the published source —
# it'll be in the platformio.ini)
3.2 The likely code structure
ESP32-pentest firmwares with menu-driven tool catalogs almost always share a structure:
Likely nyanBOX firmware structure (if open)
═════════════════════════════════════════════
src/
├── main.cpp ← setup() + loop() + menu dispatch
├── menu/ ← the menu-tool registry
│ └── tool_registry.cpp ← THIS is where tools are registered
├── tools/
│ ├── wifi_scan.cpp ← one file per tool (Vol 4-5)
│ ├── ble_scan.cpp
│ ├── nrf24_sniff.cpp ← the triple-radio tools (Vol 3)
│ ├── remoteid.cpp ← the RemoteID decoder (Vol 6)
│ ├── camera_detect.cpp ← the camera detector (Vol 7)
│ └── ...
├── radios/
│ ├── nrf24_manager.cpp ← the 3-radio SPI management (Vol 3 §4)
│ └── esp32_radio.cpp
├── ui/
│ ├── oled.cpp ← the 128×64 display driver
│ └── input.cpp ← the arrow-key handler
├── xp/
│ └── progression.cpp ← the XP system (Vol 8 §4)
└── storage/
└── eeprom_state.cpp ← EEPROM persistence (Vol 2 §7)
3.3 Adding a tool (the canonical customization)
Per DEVELOPMENT.md: “The interesting customizations are in the menu-tool registry — adding a new tool is registering it in the menu plus adding the implementation file.”
Adding a custom tool (open-source case)
════════════════════════════════════════
1. Create src/tools/my_tool.cpp + .hpp
- implement: setup(), loop(), draw(oled)
- follow the pattern of an existing tool
(wifi_scan.cpp is usually the simplest model)
2. Register it in src/menu/tool_registry.cpp
- add an entry: { "My Tool", TIER_PASSIVE, my_tool_entry }
- pick the XP tier (or TIER_NONE to skip gating)
3. Build + flash
pio run -e nyan_box -t upload
4. The tool appears in the menu.
3.4 The patch tjscientist would actually want — XP removal
If the source is open, the single most useful patch for tjscientist is removing the XP gating (Vol 8 § 4) at source rather than grinding it:
// In src/xp/progression.cpp (hypothetical)
bool isToolUnlocked(ToolEntry& tool) {
return true; // ← patch: all tools always unlocked
// original: return currentXP >= tool.requiredXP;
}
One-line patch, rebuild, done. The education scaffolding stays visible (the context text) but nothing is locked. Best of both — if the source is open.
4. Host-side analysis scripts
This is the section that’s useful regardless of the firmware question. The nyanBOX has EEPROM, not microSD (Vol 2 § 7) — it can’t store large logs on-device. The answer is to stream data off it over USB-serial and process it on a host PC. The Nyan Box/projects/ directory exists for exactly these scripts.
4.1 The USB-serial pull pattern
Pulling data off the nyanBOX
══════════════════════════════
nyanBOX ──USB-C──→ USB-serial bridge ──→ host PC
│
▼
/dev/ttyUSB0 (or COMx)
│
▼
Python script reads the
serial stream, parses it,
logs to disk, analyzes
The nyanBOX firmware streams tool output over the
serial console (most ESP32-pentest firmwares do this
by default — it's the debug/log channel). A host
script captures that stream — turning the EEPROM-
limited device into one with effectively-unlimited
logging.
4.2 A RemoteID-watch logger (sketch)
#!/usr/bin/env python3
# nyan_remoteid_logger.py — capture a long RemoteID watch
# to disk, since the nyanBOX EEPROM can't hold it.
import serial, json, time, sys
PORT = sys.argv[1] if len(sys.argv) > 1 else "/dev/ttyUSB0"
ser = serial.Serial(PORT, 115200, timeout=1)
with open(f"remoteid_{int(time.time())}.jsonl", "w") as log:
print(f"Logging RemoteID watch from {PORT} ...")
while True:
line = ser.readline().decode("utf-8", "ignore").strip()
if not line:
continue
# nyanBOX RemoteID lines — adapt the parse to the
# actual firmware output format once on hardware
if line.startswith("RID:"):
record = {
"ts": time.time(),
"raw": line,
# parse drone ID / position / operator
# position from the line per the firmware's
# actual format
}
log.write(json.dumps(record) + "\n")
log.flush()
print(f" logged: {line}")
This turns the ~13-hour RemoteID watch (Vol 2 § 5.4 — battery supports it) into a complete on-disk record instead of an OLED-only ephemeral view.
4.3 A camera-sweep correlator (sketch)
#!/usr/bin/env python3
# nyan_camera_correlate.py — pull the camera-detection
# stream + the Wi-Fi-scan stream, correlate them per
# the Vol 7 §6.2 cross-reference discipline.
import serial, sys
from collections import defaultdict
PORT = sys.argv[1] if len(sys.argv) > 1 else "/dev/ttyUSB0"
ser = serial.Serial(PORT, 115200, timeout=1)
camera_flags = {} # MAC -> camera-detection record
wifi_devices = {} # MAC -> wifi-scan record
while True:
line = ser.readline().decode("utf-8", "ignore").strip()
if line.startswith("CAM:"):
# parse the camera-detection flag (MAC, confidence, brand)
...
elif line.startswith("WIFI:"):
# parse the wifi-scan entry (MAC, SSID, vendor)
...
# Cross-reference: a CAM flag whose MAC also shows as a
# known TV/streaming/networking device in WIFI is a
# likely false positive (Vol 7 §6). Flag the deltas —
# the CAM hits that DON'T have a benign WiFi identity
# are the real leads.
This automates the Vol 7 § 6.2 cross-reference discipline — instead of eyeballing two OLED screens, the host script does the correlation and surfaces only the genuine leads.
4.4 A multi-channel NRF24 capture logger
Same pattern: the triple-NRF24 sniff (Vol 5 § 3) produces more packets than the OLED can show or the EEPROM can hold. A host logger captures the full stream — every packet on all three channels — to a pcap-like file for offline analysis.
4.5 Why this is the high-value section
These host-side scripts:
- Work regardless of open/closed firmware — they just read the serial output, no firmware modification needed
- Solve the real limitation — the EEPROM-not-microSD constraint (Vol 2 § 7) is the nyanBOX’s biggest practical weakness; serial logging makes it moot
- Are quick to write — a few dozen lines of Python each
- Live in
Nyan Box/projects/— the designated home
For tjscientist, this is the actual “development” work the nyanBOX warrants — not custom firmware, but a small host-side script library that turns the device’s ephemeral OLED output into durable, analyzable data.
5. If the source is closed — the options
If the vendor GitHub confirms the firmware is binary-only:
| Option | Effort | Verdict |
|---|---|---|
| Just use stock firmware + host scripts (§4) | Low | The right answer for almost everyone. The host scripts give you the data; the stock firmware gives you the features. |
| Reverse-engineer the binary | Very high | Pull the OTA binary, Ghidra, find the structures. A genuine research project. Only worth it if there’s a specific must-have modification and no other path. |
| Base a custom firmware off ESP32 Marauder | High | Marauder is open. You could build a Marauder-derived firmware with a nyanBOX display/input/3-NRF24 port. But you lose RemoteID + camera detection (Vol 8 § 5.3) — so this only makes sense if you don’t want those features, in which case why this hardware. |
| Ask the vendor | Low | Nyan Devices is a small, community-rooted two-person shop. The Discord exists. If there’s a feature you want, asking the creators directly may be more productive than reverse-engineering. |
5.1 The pragmatic closed-source stance
For the closed case, the realistic stance: don’t fight it. Use the stock firmware (it has the features), write the host-side scripts (they solve the storage limitation), and engage the vendor’s Discord for anything else. The nyanBOX is a $220 small-vendor education device — it does not warrant a binary-reverse-engineering project. If you find yourself wanting to RE the firmware, that’s a signal you bought the wrong device for your need (Vol 1 § 8’s decision tree should have caught that).
6. What’s actually worth customizing
Cutting through the theory — for tjscientist specifically, here’s the realistic customization priority:
| Customization | Worth it? | Path |
|---|---|---|
| Host-side analysis scripts (§4) | Yes — definitely | Just Python + pyserial; no firmware touch needed; lives in projects/ |
| Removing XP gating | Only if it’s actually annoying | Grind it (Vol 8 §4.4), or one-line source patch if open |
| Adding a custom tool | Rarely | Only if open-source AND you have a specific tool the 40+ catalog lacks |
| Extending the camera DB | Tempting but hard | The DB is in firmware; extending it needs the source or RE. Better: report missing cameras to the vendor. |
| Improving the BT5 RemoteID coverage (Vol 6 §7.3) | Out of scope | That’s a silicon limitation (original ESP32 BT5) — firmware can’t fully fix it |
| Native triple-NRF24 in alt firmware | High effort, niche | Only if you’ve decided to abandon stock firmware entirely |
The one-line takeaway: the worthwhile “development” for the nyanBOX is the host-side script library in projects/ — not custom firmware. Everything else is either grind-able friction (XP), vendor-locked (the unique features), or a research project disproportionate to a $220 device.
7. Resources
If open-source
- Vendor GitHub (check for the firmware repo): linked from https://nyandevices.com
- PlatformIO: https://platformio.org/
- ESP32 Arduino core: https://github.com/espressif/arduino-esp32
If closed-source / RE
- Ghidra: https://ghidra-sre.org/
- esptool.py (for pulling the binary): https://github.com/espressif/esptool
- ESP32 Marauder (open-source base, if going that route): https://github.com/justcallmekoko/ESP32Marauder
Host-side scripting
- pyserial: https://pyserial.readthedocs.io/
- The
Nyan Box/projects/directory — designated home for these scripts
Vendor contact
- Nyan Devices Discord (the creators — jbohack & zr_crackiin): linked from the vendor site
End of Vol 9. Next: Vol 10 covers end-to-end use-case recipes — RemoteID watch, hidden-camera sweep, multi-channel NRF24 sniff, and education-session workflows.