Geek++ · Dossier 12 / 25

Audit Hello / HelloAnswer / négociation des capacités

Étude technique publique · 1,123 mots · ≈ 5 min de lecture attentive

Étude intégraleSans réflexion CODEXSources & constantes conservées
Handshake
Client A
HELLO →← HELLOANSWERcapabilities
Client B

Périmètre : établissement client-client et négociation des capacités. Les pistes ci-dessous sont des sujets de mesure ou de robustesse, pas des fonctions produit annoncées.

1. Sources auditées

BaseClient.cpp
UpdownClient.h
ClientList.cpp
ClientUDPSocket.cpp
Packets.cpp
Opcodes.h
edonkey-protocol.txt

2. Handshake historique

Le wire eDonkey contient déjà :

OP_HELLO       0x01
OP_HELLOANSWER 0x4C

Le document historique associe ce handshake à un Client info puis à l’adresse serveur.

3. Construction du Hello actuel

SendHelloPacket() écrit :

uint8 = 16
SendHelloTypePacket()
opcode = OP_HELLO

Le 16 correspond historiquement à la taille du UserHash qui ouvre le corps du Hello.

4. HelloAnswer

SendHelloAnswer() appelle le même :

SendHelloTypePacket()

puis utilise OP_HELLOANSWER.

Le contenu principal est donc symétrique.

5. Tronc commun du payload

SendHelloTypePacket() écrit notamment :

UserHash 16
eD2K ID uint32
TCP port uint16
TagCount
Tags...
Server IP
Server port

Les extensions modernes vivent surtout dans les tags.

6. CT_NAME

Valeur :

pseudonyme utilisateur

Classe de confiance :

DISPLAY_CLAIM

Ne jamais utiliser ce champ comme identité forte.

7. CT_VERSION

Valeur de base :

EDONKEYVERSION = 0x3C

Ce champ historique n’est pas la version logicielle complète eMule.

8. CT_EMULE_UDPPORTS

Packing actuel :

bits 31..16 = Kad UDP port
bits 15..0  = eMule UDP port

Le Kad port annoncé peut être le port externe vérifié ou le port interne configuré selon l’état du firewall tester.

9. Buddy tags

Si :

Buddy présent
ET
client firewalled

la branche ajoute :

CT_EMULE_BUDDYIP
CT_EMULE_BUDDYUDP

Ces champs influencent le chemin de callback.

10. CT_EMULE_MISCOPTIONS1

Packing observé :

AICH version              << 29
Unicode                   << 28
UDP version               << 24
Data compression          << 20
SecureIdent               << 16
SX1 version               << 12
Extended Requests         << 8
Comments                  << 4
PeerCache                 << 3
NoViewSharedFiles         << 2
MultiPacket               << 1
Preview                   << 0

Plusieurs champs occupent plusieurs bits.

11. Valeurs MISC1 actuelles

Branche étudiée :

AICH = 1
Unicode = 1
UDPVer = 4
Compression = 1
SecureIdent = 3 si crypto disponible
SX1 = 4
ExtendedRequests = 2
Comments = 1
MultiPacket = 1
Preview selon réglage
PeerCache = 0

Le commentaire SX1 rappelle un héritage de compatibilité.

12. CT_EMULE_MISCOPTIONS2

Il regroupe notamment :

Kad version
LargeFiles
ExtMultiPacket
reserved/mod bit
SupportsCryptLayer
RequestsCryptLayer
RequiresCryptLayer
SupportsSourceEx2
SupportsCaptcha
DirectUDPCallback

Avant toute documentation octet-par-octet définitive, le packing exact doit être recoupé avec le parser, aMule et des captures.

13. Connect Options condensées

SetConnectOptions(uint8) interprète :

bit 0 = crypt support
bit 1 = crypt request
bit 2 = crypt require
bit 3 = direct UDP callback

Cette forme compacte réapparaît dans des réponses de sources et callbacks.

14. États contradictoires possibles

Paquets théoriquement incohérents :

RequiresCrypt = 1
SupportsCrypt = 0

ou :

DirectCallback = 1
sans port exploitable

Le parser doit rester robuste et la machine d’état choisir un comportement conservateur.

15. Ancien OP_EMULEINFO

SendMuleInfoPacket() écrit :

eMule short version
EMULE_PROTOCOL
7 tags

Tags actuels :

compression
UDP version
UDP port
SourceExchange
Comments
ExtendedRequests
Features

16. ET_FEATURES

Le champ legacy combine notamment SecureIdent et Preview. Il existe donc une duplication historique entre plusieurs mécanismes d’annonce.

17. ProcessMuleInfoPacket()

Le parser conserve des déductions implicites pour d’anciennes versions :

UDP v1
SX1 v1
comments
shared directories

Commentaire clé du code :

