Geek++ · Dossier 05 / 25

Trust Model, Leecher Mods et données distantes non fiables

Étude technique publique · 3,285 mots · ≈ 15 min de lecture attentive

Étude intégraleSans réflexion CODEXSources & constantes conservées
Confiance distribuée
REMOTE
claim
→
LOCAL
measured
→
HASH / CRYPTO
verified

0. Résumé exécutif

Jusqu’ici, nous séparions principalement :

PROTOCOLE
vs
POLITIQUE LOCALE

Il faut maintenant ajouter :

CONFIANCE DANS LES DONNÉES DISTANTES

Une valeur parfaitement conforme au protocole peut être mensongère.

Exemples :

Queue Rank
ModString
Client Version
pseudo
bits de capacité
état de parties
liste Source Exchange

Le paquet peut être syntaxiquement valide tout en portant une information choisie volontairement par un client modifié.

Le principe directeur proposé est :

Toute donnée contrôlée par un pair distant est une assertion non fiable tant qu’elle n’est pas vérifiée localement ou cryptographiquement.

Ce dossier montre également une nuance importante par rapport à l’intuition « un leecher envoie un faux rang pour passer premier dans notre upload ».

Dans l’eMule officiel :

  • le score de notre propre Upload Queue est calculé localement ;
  • un faux Remote Queue Rank ne permet donc pas directement au pair de s’attribuer un meilleur score chez nous ;
  • en revanche, le Remote Queue Rank reçu est utilisé dans certaines décisions de notre Download Manager, notamment lors des choix A4AF / Source Exchange autour du seuil QR 50.

Il existe donc bien une surface de manipulation, mais elle n’est pas exactement celle que l’interface pourrait laisser penser.


1. Preuve historique : les clients mensongers ont réellement existé

Le corpus des Mods contient des fonctions explicitement offensives.

Applejuice

Le changelog annonce :

advanced undetectable Fake Rank
send Fake Rank to Clients on Queue
send Fake Rank instead of Full Queue
send Fake Rank to all Clients or only Leechers
manual enter send Fake Rank < x

Il annonce aussi :

Fake Tags
Clientversion Thief
Community Faker
Client Emulations
send arbitrary Clientversion
select sending Modstring
random Modstring
Ghost / no Modstring

Le même Mod comprend également :

Boost Clients depending on Remote Queue Rank

C’est une démonstration directe du problème de confiance :

A prend une décision locale selon un champ distant
B peut falsifier ce champ
→ B peut tenter d’influencer A

2. Les protections historiques confirment l’existence du problème

Le corpus mentionne notamment :

QR-Faker / Faked Ranks kicken
Anti-Fake-Rank
Anti-Nick-Thief
Anti-ModID Faker
Hash Thief Protection
Ghost Mod detection
Client Analyzer
Argos Anti-Leecher
DLP
SNAFU

Argos est documenté comme utilisant une détection multi-critères portant sur :

ModString
pseudonyme
logiciel
UserHash
opcode
Source Exchange
fast ask
tags invalides
violations de protocole

Ce corpus doit être étudié comme une base historique de menaces, pas comme un ensemble de règles à recopier.


4. Classification des données par niveau de confiance

Niveau L0 — Remote Claim

Le pair contrôle entièrement la valeur.

Exemples :

nickname
ModString
version
Remote Queue Rank
capabilities déclarées
part map
sources SX envoyées
affichage
optimisation faible
jamais privilège important seul

Niveau L1 — Cohérence locale

La valeur distante est cohérente avec d’autres observations.

Exemple :

le pair annonce SX4
et répond ensuite avec des paquets SX4 structurellement valides

Cela augmente la confiance dans cette capacité seulement.

Niveau L2 — Observation comportementale

Notre client observe directement un événement.

Exemples :

connexion réussie
octets reçus
latence
requêtes réellement faites
source SX réellement joignable
bloc reçu

Niveau L3 — Vérification cryptographique / intégrité

Exemples :

SecureIdent validé
bloc vérifié par hash
AICH cohérent
FileHash localement confirmé

Ces niveaux ne doivent pas devenir un « score universel ».

Ils doivent être appliqués au domaine concerné.


5. Remote Queue Rank : cas d’école

5.1 Réception

Dans DownloadClient.cpp eMule 0.72a :

