
👻 Specter — balayage passif de détection de lecteurs/écrémeurs NFC 13.56 MHz pour Flipper Zero. Mesureur EMF de contre-surveillance utilisant la puce NFC embarquée. Aucun matériel supplémentaire requis.
Specter transforme votre Flipper Zero en détecteur de surveillance de poche pour les lecteurs NFC actifs à 13,56 MHz. Il écoute passivement le champ RF qu'un lecteur sous tension émet en permanence — un skimmer de carte caché glissé dans un terminal de paiement, un lecteur dissimulé derrière un panneau de porte, un enregistreur malveillant scotché sous un bureau — puis vous indique où il se trouve, de quel type d'appareil il s'agit, si la pièce est propre et — laissé en surveillance — le moment où l'un d'eux apparaît pendant votre absence. Il n'émet jamais.
Les lecteurs sont invisibles. Specter les rend visibles.
Présenté dans
Help Net Security
·
Cyber Security News
Un balayage, du début à la fin : pièce calme → rapprochement → verrouillé → ce que c'est → le verdict de la pièce.
Balayage (calme) · Balayage (lecteur verrouillé) · Empreinte · Inspection (en cours) · Inspection (verdict)
Surveillance (dégagé) · Surveillance (lecteur !) · Journal · Calibrage · Paramètres
Specter regroupe cinq outils autour d'un seul capteur. Chacun répond à une question différente, donc le bon choix dépend de ce que vous cherchez réellement à déterminer :
| Mode | La question à laquelle il répond | Utilisez-le quand |
|---|---|---|
| 🔍 Balayage | Où est-il ? | Vous suspectez un appareil et voulez le localiser précisément en vous déplaçant |
| 🔬 Empreinte | De quel type d'appareil s'agit-il ? | Vous avez trouvé un émetteur et voulez savoir comment il se comporte |
| 🗺️ Inspection des lieux | Cette pièce est-elle propre ? | Vous voulez un verdict unique pour tout un espace, sans les mains |
| 🛰️ Mode Surveillance | Un appareil est-il apparu pendant mon absence ? | Vous laissez le Flipper quelque part pour monter la garde |
| 📖 Journal | Qu'ai-je trouvé, et quand ? | Vous rédigez un rapport, ou comparez aujourd'hui avec la semaine dernière — filtrez par type de découverte |

Ce qu'il fait. Un compteur EMF en direct. Tenez le Flipper à plat et déplacez-le lentement sur l'élément que vous vérifiez — un terminal de carte, un lecteur de porte, le dessous d'un rebord de distributeur, un colis, un bureau. L'aiguille suit l'intensité du champ en temps réel.
Ce que vous voyez.
FIELD % — la même lecture sous forme de nombre, avec une flèche de tendance ▲ / ▼
indiquant si la dernière demi-seconde a rendu les choses plus chaudes ou plus froides. Lorsque
vous cherchez, cette flèche compte plus que le nombre.PK / C — la lecture de crête et le nombre de contacts distincts que vous avez eus.● LECTEUR ACTIF avec un mot de proximité dès
qu'une porteuse est détectée.FAIBLE → PROCHE → PRÈS → FORT → MAX. MAX signifie que le compteur est
au maximum : vous êtes aussi proche que cette mesure peut le résoudre.Son. Clics geiger optionnels qui s'accélèrent à mesure que vous vous rapprochez, pour pouvoir balayer avec le Flipper dans la poche et chasser uniquement à l'oreille.
| Touche | Action |
|---|---|
OK | Réinitialiser le maintien de crête et le nombre de contacts |
maintenir OK | Enregistrer cette lecture dans le journal |
GAUCHE | Calibrer sur le bruit de fond de la pièce (3 s) |

Ce qu'il fait. Une fois que le Balayage a trouvé quelque chose, tenez le Flipper immobile contre lui. L'Empreinte cesse de mesurer la proximité et commence à chronométrer les transitions marche/arrêt de la porteuse, ce qui distingue réellement un type d'émetteur d'un autre.
Ce que vous voyez. Un verdict, une barre de confiance et les preuves derrière les deux :
| Classe | Ce que cela signifie en pratique |
|---|---|
| CONTINU | La porteuse est maintenue en permanence |
| INTERROGATION | Un cycle d'interrogation fixe, rythmé par un cristal — la période est affichée en ms |
| INTERMITTENT | Par rafales mais irrégulier — souvent un téléphone ou un lecteur en cours d'utilisation |
En dessous figurent PER (période d'interrogation), BST (largeur de rafale), JIT (gigue) et
DUTY (cycle de service réel), plus un train d'impulsions d'analyseur logique de la
porteuse brute — le verdict n'est donc jamais quelque chose à prendre pour acquis. Un véritable
lecteur à interrogation apparaît comme une onde carrée impossible à confondre.
Un
~devant une mesure signifie qu'elle est proche du plancher d'échantillonnage de 2 ms, et la confiance est réduite en conséquence.
| Touche | Action |
|---|---|
OK | Enregistrer la découverte dans le journal |
maintenir OK | Redémarrer la mesure |

Ce qu'il fait. Un balayage chronométré de tout un espace. Lancez-le, parcourez la pièce normalement et obtenez un verdict unique à la fin — sans surveiller l'aiguille.
Ce que vous voyez. Un compte à rebours et une barre de progression pendant l'exécution, puis une carte de verdict :
PROPRE — rien n'a franchi le bruit de fondTRACE — des contacts brefs ou faibles ; une seconde passe plus lente vaut la peineLECTEUR ACTIF — quelque chose était réellement actif et émettait…avec les champs MAX / AVG, le nombre de contacts et FIELD % — la proportion du balayage
pendant laquelle une porteuse était réellement active, souvent le chiffre le plus révélateur des quatre.
Dure 30 s, 60 s ou 2 min, et consigne automatiquement le résultat.
| Touche | Action |
|---|---|
OK | Relancer l'inspection |

Ce qu'il fait. Monte la garde indéfiniment. Armez-le, posez le Flipper, éloignez-vous. Là où le Balayage est votre chasse et l'Inspection un test de durée fixe, la Surveillance se contente d'attendre — pendant des minutes ou des heures.
Ce que vous voyez. Une grande horloge de temps écoulé et TOUT EST DÉGAGÉ tant que rien n'est là.
Dès qu'un lecteur apparaît, le bandeau s'inverse en LECTEUR PRÉSENT, l'écran se réveille
et l'alarme retentit. Le bandeau est stable plutôt que clignotant —
un petit marqueur pulse à la place, pour qu'il reste lisible sans stroboscopie. Une fois le lecteur passé, l'écran conserve les
preuves : CONTACTS (nombre de contacts distincts), CRÊTE, DERNIER (il y a combien de temps le
plus récent a eu lieu) et VU (temps total pendant lequel une porteuse était réellement active).
La Surveillance ignore délibérément le mode furtif — un garde sombre et silencieux qui ne vous dirait jamais qu'il a vu quelque chose serait pire qu'inutile.
| Touche | Action |
|---|---|
OK | Réarmer — efface l'horloge et les compteurs |
Les découvertes sont enregistrées deux fois, en une seule action, pour être lisibles sur l'appareil et déjà prêtes pour un tableur — aucune étape d'exportation à retenir :
logbook.txt — groupé, pour la visionneuse sur l'appareil | logbook.csv — une ligne plate par entrée |
|---|---|
| ``` 2026-07-18 14:35:11 SURVEY 60s ACTIVE max74… 2026-07-18 14:32:07 READER POLLING 204ms… ``` | ``` timestamp,type,detail 2026-07-18 14:35:11,SURVEY,60s ACTIVE … 2026-07-18 14:32:07,READER,POLLING 204ms … ``` |
Les entrées sont étiquetées SWEEP, READER, SURVEY ou WATCH et horodatées à partir de
l'horloge du Flipper. Les deux fichiers vivent dans apps_data/specter/ sur la carte SD. Rien
ne quitte jamais l'appareil. Effacez-les via Settings → Clear logbook (avec confirmation
d'abord — c'est la seule chose irréversible que l'application peut faire).
Appuyez sur LEFT sur l'écran Sweep et Specter écoute le plancher de bruit ambiant pendant 3 secondes, puis définit le seuil de détection juste au-dessus de ce qu'il a mesuré — enregistré comme votre sensibilité Custom. Chaque pièce a un plancher RF différent ; cela s'accorde à celui où vous vous trouvez plutôt qu'à un nombre figé à la compilation. Tenez-vous dans un endroit calme lorsque vous l'exécutez.
Maintient l'écran et la LED sombres pendant tout le balayage, afin que le Flipper ne
brille pas pendant que c'est vous qui regardez. Le son et les vibrations continuent de
fonctionner — le but n'est pas de désactiver le retour que vous balayez. Quitter un écran
furtif rallume l'affichage, donc BACK vous ramène toujours sur un menu éclairé.
Pourquoi un lecteur que vous touchez n'émet pas 100 % du temps. Le détecteur mesure une seule chose physique : la fraction du temps pendant laquelle une porteuse 13,56 MHz est active. Mais les lecteurs interrogent par impulsions — une courte rafale, une pause, une autre rafale. Un terminal typique ne rayonne que 20 à 35 % du temps, donc le rapport cyclique brut sature autour de 30 %, quelle que soit la proximité.
Afficher ce nombre brut sur la jauge faisait ressembler une détection parfaite à un tiers de celle-ci. Le compteur est plutôt calibré sur cette bande d'interrogation réelle :
| Rapport cyclique brut de la porteuse | Compteur | Proximité |
|---|---|---|
| 3 % (bruit ambiant) | 10 % | FAINT |
| 12 % | 40 % | NEAR |
| 20 % | 67 % | CLOSE |
| 28 % | 93 % | STRONG |
| ≥30 % (posé sur un lecteur) | 100 % | MAX |
Le rapport cyclique brut n'est jamais perdu : le plancher de bruit, l'auto-calibration et
le DUTY de l'écran Fingerprint fonctionnent toujours en rapport cyclique réel, car ceux-ci
décrivent le signal, pas votre distance par rapport à lui. Vous voulez le nombre littéral ?
Settings → Meter → Raw.
La sensibilité, la durée du survey, le son, les vibrations, la LED, le mode furtif, la journalisation et le mode du compteur sont enregistrés sur la carte SD dès que vous les modifiez. Un kit de balayage qui oublie sa configuration est pire que pas de persistance du tout.
Chaque lecteur NFC sous tension émet en continu une porteuse de 13,56 MHz dans l'air, en attendant qu'une carte se réveille. Vous ne pouvez pas la voir, mais la puce NFC du Flipper le peut : le ST25R3916 dispose d'un détecteur de champ externe matériel (le même circuit qui permet au Flipper d'émuler une carte et de savoir quand un lecteur lui parle). Specter place la puce en mode détection seule et échantillonne ce bit « champ présent ? » environ 500 fois par seconde — sans jamais activer sa propre porteuse.
Ce bit unique, échantillonné assez rapidement, transporte deux signaux indépendants :```mermaid
flowchart LR
R["🔍 Hidden 13.56 MHz reader / skimmer
(constantly polling its field)"] -- "RF carrier" --> A
subgraph FLIP["Flipper Zero — Specter.fap"]
A["ST25R3916 NFC chip<br/>external-field detector"] --> S["Sampler thread<br/>~500 samples/s"]
S --> M["<b>How much?</b><br/>carrier duty-cycle<br/>peak · average · contacts"]
S --> C["<b>What rhythm?</b><br/>burst / gap edge timing<br/>period · jitter"]
M --> G["EMF gauge · waveform<br/>geiger clicks · LED · vibe"]
M --> V["Survey verdict<br/>CLEAN / TRACE / ACTIVE"]
C --> K["Emitter class<br/>CONTINUOUS / POLLING /<br/>INTERMITTENT + pulse train"]
V --> L["📖 SD logbook"]
K --> L
end
**Combien → force.** Sur une courte fenêtre, Specter mesure *quelle fraction du temps* un porteur est
présent et la lisse en **FIELD %**. Un lecteur posé directement sur le Flipper fait monter le compteur au maximum ;
un lecteur plus faible ou plus éloigné le fait à peine bouger. Cela pilote l'aiguille, le mot de proximité et le taux de clics.
**Quel rythme → identité.** Séparément, chaque transition de ce bit est chronométrée. Un lecteur qui se réveille
pendant 20 ms toutes les 200 ms produit un motif rafale/pause avec presque aucune gigue, car sa boucle d'interrogation est
pilotée par une machine à états synchronisée sur un cristal. Les mouvements de la main et le bruit RF ne sont pas aussi réguliers. Cette
différence est ce qui sépare **POLLING** de **INTERMITTENT**.
### Les couches de décision sont testées sur un vrai ordinateur
Les endroits où Specter transforme des nombres en une *affirmation* — « c'est un lecteur à interrogation », « cette pièce est
propre », « c'est ce que l'aiguille devrait indiquer » — sont du C pur sans dépendances matérielles, et ils sont
validés par des tests hôte plutôt que découverts sur l'appareil :```bash
make -C test # 300 checks: classifier, verdict, meter scaling, presence
Aucune carte de développement, aucun firmware à flasher — c'est un simple .fap.
Option A — .fap précompilé (le plus simple)
Récupérez le bon .fap depuis la page Releases :
| Votre firmware | Fichier |
|---|---|
| Officiel / stock | specter.fap |
| Unleashed, RogueMaster, Momentum ou tout autre plus récent | specter-fw-dev.fap |
Si le Flipper affiche
APP:87 < FW:88 — This app might not work, vous avez le mauvais fichier — prenez l'autre. La version de l'API de l'application est figée lors de la compilation, donc une seule build ne peut pas satisfaire les deux lignes de firmware. Elle fonctionne généralement quand même si vous appuyez sur Continuer, mais la build correspondante ne le demandera pas.
Ouvrez qFlipper, glissez le fichier sur SD Card / apps / NFC /.
Sur le Flipper : Apps → NFC → Specter.
Option B — compilez-le vous-même avec ufbt```bash
python3 -m pip install --upgrade ufbt
ufbt # build specter.fap into ./dist ufbt launch # build, upload to the Flipper and open it make -C test # run the host tests for the pure logic
Le fichier `.fap` atterrit dans `dist/specter.fap` ; `ufbt launch` le copie vers `apps/NFC/` et le lance pour vous.
> Les icônes dans `icons/`, les captures d'écran et la bannière dans `images/` sont générées — régénérez-les avec
> `python3 tools_gen_icons.py`, `python3 tools_gen_mockups.py` et `python3 tools_gen_banner.py` (nécessite `pillow`).
---
## 🎮 Utilisation
**Un balayage, de bout en bout :**
1. Lancez **Specter**. Sur l'écran **Sweep**, appuyez sur **GAUCHE** et maintenez pendant 3 secondes pour
calibrer le plancher de bruit de la pièce.
2. Tenez le Flipper à plat et déplacez-le **lentement** sur ce que vous vérifiez — un terminal de carte, un
lecteur de porte, le dessous d'un rebord de DAB, un colis, un bureau.
- **Forme d'onde calme / plate** → aucun lecteur actif à portée.
- **Aiguille qui grimpe, clics qui s'accélèrent** → vous approchez d'un émetteur. Continuez vers le pic.
- **`● ACTIVE READER` + bordure d'alarme** → un lecteur actif est juste ici.
3. Vous avez trouvé quelque chose ? Revenez en arrière et ouvrez **Fingerprint**. Tenez le Flipper immobile contre lui et laissez la
cadence se stabiliser — quelques secondes suffisent généralement. Appuyez sur **OK** pour enregistrer la découverte.
4. Vous balayez plutôt toute une pièce ? Ouvrez **Site Survey**, parcourez l'espace jusqu'à ce que la barre se remplisse, et lisez
le verdict.
5. Vous quittez la zone ? Mettez le Flipper en **Watch Mode** et il montera la garde, se réveillant et sonnant
si un lecteur apparaît pendant votre absence.
6. Consultez le **Logbook** pour tout ce que vous avez enregistré, horodaté — ou récupérez `logbook.csv` depuis la carte
dans un tableur.
> 💡 Balayez d'abord un lecteur connu pour être bon (le NFC de votre propre téléphone, ou un terminal sans contact de confiance) pour
> voir à quoi ressemble un champ fort et légitime sur le compteur — et ce que son empreinte indique. Ensuite,
> partez en chasse.
### Commandes
| Écran | Touche | Action |
|---|---|---|
| **Sweep** | `OK` | Réinitialiser le pic / les contacts |
| | `maintenir OK` | Journaliser la lecture actuelle |
| | `GAUCHE` | Calibrer le plancher de bruit (3 s) |
| **Fingerprint** | `OK` | Enregistrer la découverte dans le logbook |
| | `maintenir OK` | Redémarrer la mesure |
| **Site Survey** | `OK` | Relancer le balayage |
| **Watch Mode** | `OK` | Réarmer (effacer le compteur et l'horloge) |
| *n'importe où* | `BACK` | Remonter d'un niveau |
---
## 🔬 Limites honnêtes
- **13,56 MHz (HF) uniquement.** Specter détecte la **bande NFC** — celle utilisée par les skimmers de paiement sans contact,
la plupart des lecteurs d'accès modernes, les lecteurs de transport et d'hôtel. Il **ne peut pas** voir les lecteurs **125 kHz (LF)**
(anciens panneaux de porte HID Prox / EM4100) ; la voie LF du Flipper n'a pas d'équivalent de détection de champ.
- **Il détecte la *porteuse* d'un lecteur, pas ce qu'il lit.** Specter vous dit *un lecteur actif est ici,
approximativement à quelle distance, et à quel rythme il interroge* — il ne décode, n'identifie ni ne capture rien
de ce que fait le lecteur.
- **La force est relative, pas calibrée.** `FIELD %` et les mots de proximité sont un guide comparatif « plus chaud /
plus froid » pour le balayage, pas une distance mesurée en cm. C'est une lecture *mise à l'échelle* du
rapport cyclique de la porteuse par rapport à une bande d'interrogation typique (voir [Lecture du compteur](#-reading-the-meter--fixed-in-23)) ;
un lecteur qui interroge de manière inhabituellement clairsemée lira plus bas à la même distance, et un lecteur en mode
onde continue saturera depuis plus loin.
- **Le compteur plafonne.** `MAX` signifie que la porteuse est aussi haute que ce lecteur ne la monte jamais — au-delà
de ce point, se rapprocher ne peut réellement pas produire un nombre plus grand. Utilisez le maintien de pic `PK` pour comparer
les positions à la place.
- **La cadence se résout à ~2 ms.** C'est la période d'échantillonnage. Les durées proches de celle-ci sont affichées avec un
**`~`** et la confiance est réduite en conséquence — Specter préfère signaler son propre plancher de résolution
plutôt que de citer un nombre à l'apparence précise qu'il ne peut pas garantir.
- **`CLEAN` signifie propre à la sensibilité que vous avez choisie.** Un skimmer dormant qui ne se réveille que lors d'un vrai contact,
ou un skimmer blindé, reste invisible à *tout* seuil. L'absence de lecture n'est pas une garantie
d'absence.
- **Une seule radio à la fois.** Specter prend le contrôle de la puce NFC pendant le balayage, alors fermez d'abord toute autre application NFC
(il affichera *NFC unavailable* si quelque chose d'autre tient la radio).
---
## ⚖️ Légal et éthique
Specter est un outil **défensif, en écoute seule** — il **n'émet jamais**, n'alimente jamais un champ, ne touche jamais
le lecteur. Utilisez-le pour balayer **votre propre** zone de TPE, porte, bureau ou effets personnels, ou du matériel que vous êtes **explicitement
autorisé** à évaluer. Vous êtes responsable de la façon dont vous l'utilisez. Connaissez vos lois locales.
---
## 🗺️ Feuille de route
- [x] Conserver la sensibilité / le son / les vibrations / la LED après redémarrage
- [x] « Logbook » des détections avec horodatages sur la carte SD
- [x] Balayage en arrière-plan avec l'écran éteint — *mode furtif*
- [x] Seuil réglable pour un contrôle de portée plus fin — *auto-calibration + sensibilité personnalisée*
- [x] Empreinte d'un émetteur par sa cadence d'interrogation
- [x] Balayage de site minuté avec verdict de pièce
- [x] Export du logbook en CSV pour les rapports — *écrit en direct à côté du .txt*
- [x] Mode surveillance longue durée sans intervention avec alarme de réveil à la détection
- [x] Faire utiliser au compteur toute sa plage face aux lecteurs à interrogation réelle
- [x] Flèche de tendance plus chaud/plus froid pendant la chasse
- [ ] Étudier une détection de lecteur à bobine LF (125 kHz) comme mode séparé
- [ ] Filtrage du logbook sur l'appareil par type
---
## 🗂️ Structure du projet```
Specter-FlipperZero/
├── application.fam # Flipper app manifest (category: NFC)
├── specter.c / specter_i.h # app entry, wiring, alert feedback, stealth
├── helpers/
│ ├── field_detector.{c,h} # worker thread: samples the field-present bit,
│ │ # duty-cycle + edge timing + calibration
│ ├── emitter_classify.{c,h} # pure: cadence -> CONTINUOUS/POLLING/INTERMITTENT
│ ├── survey_verdict.{c,h} # pure: survey stats -> CLEAN/TRACE/ACTIVE
│ ├── field_scale.{c,h} # pure: raw carrier duty -> full-scale meter
│ ├── present_hold.h # pure: debounce presence across poll gaps
│ ├── specter_settings.{c,h} # persisted settings (saved_struct)
│ └── specter_log.{c,h} # SD logbook, RTC-stamped .txt + live .csv
├── views/
│ ├── sweep_view.{c,h} # the EMF gauge / waveform / alarm screen
│ ├── fingerprint_view.{c,h} # classification card + pulse-train trace
│ ├── survey_view.{c,h} # progress + verdict card
│ └── watch_view.{c,h} # unattended guard: clock + count + alarm
├── scenes/ # scene-manager navigation
├── test/ # host tests for the pure decision layers
├── icons/ # 1-bit Flipper icons (generated)
├── images/ # banner + screen mockups (generated)
└── tools_gen_*.py # regenerate icons / mockups / banner
Toutes les illustrations sont générées, elles ne s'écartent donc jamais de l'application :
| Élément | Taille | Emplacement |
|---|---|---|
images/banner.png | 2560×800 | En-tête du README (2× pour rester net sur les écrans Retina) |
images/social-preview.png | 1280×640 | Paramètres → Aperçu social — taille recommandée par GitHub (min 640×320, limite de 1 Mo) |
images/mark.png | 512×512 | Logo carré : avatars, favicons, diapositives |
images/demo.gif | 768×384 | L'animation ci-dessus, ~9 s, construite à partir des constantes réelles de la vue |
| python3 tools_gen_banner.py # banner, social preview, logo mark | ||
| python3 tools_gen_gif.py # the demo animation | ||
| python3 tools_gen_mockups.py # screen stills | ||
| python3 tools_gen_icons.py # 1-bit Flipper icons |
> L'aperçu social est le seul élément que GitHub ne peut pas récupérer depuis le dépôt — il
> doit être téléversé manuellement une fois dans **Settings → Social preview**. C'est ce qui s'affiche
> lorsque le dépôt est partagé sur Slack, X, LinkedIn ou Discord.
---
## 🙏 Crédits
- Conçu par **[at0m-b0mb](https://github.com/at0m-b0mb)**.
- Fait partie d'une famille d'outils de sécurité Flipper : **[Argus](https://github.com/at0m-b0mb/Argus-FlipperZero)** (watchdog Wi-Fi deauth / evil-twin), **[GhostTag](https://github.com/at0m-b0mb/GhostTag-FlipperZero)** (chasseur anti-filature BLE) et **[Cerberus](https://github.com/at0m-b0mb/flipper-cerberus)** (watchdog RF Sub-GHz).
- Propulsé par le firmware [Flipper Zero](https://github.com/flipperdevices/flipperzero-firmware) NFC HAL (`furi_hal_nfc` détection de champ) + [ufbt](https://github.com/flipperdevices/flipperzero-ufbt).
## 📄 Licence
[MIT](https://github.com/at0m-b0mb/specter-flipperzero/blob/main/LICENSE) © 2026 at0m-b0mb