in the future do not use version to guess about new features

18. Principe d’extension

Toute future fonction qui exigerait une interop devrait préférer :

capability explicite

à :

if software version >= X

Mais aucun nouveau bit n’est justifié tant qu’un besoin wire réel n’existe pas.

19. Classification du logiciel

InitClientSoftwareVersion() distingue entre autres :

cDonkey
xMule
aMule
Shareaza
lphant
MLdonkey
eDonkeyHybrid
eMule-compatible

Utilité :

UI
debug
compatibilité

Pas :

preuve de confiance

20. Mod string / version string

Un pair peut falsifier une chaîne logicielle. Toute logique anti-leecher fondée uniquement sur ce nom serait fragile.

Le D05 reste la référence pour une confiance fondée sur des observations.

21. Connexion obfusquée

CUpDownClient::Connect() active la couche d’obfuscation si :

UserHash valide
remote SupportsCrypt
local Crypt enabled
ET
(remote RequestsCrypt OU local Preferred)

Sinon, elle reste en clair si la politique le permet.

22. Required Crypt

Les incompatibilités sont également filtrées lors de l’admission des sources.

Si une extrémité exige un mode que l’autre ne peut satisfaire :

source/connexion inutilisable

Cette interaction doit être étudiée avec D13.

23. Large Files

La capability gouverne l’usage de variantes telles que :

OP_COMPRESSEDPART_I64
OP_SENDINGPART_I64
OP_REQUESTPARTS_I64

Tester explicitement les frontières de taille.

24. MultiPacket

Le protocole conserve plusieurs générations :

OP_MULTIPACKET          deprecated
OP_MULTIPACKET_EXT      deprecated
OP_MULTIPACKET_EXT2     moderne

Les anciennes branches sont des chemins de compatibilité susceptibles d’être peu testés aujourd’hui.

25. Hashset v2 / FileIdentifier

Les opcodes :

OP_HASHSETREQUEST2
OP_HASHSETANSWER2

utilisent un FileIdentifier plus riche et peuvent demander des données MD4/AICH selon options.

À relier au D07 et au D14.

26. Direct UDP Callback

Le bit local n’est activé que si :

Kad actif
TCP firewalled
UDP non-firewalled
UDP verified

Il s’agit donc déjà d’une capability calculée à partir d’observations.

32. Evidence de capacités

Structure conceptuelle locale :

PeerCapabilities {
    announced
    negotiated
    successfully_used
    failed
}

Sans score unique.

33. Claimed vs observed

Exemples :

annonce SX2
→ requête SX2
→ réponse valide ?
annonce AICH
→ répond à AICH ?

Cela peut aider au diagnostic de clients atypiques.

34. Ne pas pénaliser immédiatement

Une incohérence peut venir d’un vieux client, d’un bug, d’un Mod expérimental, d’un paquet partiel ou d’une mauvaise interprétation de notre parser.

Première phase :

observer
journaliser
rejouer

pas bannir.

35. Dette de compatibilité

Inventorier toutes les zones où :

version logicielle
→ capacité supposée

et les classer :

legacy indispensable
legacy encore active
supposition remplaçable par flag

36. Machine d’état

Tester aussi l’ordre des messages :

HelloAnswer sans Hello
double Hello
MuleInfo prématuré
File Request avant fin du handshake

La robustesse dépend autant de l’ordre que des champs.

37. Identité

Trois niveaux doivent rester séparés :

UserHash déclaré
clé publique SecureIdent connue
signature SecureIdent vérifiée

Ne jamais convertir le premier en troisième dans une métrique.

38. Vie privée / fingerprinting

Le Hello révèle déjà :

nickname
capabilities
versions
ports
server
Buddy éventuel

Chaque nouvelle capability publique augmente un peu le fingerprinting. Toute extension future doit donc avoir un besoin d’interop réel.

39. Compatibilité passive d’abord

Pour une expérimentation locale, préférer :

instrumentation
logs
compteurs

à un nouveau tag/opcode.

40. Lien D12 → D13

D12 répond :

« comment savons-nous que le pair comprend l'obfuscation ? »

D13 répondra :

« que fait réellement cette obfuscation au flux ? »

Ne pas confondre négociation de capability et sécurité cryptographique.

41. Conclusion

Le handshake eMule est une couche de négociation riche construite autour d’un cœur eDonkey très ancien.

Les risques techniques intéressants aujourd’hui sont surtout :

legacy inference
tags malformés
flags incohérents
chemins peu testés
claims pris à tort pour des preuves

La meilleure première étape est la couverture de tests et l’observabilité, pas l’ajout de nouvelles capacités.

================================================================================================


Dossier 12 terminé

Audit Hello / HelloAnswer / négociation des capacités

← Dossier 11Dossier 13 →