ProcessEdonkeyQueueRank(...)
ProcessEmuleQueueRank(...)

lisent directement le rang envoyé par le pair puis appellent :

SetRemoteQueueRank(rank, ...)

Aucune preuve de la file distante n’est possible.

C’est logique : nous n’avons pas accès à sa waiting list.

5.2 Protection contre le flood

eMule ne fait toutefois pas confiance au rythme des messages.

CheckQueueRankFlood() :

  • compte les QR non sollicités ;
  • suit les mauvaises requêtes ;
  • peut bannir avec la raison :
QR flood

Le contenu numérique du rang n’est pas vérifiable.

La fréquence d’envoi, elle, peut être vérifiée localement.

C’est exactement la distinction :

vérité distante : invérifiable
comportement protocolaire : observable

5.3 Utilisation du QR distant dans l’eMule officiel

Point important découvert dans la 0.72a.

SwapToRightFile() contient notamment des conditions :

GetRemoteQueueRank() <= 50

et :

GetRemoteQueueRank() > 50

dans des décisions liées au changement de fichier / Source Exchange.

Donc :

le Remote Queue Rank n’est pas purement décoratif dans le client officiel.

Un pair qui annonce volontairement un QR artificiel peut théoriquement influer sur cette branche de décision.

Cela ne signifie pas qu’il obtient directement un meilleur upload chez nous.

Cela signifie qu’une donnée invérifiable influence une heuristique locale de téléchargement.

6. Notre Upload Queue est mieux protégée contre le Fake Rank

Le dossier 04 a montré que notre propre score d’upload dépend de valeurs locales :

GetWaitStartTime()
Credits()->GetScoreRatio()
priorité locale du fichier

Un client distant ne fournit pas directement ces valeurs.

Il ne peut donc pas envoyer :

score=999999

dans un paquet standard pour devenir premier.

Les attaques sont plutôt indirectes

Exemples de domaines à surveiller :

identité clonée
multiplication d’instances/adresses
reconnexion/reask agressif
changement du fichier après attribution du slot
tentatives de contourner les règles de queue

Le détail de chacune doit être traité défensivement et mesuré.


7. Hello Tags : syntaxiquement valides ≠ vrais

BaseClient.cpp parse notamment :

CT_NAME
CT_VERSION
CT_PORT
CT_MOD_VERSION
CT_EMULE_UDPPORTS
CT_EMULE_BUDDYUDP
CT_EMULE_BUDDYIP

et les Info Packets contiennent notamment :

ET_COMPRESSION
ET_UDPPORT
ET_UDPVER
ET_SOURCEEXCHANGE
ET_COMMENTS
ET_EXTENDEDREQUEST
ET_COMPATIBLECLIENT
ET_FEATURES
ET_MOD_VERSION

Le parser vérifie les types.

Mais la valeur vient du client distant.

Exemple :

m_strModVersion = temptag.GetStr();

Un Mod peut donc choisir la chaîne qu’il transmet.

8. ModString, version et nickname ne doivent pas accorder de privilège

Le corpus historique montre explicitement :

Clientversion Thief
Mod Thief
Nick Thief
Ghost Mod
Client Emulation
random Modstring

Par conséquent :

Mauvaise règle

si mod == "TrustedMod"
    donner un bonus

Meilleure règle

Le ModString peut servir à :

diagnostic
compatibilité historique
statistiques
indice faible

mais pas à accorder seul :

crédits
slot prioritaire
bypass queue
confiance SX élevée

9. SecureIdent : exemple d’une donnée transformée en preuve

Le UserHash reçu dans le Hello est lui aussi choisi par le pair.

Pris seul :

UserHash = déclaration

Avec SecureIdent réussi :

UserHash + possession de la clé privée
= preuve cryptographique historique

L’eMule officiel utilise cette distinction dans plusieurs endroits.

Dans ClientList::AttachToAlreadyKnown() :

  • si deux connexions présentent un même UserHash ;
  • et que le client déjà connu possède une identité sécurisée validée ;
  • le nouveau client contradictoire peut être banni pour UserHash invalide.

C’est une excellente philosophie à généraliser :

la déclaration n’est pas le problème ; le privilège n’est accordé qu’après preuve.


10. Source Exchange : surface de pollution naturelle

10.1 Ce que SX transporte

Selon la version :

IP/ID
port
serveur
UserHash
options de connexion

Toutes ces informations sont fournies par le pair SX.

10.2 Défenses déjà présentes

CPartFile::AddClientSources() 0.72a vérifie :

  • version SX connue ;
  • cohérence exacte taille / nombre d’entrées ;
  • format de chaque version ;
  • IP valides ;
  • IPFilter ;
  • clients bannis ;
  • règles CanAddSource() ;
  • limite maximale de sources ;
  • dédoublonnage ultérieur via CheckAndAddSource().

Le commentaire SX1 dit explicitement que certaines vérifications réduisent le risque de :

wrong source data
wrong userhashes
duplicate sources

10.3 Limite fondamentale

Même après toutes ces vérifications :

IP syntaxiquement valide

ne prouve pas :

source en ligne
source possédant ce fichier
source répondant
source utile

11. Capability Trust : annoncer une fonction ne suffit pas

Exemple :

SX version = 4
CLAIMED_SX4
OBSERVED_VALID_SX4
OBSERVED_BROKEN_SX4

Réaction possible :

si un pair annonce une capacité mais produit plusieurs réponses invalides :

désactiver cette fonctionnalité pour ce pair

plutôt que :

bannir complètement le pair

Cela réduit les faux positifs et conserve la compatibilité.


12. Fast Reask / requêtes agressives

L’eMule officiel possède déjà une protection.

UploadClient.cpp::AddRequestCount()

Si le même fichier est redemandé avant :

MIN_REQUESTTIME = 10 minutes

et que le pair n’a pas de Friend Slot :

badrequests++

À :

BADCLIENTBAN = 4

le client peut être banni.

C’est un exemple de protection 100 % comportementale :

eMule ne cherche pas à savoir quel Mod est utilisé.

Il observe seulement :

ce client redemande trop vite

13. File Request Flood

BaseClient.cpp::CheckFailedFileIdReqs()

Les requêtes répétées portant sur des identifiants de fichiers invalides sont comptées.

Après répétitions et accumulation dans BadRequests, le client peut être banni avec :

FileReq flood

Encore une fois :

preuve locale du comportement

plutôt que :

liste noire de noms de Mods

14. Queue Rank Flood

Même logique :

QR reçus alors qu’ils n’étaient pas attendus

sont comptés.

Après répétitions :

Ban("QR flood")

Le rang lui-même peut mentir.

Le flood, lui, est objectivement observable.


15. Spam

L’eMule officiel possède aussi :

SetSpammer(true)
→ Ban("Identified as Spammer")

Le dossier Trust devra plus tard examiner précisément les critères de classification comme spam afin de distinguer les règles robustes des heuristiques historiques.


16. Plusieurs clients depuis la même IP

UploadQueue.cpp contient déjà une limitation afin d’éviter qu’une même IP occupe trop d’entrées dans la waiting queue.

C’est une protection contre une forme simple de multiplication d’identités.

Limite :

elle ne protège pas contre des pairs utilisant réellement plusieurs IP

et ne doit pas être étendue naïvement à des environnements NAT où plusieurs utilisateurs légitimes partagent une adresse.

17. Données corrompues : une défense fondée sur les conséquences

L’eMule 0.72a possède :

CorruptionBlackBox

Le système enregistre les plages reçues et leurs expéditeurs.

Après vérification :

VerifiedData()
CorruptedData()
EvaluateData()

peuvent déterminer les clients ayant contribué aux zones corrompues.

Le code peut ensuite bannir un client lorsque la proportion de données corrompues attribuées dépasse la limite prévue.

Intérêt architectural

C’est probablement l’un des meilleurs exemples de défense historique :

pas besoin de croire le ModString
pas besoin de deviner l’intention

La sanction est liée à des octets réellement reçus et vérifiés comme mauvais.


18. Hashes : la donnée finale ne dépend pas de la parole du pair

Un client peut annoncer posséder une partie.

Il peut même envoyer des octets.

Mais la partie n’est considérée valide qu’après vérification :

ED2K / MD4
et éventuellement
AICH

Il s’agit d’un excellent exemple de design zéro-confiance avant l’heure :

recevoir
≠
accepter comme valide

19. Part Status : déclaration utile, preuve faible

La carte de parties du pair est nécessaire pour sélectionner les blocs.

Mais elle est contrôlée par le pair distant.

Remote Claim

La confiance augmente seulement lorsque :

le pair accepte effectivement les requêtes correspondantes
et fournit des données valides

À mesurer

parts advertised
requests attempted
requests fulfilled
valid payload

Un taux faible n’est toutefois pas automatiquement une triche :

fichier modifié
session interrompue
source obsolète
A4AF
changement d’état

La détection doit être statistique et prudente.


20. Pourquoi les vieilles blacklists sont insuffisantes

Argos, DLP et d’autres systèmes ont souvent utilisé :

modstrings connues
nick patterns
version patterns
hash patterns
bad opcodes

Ils étaient utiles dans le contexte de leur époque.

Mais une blacklist possède plusieurs défauts :

facile à contourner en changeant l’identifiant
vieillit rapidement
faux positifs
maintenance externe nécessaire
peut confondre client rare et client hostile

21. Ce que nous devons récupérer des anciens Anti-Leecher

À conserver conceptuellement

détection multi-critères
corrélation dans le temps
différents niveaux d’anomalies
historique par client
réactions graduées
protection anti-thief
protection fast-reask
analyse des incohérences protocole

À ne pas copier aveuglément

ban sur ModString seul
ban sur pseudo seul
ban permanent au premier signal
community favoritism
règles spécifiques à des Mods disparus
signatures non expliquées

23. Exemple

PeerTrustProfile

IdentityTrust
  UserHash              claimed
  SecureIdent           verified
  result                HIGH

ProtocolCompliance
  malformed packets     0
  file request floods   0
  QR floods             0
  result                HIGH

QueueSignalTrust
  remote QR             unverifiable
  suspicious changes    3
  result                UNKNOWN

SourceExchangeQuality
  received              143
  valid syntax          143
  new                    62
  reachable              34
  useful                 19
  result                 NORMAL

DataIntegrity
  verified bytes         1.8 GiB
  corrupt attributable   0
  result                 HIGH

Ce profil n’a pas besoin d’être affiché tel quel à l’utilisateur normal.

Il sert au moteur et au diagnostic.


24. Provenance de chaque donnée

Proposition très importante :

LOCAL_MEASURED
REMOTE_CLAIM
CRYPTO_VERIFIED
HASH_VERIFIED
CROSS_CHECKED
HEURISTIC

Exemples :

RemoteQueueRank
value=17
origin=REMOTE_CLAIM

CreditDownloadedBytes
value=412 MiB
origin=LOCAL_MEASURED

SecureIdentity
state=VALID
origin=CRYPTO_VERIFIED

BlockIntegrity
state=GOOD
origin=HASH_VERIFIED

Cela permet de voir immédiatement dans le code si une décision forte dépend d’une donnée faible.


25. Trust Boundary Review

1. quelles entrées utilise-t-elle ?
2. qui contrôle ces entrées ?
3. peuvent-elles être vérifiées ?
4. quel avantage accordons-nous ?
5. que se passe-t-il si elles sont fausses ?

Exemple actuel :

SwapToRightFile()
entrée : RemoteQueueRank
contrôlé par : pair distant
preuve : aucune
effet : influence décision de swap

Statut :

AUDIT PRIORITAIRE

26. Réactions graduées

Proposition de niveaux :

R0 — Observer

aucune conséquence
log / métrique seulement

R1 — Ignorer la donnée

Exemple :

RemoteQR jugé incohérent
→ ne plus l’utiliser pour une optimisation

R2 — Désactiver la capacité

Exemple :

SX4 annoncé mais réponses répétées invalides
→ plus de SX avec ce pair pendant cette session

R3 — Cooldown

Exemple :

requêtes trop rapides
→ ignorer temporairement

R4 — Disconnect

Pour violation importante de session.

R5 — Temporary Ban

Réservé aux preuves fortes :

flood répété
usurpation SecureIdent établie
corruption attribuée au-delà du seuil

27. Le ban doit être explicable

Chaque sanction devrait avoir :

reason_code
evidence
timestamp
duration
scope

Exemple :

BAN
reason=QR_FLOOD
evidence=3 unsolicited QR + badrequest threshold
duration=historical default

Pas :

BAN
reason=leecher

Cette différence sera très importante pour le support et le développement.


28. Temporaire plutôt que définitif

Le réseau est dynamique.

Une IP peut plus tard appartenir à un autre utilisateur.

Un NAT peut représenter plusieurs utilisateurs.

Une erreur réseau peut imiter un comportement mauvais.

états à durée de vie limitée
dégradation progressive
réévaluation

sauf données persistantes cryptographiquement liées à une identité.


29. Pas de bonus fondé sur des données non vérifiables

Une Remote Claim ne doit jamais suffire seule à obtenir un privilège local significatif.

Exemples de privilèges :

slot immédiat
crédit artificiel
contournement de queue
bypass de limites
priorité spéciale

Cette règle aurait historiquement évité une partie des mécaniques exploitables par Fake Rank / Community Faker.


30. Attention aux mécanismes communautaires

Le corpus Applejuice comporte plusieurs fonctions :

Community
Community Faker
ignore hard limit for community
boost
special slots

Dès qu’un label distant ouvre un privilège local :

« je suis membre de la communauté »

il devient une cible naturelle de falsification.


31. Telemetry : mesurer les attaques réellement présentes en 2026

Beaucoup de protections historiques ciblent peut-être aujourd’hui des comportements disparus.

Nous ne devons pas supposer.

Proposition :

[TRUST_ANOMALY]
type=QR_UNSOLICITED
peer=anon-id
count=...

[TRUST_ANOMALY]
type=SX_INVALID_PACKET
version=4
expected=...
received=...

[TRUST_ANOMALY]
type=CAPABILITY_CONTRADICTION
claimed=SX4
observed=invalid_sx4

[TRUST_ANOMALY]
type=FILE_REASK_TOO_FAST
delta=...

Après plusieurs semaines :

quelles attaques existent réellement ?
quelles protections ne se déclenchent jamais ?
quels signaux créent des faux positifs ?

32. Confidentialité des logs

Un journal Trust ne doit pas devenir une base inutilement intrusive.

Par défaut :

pas de UserHash complet
pas d’IP persistée indéfiniment
identifiant pseudonymisé de session
durées de rétention courtes

Pour debug volontaire :

mode détaillé explicite

33. Patch immédiat 1 — annoter la confiance du Remote QR

Aucun changement protocolaire.

Première étape :

// Remote-provided, unverifiable queue position.
// Never treat as authoritative.
m_nRemoteQueueRank = nr;

Puis créer des compteurs d’usage :

remote_qr_received
remote_qr_used_for_swap
remote_qr_threshold_le50
remote_qr_threshold_gt50

But :

savoir si la branche QR 50 est encore réellement importante.


34. Patch immédiat 2 — Decision Trace autour de SwapToRightFile

Ajouter uniquement du diagnostic.

Exemple :

[A4AF_SWAP_DECISION]
from=fileA
to=fileB
remoteQR=17
remoteQRTrust=UNVERIFIED
sxAllowedA=yes
sxAllowedB=no
decision=SWAP
reason=REMOTE_QR_LE_50

Cette trace nous permettra de mesurer exactement l’influence d’une donnée falsifiable.


35. Patch immédiat 3 — Source Exchange Quality Metrics

Ajouter à la provenance SX :

provider client
source announced
source accepted
source duplicate
source rejected-IP
source connected
source useful

Ne pas punir dans un premier temps.

Observation seulement.


36. Patch immédiat 4 — centraliser les anomalies protocole

Aujourd’hui, les protections sont dispersées :

CheckQueueRankFlood
CheckFailedFileIdReqs
AddRequestCount
CorruptionBlackBox
SecureIdent
same-IP queue logic

Créer à terme :

PeerProtocolMonitor

qui collecte les événements sans nécessairement remplacer les mécanismes existants.

Première phase :

miroir des événements

Aucun changement de comportement.


37. Patch immédiat 5 — le CSPRNG SecureIdent du dossier 03

Il s’intègre directement au Trust Model.

Le challenge SecureIdent est une preuve.

Il doit donc être généré avec une source d’aléa adaptée.

Remplacer :

rand()+1

39. Fuzzing défensif

Les parsers de paquets anciens sont un bon candidat au fuzzing local.

Objectif :

aucun crash
aucun dépassement
aucune allocation aberrante
aucun état impossible

Cibles prioritaires :

Hello / HelloAnswer
MuleInfo
SX1 / SX2
QueueRank
FileRequest
PartStatus
AICH

