Skip to content

Write the file formats down, checked field by field against a device - #59

Open
lgnap wants to merge 6 commits into
antoinevalentinHA:masterfrom
lgnap:docs/formats
Open

lgnap wants to merge 6 commits into
antoinevalentinHA:masterfrom
lgnap:docs/formats

Conversation

@lgnap

@lgnap lgnap commented Sep 11, 2026

Copy link
Copy Markdown

What

FORMATS.md: the on-card layout (.md, .pi, .content/), the pack files (ni, li, ri, si, bt, nm, assets), both ciphers, and a section on what the formats offer for versioning a story. Every field carries one of three statuses: verified on a device, code only, unknown. Linked from the README next to TESTING.md and FIELD-VALIDATION.md.

How

A read-only session on a v7 .md device (USB 0483:a341, firmware 3.2.3, 12 packs: 3 STUdio-made, 9 Luniistore). Nothing written to the card, no device data committed — keys and serials are described, never reproduced.

Worth knowing

  • The AES key path is confirmed end to end: key/IV from .md, word-swapped as AESCBCCipher does, and openssl enc -aes-128-cbc on the first 512 bytes of a card file gives exactly the clear library file. The 512-byte boundary and the zero padding of the V3 cipher are confirmed on real files.
  • .md v7 carries the USB vendor/product ids at 0x34/0x36, in the 14 bytes the parser skips. Two more unread 16-byte fields at 0x60 and 0x70 are documented as unknown.
  • The firmware version parser reads one digit per component and drops the patch level (3.2.3 → 3.2). A 3.10 firmware would be misread. Documented as a gap, not fixed here.
  • bt on v7 is serial-derived and pack-independent on 9 of 12 packs — but three Luniistore packs carry an opaque bt and are ciphered with a key that is not the device key. What was tried against them is listed so nobody repeats it.
  • Versioning: the story pack version travels through every format and the device stores it, but nothing is known to read it; the device identifies a story by UUID only, and the pack UUID is the first node's UUID. The card had the same STUdio story under two UUIDs with byte-identical ni — the failure mode a versioning feature would need to address. That feature is tracked separately.

Docs only; CI unaffected.

🤖 Generated with Claude Code

…evice

The formats lived only in the readers, writers and the device layer. This
writes them down with a status on every field: verified on a real card,
only what the code does, or unknown.

Verified on a v7 `.md` device (USB 0483:a341, firmware 3.2.3), read-only:
the `.md` layout including two fields the parser skips (the USB vendor
and product ids), the `.pi` index, the folder naming, the `ni` header and
44-byte stage node, `li`, the 12-byte `ri`/`si` entries, the 512-byte
cipher boundary, the zero padding of the V3 cipher, the word-swapped AES
key (openssl reproduces the library files from the card), the
serial-derived `bt`, the BMP asset format, and the fact that three of the
nine Luniistore packs on the card use a key that is not the device key.

Unknowns are listed in the order they are worth attacking, with what was
already tried against them so nobody repeats it. A section on versioning
states what the formats offer for keeping several versions of one story:
a version number nobody is known to read, and a UUID that is the only
identity the device knows.

No device data is committed; keys and serials are described, not
reproduced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude Tuxedo and others added 4 commits September 11, 2026 14:56
…pack and writes nothing to the card

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…:a341 device

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d the USB reset on 0xf6

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…y shields STUdio packs from a Luniistore sync

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… unknowns

The deep firmware work is already done — o-daneel's Lunii.RE (v1/v2) and
Lunii_v3.RE (v3) reverse the STM32 in Ghidra. Folding in what it settles:

- The three opaque-bt Luniistore packs are not an anomaly: on v3, bt is a
  per-story AES key+IV ciphered with the device key, and resources use
  that per-story key. So they are genuine v3 packs read by a known path
  (decipher bt with the device key, then resources with the story key),
  not the mystery §10 called them.
- .cfg is decoded, not unknown: nine (tag, value) pairs, meanings read
  from the firmware, matching this card. Replaces our guessed structure.
- wifi.prefs is the device's own Wi-Fi credentials under the device key,
  not the app's.
- Corrected an overclaim: .md 0x34 is not the USB vendor/product ids. The
  bytes equal them by coincidence, but Lunii.RE documents 830441A3 as a
  static signature; the field is left open rather than mislabelled.

The unknowns section becomes "prior art, and what is still open",
crediting the three repos and reordering what is left. STUdio needs none
of the crypto; this is interoperability context and honest sourcing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant