Une fois, avant de défendre un autre travail de laboratoire, ils m'ont posé une question: quels champs d'un paquet IP peuvent être utilisés pour le matelassé? Je ne savais pas et je haussai simplement les épaules. Mais bientôt, j'ai quand même décidé d'étudier cette question.
Sous la coupe, vous trouverez l'étude des en-têtes de paquets IP, le propre utilitaire ping de Python et plusieurs façons de transférer des données sans attirer l'attention.
Table des matières
- Structure des paquets IP
- Réglage de l'environnement
- Ping: option facile
- Ping: option difficile
- Des améliorations?
Structure des paquets IPv4

Sélectionnez les champs dont le changement n'affectera pas grandement le package:
Le DIH peut varier de 5 à 15.
Le champ
ToS est utilisé pour hiérarchiser les notifications de trafic et de congestion sans perdre de paquets. Le plus souvent, ce champ est 0. Théoriquement, il peut être utilisé pour transmettre un octet entier d'informations.
La longueur du paquet est un excellent champ pour transmettre des nombres de 20 à 65535.
TTL peut transmettre jusqu'à 7 bits d'informations. Vous devez connaître le nombre de sauts vers l'hôte et en tenir compte.
Réglage de l'environnement
Pour répéter l'expérience, vous aurez besoin de deux machines avec Python et le framework scapy.
Vous pouvez l'installer en suivant les
instructions de la documentation . Dans mon cas, il s'agissait de deux gouttelettes sur DO avec le réseau local activé. Pour tester l'opérabilité du stegano, deux itinéraires ont été choisis: via le réseau local pour 1 saut et via Internet pour 2 sauts.
Ping: option facile
D'abord, nous implémentons sender.py, qui enverra des paquets ICMP sans messages cachés.
from scapy.all import *
Scapy remplira les champs restants avec des valeurs par défaut avant l'envoi et calculera la somme de contrôle.
Du côté de la réception, écrivez listener.py, qui écoutera et affichera tous les paquets ICMP entrants.
from scapy.all import *
Sortie d'écoute ###[ Ethernet ]### dst = hh:hh:hh:hh:hh:hh src = gg:gg:gg:gg:gg:gg type = 0x800 ###[ IP ]### version = 4 ihl = 5 tos = 0x0 len = 28 id = 24923 flags = frag = 0 ttl = 64 proto = icmp chksum = 0x4364 src = 10.0.0.1 dst = 10.0.0.2 \options \ ###[ ICMP ]### type = echo-request code = 0 chksum = 0xf7ff id = 0x0 seq = 0x0 ###[ Padding ]### load = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
L'en-tête de paquet IP a un champ identifiant. Remplissez-le avec les symboles «A» et «B»:
payload = ord("A") * 0x100 + ord("B") pkt = IP(src="10.0.0.1", dst="10.0.0.2", id = payload) / ICMP(type = 8)
De plus, dans l'en-tête ICMP, il y a exactement le même champ dans lequel deux octets peuvent également être chargés.
Modifiez l'écouteur pour afficher les données reçues:
from scapy.all import * import sys packets = sniff(filter="icmp", timeout = 10, count = 100, iface="eth0") for pkt in packets: if pkt[ICMP].type != 8: continue
Dans l'image et la ressemblance, vous pouvez remplir presque n'importe quel champ qui a été précédemment noté comme approprié pour la courtepointe.
Ping: option difficile
Le transfert de données du paragraphe précédent n'était pas le plus évident, mais nous pouvons le rendre encore moins évident. Vous pouvez masquer les données dans le champ de la somme de contrôle. Selon
RFC1071, une somme de contrôle est (soudain!) Une inversion au niveau du bit d'une somme arithmétique légèrement plus complexe.
Explication avec un exempleSupposons que nous ayons un en-tête pour lequel nous voulons calculer la somme de contrôle. Au moment du calcul, le champ de somme de contrôle est réinitialisé.
4500 003c 000a 0000 8001 [checksum] c0a8 000d c0a8 000d
1. Additionnez tous les mots de 16 bits, en vous souvenant du transfert de haut niveau:
4500 + 003c + 000a + 0000 + 8001 + [checksum=0000] + c0a8 + 000d + c0a8 + 000e = = (2) 46b2
2. Additionnez le résultat avec les transferts:
46b2 + 2 = 46b4
3. Inverser:
~(46b4) = b94b
b94b est la somme de contrôle que nous
recherchons . Pour vérification, vous pouvez remplacer dans l'en-tête et effectuer les étapes 1 et 2. Si vous obtenez FFFF, le montant trouvé est correct.
Vérification:
1. 4500 + 003c + 000a + 0000 + 8001 + [checksum=b94b] + c0a8 + 000d + c0a8 + 000e = = (2) FFFD 2. FFFD + 2 = FFFF
Nous savons que la somme de contrôle d'un paquet change à mesure que les nœuds traversent le réseau, à mesure que le TTL change. De plus, lors du passage par NAT dans le paquet, «l'adresse source» est remplacée, ce qui affecte également la somme de contrôle. Et combien TTL diminuera en atteignant notre auditeur ... La cerise sur le gâteau est que le témoin de l '"identifiant" coïncide avec le témoin de la somme de contrôle. Ce fait nous permet d'influencer la somme de contrôle et de la changer en n'importe quelle valeur de la zone de définition. Étant donné que la somme de contrôle (charge utile) sera calculée uniquement lors du passage du dernier nœud de la route, il est important de prendre en compte tout ce qui peut être modifié dans le paquet pendant la route lors du calcul.
L'algorithme de recherche de "l'identifiant", qui nous donnera la somme de contrôle souhaitée:
- Nous configurons le package comme lors du passage sur le dernier nœud (IP, TTL, etc.)
- Dans "l'identifiant", écrivez la charge utile
- Nous calculons la somme de contrôle
- Le résultat doit être écrit dans "l'identifiant" du paquet envoyé
Nous allons écrire une fonction qui formera un paquet par le nombre d'espoirs, les IP derrière NAT et deux octets de charge utile.
Des améliorations?
- les champs chksum, seq, id dans l'en-tête du protocole ICMP peuvent également être utilisés pour transmettre des données
- Les ToS peuvent être utilisés pour identifier les packages "par eux-mêmes" et ignorer la demande d'écho des autres.