Le fuzzing concerne ici la robustesse de notre propre client.

Il ne nécessite aucune émission vers le réseau réel.


41. Matrice de confiance proposée

Information Source Vérifiable ? Utilisation recommandée
Nickname pair non affichage
ModString pair non diagnostic / indice faible
Client version pair partiellement par comportement compatibilité prudente
Remote QR pair non heuristique faible
UserHash pair oui via SecureIdent identité après preuve
Octets transférés local oui crédits / stats
Source SX pair seulement par essai découverte avec filtrage
Part Status pair seulement par transfert planification prudente
Bloc reçu local oui provisoire jusqu’au hash
Bloc/part vérifié hash oui forte confiance
Fréquence de requêtes local oui anti-abus
Paquet malformé local oui compliance
Corruption attribuée local + hash oui avec limites forte anomalie

42. Architecture proposée

PeerTrustProfile

Données par pair.

PeerEvidenceStore

Événements avec :

type
scope
strength
timestamp
expiration

PeerProtocolMonitor

Collecte :

flood
malformed packet
capability contradiction
rate violation

PeerQualityMonitor

Collecte :

SX yield
valid data
connection success
part claim success

PeerPolicy

Transforme les preuves en actions graduées.


43. Ne pas utiliser une moyenne magique

Exemple à éviter :

TrustScore = 72/100

Pourquoi ?

Parce qu’un client pourrait :

être excellent pour les données
mais mauvais pour SX

Une moyenne cacherait cette distinction.

Meilleure approche :

DataIntegrity = HIGH
SXQuality = LOW
QueueSignal = UNKNOWN
Identity = VERIFIED

Puis chaque sous-système n’utilise que la dimension qui le concerne.


44. Intégration à Source Discovery Manager

Dossier 01 :

Source Discovery Manager

peut maintenant utiliser :

SXQuality

mais pas :

ModStringTrust

Exemple :

deux pairs nous proposent 50 sources.

Pair A :
50 proposées
35 joignables historiquement

Pair B :
50 proposées
2 joignables historiquement

45. Intégration à Upload Intelligence

Dossier 04 :

l’Upload Queue doit utiliser seulement :

temps local
crédits locaux vérifiés
priorité locale
états localement observés

et jamais :

Remote Queue Rank
Remote ModString
Remote claimed ratio

pour accorder directement un slot.


46. Intégration à Connectivity Intelligence

Dossier 02 :

les capacités de callback annoncées peuvent être :

CLAIMED

puis évoluer vers :

OBSERVED_WORKING

si une tentative réussit.


47. Intégration à Identity Health

Dossier 03 :

SecureIdent devient la racine de confiance de l’identité historique.

Un ModString ne doit pas remplacer SecureIdent.

Un UserHash identique sans preuve cryptographique doit rester suspect lorsqu’il existe une identité sécurisée connue.


48. Ce que nous pouvons tirer d’Argos et Client Analyzer

L’idée la plus intéressante n’est pas la liste de Mods bannis.

C’est la corrélation multi-critères.

Argos documente :

modstring
pseudo
logiciel
hash
opcode
fast ask
SX exploit
tags invalides
violations protocole
plusieurs signaux indépendants

mais donner beaucoup plus de poids aux signaux :

objectivement observables

qu’aux simples chaînes de caractères.


49. Ordre de confiance suggéré

Du plus solide au plus faible :

hash / signature cryptographique
        ↓
mesure locale directe
        ↓
comportement répété cohérent
        ↓
corrélation de plusieurs déclarations
        ↓
déclaration distante isolée
        ↓
ModString / nickname / réputation statique

51. Conclusion

Le réseau eD2K/eMule a été conçu dans un environnement ouvert où les clients peuvent être modifiés.

Les anciens Leecher Mods démontrent que :

un paquet valide peut contenir une information mensongère

et les anciens Anti-Leecher démontrent que cette réalité était connue depuis longtemps.

Elle doit construire un modèle clair :

déclaration → observation → vérification → décision proportionnée

avec une règle centrale :

les avantages locaux doivent reposer autant que possible sur des faits mesurés par notre propre client.



Dossier 05 terminé

Trust Model, Leecher Mods et données distantes non fiables

← Dossier 04Dossier 06 →