Streamer une caméra TecTecTec XPro2 sur PC : Différence entre versions

De Ensiwiki
Aller à : navigation, rechercher
(Exploitation des données capturées)
Ligne 1 : Ligne 1 :
 +
[[Catégorie:Projets]]
 +
[[Catégorie:Projets Réseaux Mobiles et Avancés]]
 +
 
== Présentation ==
 
== Présentation ==
 
L'objectif principal du projet est de pouvoir streamer le flux vidéo de la caméra sur un ordinateur. La caméra ne peut actuellement que streamer vers un smartphone via une application dédiée.
 
L'objectif principal du projet est de pouvoir streamer le flux vidéo de la caméra sur un ordinateur. La caméra ne peut actuellement que streamer vers un smartphone via une application dédiée.

Version du 9 avril 2018 à 09:47


Présentation

L'objectif principal du projet est de pouvoir streamer le flux vidéo de la caméra sur un ordinateur. La caméra ne peut actuellement que streamer vers un smartphone via une application dédiée.


Comment Faire ?

Prérequis

Matériel nécessaire

  • 1 Caméra TecTecTec XPro2
  • 1 Ordinateur avec carte réseau supportant le mode monitor et un OS Linux de préférence

Logiciel nécessaire

  • airmon-ng pour utiliser le mode monitor de la carte wifi
  • Wireshark pour analyser le traffic réseau de la caméra
  • ffplay ou VLC pour lire le flux vidéo

Analyse du réseau

Activation du mode monitor

Le mode monitor permet à un récepteur Wifi d'écouter la totalité du traffic réseau à sa portée sans se limiter au réseau auquel il appartient. Ce mode d'écoute n'est pas compatible avec toutes les cartes réseau. Une liste de cartes compatibles est disponible à cette adresse :

Il est possible d'activer le mode monitor de deux manières :

Avec iwconfig

 ifconfig wlan0 down
 iwconfig wlan0 mode monitor
 ifconfig wlan0 up

Avec la suite aircrack

 airmon-ng check kill
 airmon-ng start wlan0

Il est ensuite possible de monitorer les échanges Wifi grace à la commande

 airodump-ng <iface>

Prévention du channel hopping

Un réseau Wifi opère sur des canaux (une bande de fréquences) afin de limiter les interférences avec d'autres équipements. Pour le Wifi 2.4GHz il existe 14 canaux et chaque point d'accès fonctionne sur un canal pré-déterminé. Une carte réseau en mode monitor ne peut écouter le traffic que sur un seul canal à la fois. Elle vas donc faire du channel-hopping (c'est à dire qu'elle va changer de canal ou bout d'un très petit intervalle de temps) afin de pouvoir écouter le traffic sur l'ensemble des canaux. Cela a cependant le gros désavantage de rater une partie des paquets émis. Il est heureusement possible de spécifier un canal précis à monitorer. Les autres canaux seront alors ignoré et nous pourrons enregistrer l'intégralité du traffic qui nous intéresse. Grace à airodump-ng il est possible de voir sur quel canal (channel) Wifi la caméra TecTecTec est active (ici le canal 6) Une fois le canal identifié il faut redémarrer la carte réseau en mode monitor sur le canal utilisé par la caméra

 airmon-ng stop wlan0mon
 airmon-ng check kill
 airmon-ng start wlan0 6


Capture du traffic avec Wireshark

En lançant Wireshark sur l'interface passée précédement nous pouvons désormais capturer l'ensemble du traffic sur le canal étudié. Il reste cependant un problème majeur : L'intégralité du traffic est crypté, généralement en WPA2. Il nous est cependant possible, en streamant le flux vidéo de la caméra sur un smartphone et étudiant la forme des paquets reçus de déterminer quels sont les BSSID de la caméra et du smartphone pour filter le traffic et ne garder que celui entre les deux appareils.

Décryptage WPA

Pour décrypter le traffic entre les deux appareils nous avons besoin de deux choses : La clé WPA2 et le dialogue de connexion entre les deux appareils (4-way handshake). Pour récupérer le 4-way Handshake il faut procéder de la façon suivante :

  • Déconnecter le smartphone du Wifi
  • Aller dans les préférences Wifi et "Oublier" le point d'accès correspondant à la caméra
  • Lancer la capture de traffic avec Wireshark
  • Connecter le smartphone au wifi de la caméra
  • Effectuer la capture

Une fois la capture terminée il est possible de vérifier que le 4-way handshake a bien été capturé en filtrant les paquets de type EAPOL (filtre eapol dans Wireshark) et en vérifiant ques les 4 paquets sont bien capturés ("1 of 4", "2 of 4", "3 of 4" et "4 of 4" ).

Pour décrypter le traffic il faut alors se rendre sous Wireshark dans Edit->Preferences->Protocols->IEEE 802.11 Cliquer sur edit keys et ajouter une entrée de type wpa-pwd en entrant dans le champ key lePassword:SSID_du_reseau Valider et cocher les cases "Assume packets have FCS" et "Ignore the protection bit YES - with IV" Retourner ensuite au résultat de la capture, normalement les paquets devraient être décryptés et vous devriez maintenant voir les adresses IP de la caméra et du téléphone.

Exploitation des données capturées

Une fois le trafic décrypté, il faut analyser les différentes trames reçus pour tenter de comprendre le protocole entre le téléphone et la caméra. Tout d'abord, il est simple de constater que les échanges se font dans un premier temps avec le protocole TCP sur le port 6666. On applique ensuite le filtre suivant sur Wireshark afin d'afficher uniquement les trames utiles. L'option "follow TCP stream" est également très pratique.

FiltreWireshark.png

En parcourant les différentes trames, on remarque un format de paquet commun à toute les trames. Il est facilement reconnaissable car il débute par le magic number 0xABCD.

TrameTCPTecTecTec.png


Sur la caméra, un daemon écoute le port TCP 6666. Le client se connecte au point d'accès puis envoie une demande de connexion contenant un login et un mot de passe. Celui-ci n'est pas chiffré. La caméra accepte ensuite la connexion en renvoyant de nouveau un paquet contenant le login/mot de passe, admin/12345.

LoginPacket.png

Pour démarrer le streaming vidéo, le client envoie le paquet suivant : 0xABCD 0008 0000 01FF 0000. Le flux vidéo est alors envoyé sur le port UDP 6669 au client. De plus, la caméra vérifie régulièrement que le client est toujours présent en envoyant des paquets "Alive Request". En l'absence de réponse, la caméra finit par s'éteindre, considérant le client comme déconnecté. Les commandes associées sont les suivantes : 0x0000 1112 (Alive Request) et 0x0000 1113 (Alive Response).


A partir de maintenant, le format des paquets diffère selon ce modèle :

TrameUDPTecTecTec.png

Il existe 2 types de message UDP. Le type n°1 est celui contenant le flux vidéo au format brute H.264. Le numéro de séquence est incrémenté à chaque paquet. Après un certain nombre de paquets vidéo envoyés au client, la caméra envoie un paquet plus petit de type 2. Celui-ci indique le temps écoulé en milliseconde pour le groupe de paquet précédemment transmis.

UDPWiresharkTecTecTec.png


De nombreuses autres commandes existent, mais celles présentées ici sont suffisantes pour établir un streaming vidéo minimal.

Streamer sur un PC avec ffplay

Le stream vidéo en diffusé en H264 raw et directement encapsulé dans les trames UDP sans utilisation de protocole particulier. Pour lire le stream il nous suffit donc de simplement supprimer les entêtes UDP et de les lires directement avec ffplay.

En plus de celà nous devons également communiquer avec la caméra sur le port 6666 afin d'envoyer les commandes de login et de démarrage de stream ainsi que répondre à ses keep_alive pour ne pas interrompre le stream. Nous avons ainsi réalisé le programme suivant en nodeJS afin de réaliser ces opérations.

var net = require ("net");
var dgram = require("dgram");

var videoRcv = dgram.createSocket('udp4');
var videoSnd = dgram.createSocket('udp4');

var client = net.Socket();

var elapsed = 0;
var iSeq = 0;

//On se met sur le port 6669 utilisé par la caméra
videoRcv.bind(6669);

var videoBuffer = Buffer.alloc(0);
var rtp = Buffer.alloc(12);

videoRcv.on('listening', function(){
	console.log("En attente du stream sur le port 6669");
});

videoRcv.on('message', function(msg, info){
	//Récupération du type de payload
	var type = msg.readUInt16BE(6);
	
	if(type == 1) {//Type 1 => donnée videoBuffer
		videoBuffer = Buffer.concat([videoBuffer, msg.slice(8)]);
	} else if (type == 2){
		//Décommenter pour streamer sur VLC (Expérimental)
		//Et ajouter à VLC un fichier .SDP contenant les lignes suivantes
		//m=video 4242 RTP/AVP 99
		//a=rtpmap:99 H264/90000
		/*
                rtp.writeUInt16BE(0x8063, 0);
		rtp.writeUInt16BE(iSeq, 2);
		//elapsed * 90 à cause du h264
		//Le h264 demande un sample rate de 90Hz
		rtp.writeUInt32BE(elapsed * 90, 4);
		rtp.writeUInt32BE(0, 8);

		videoSnd.send(Buffer.concat([rtp, videoBuffer]), 4242, "127.0.0.1");
                */
		
		//Envoie le stream vidéo sur le port 6969 en localhost.
		//Peut être lu par ffplay directement
		videoSnd.send(videoBuffer, 6969, "127.0.0.1");
		
		elapsed = msg.readUInt32LE(20);
		videoBuffer = Buffer.alloc(0);
		iSeq++;
	} else {
		console.log("Type inconnu...");
	}
});

client.connect(6666, '192.168.100.1', function() {
	console.log("Connexion à la TecTecTec");
    
	//Création du packet de connexion à la caméra
	//0x0110 -> demande de login
	var packet = Buffer.from([0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
	packet.writeUInt16BE(0x0110, 6);
	
	var loginData = Buffer.alloc(128);
	
	//Les identifiants sont passé dans le packet
	loginData.write("admin", 0, 5, "ascii");
	loginData.write("12345", 64, 5, "ascii");
	
	//On ajoute les données au paquet et on l'envoie
	packet = Buffer.concat([packet, loginData]);
	//On change l'octet indiquant la taille du paquet pour mettre la nouvelle
	packet.writeUInt16BE(packet.length - 8, 2);
	sendToClient(client,packet);
});

client.on('data', function(data){
	//Commande envoyée par la caméra
	var commande = data.readUInt16BE(6);
	if(commande == 0x0111){ //Login accepté
		console.log("Connexion acceptée");
		sendCommand(client, 0xA034); //On demande la version de la caméra
	} else if (commande == 0x0112){ //ping?
		client.write(Buffer.from([0xab, 0xcd, 0x00, 0x00, 0x00, 0x01, 0x13])); //Demande de continuer le stream
	} else if (commande == 0xA035){ //Renvoie la version de la caméra
		sendCommand(client, 0x01FF, Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); //Demande le début du stream
	}
});

client.on('close', function() {
	console.log("Connexion perdue");
});

function sendCommand(client, commande, payload) {
	var p = Buffer.from([0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
	packet.writeUInt16BE(commande, 6);
	if(payload != null) {
		p = Buffer.concat([p, payload]);
	}
	p.writeUInt16BE(p.length - 8, 2);
	sendToClient(client, p);
}

function sendToClient(client, data) {
	client.write(data);
}

Une fois ce programme lancé il est possible de lire le stream vidéo avec la commande suivante :

 ffplay udp://127.0.0.1:6969

Extension : Streamer via internet

Une extension envisagée du projet est de pouvoir connecter la caméra à un réseau internet pour pouvoir ensuite visualiser le stream vidéo depuis n'importe quel PC. Pour cela il nous faut accéder au software de la caméra. Celle ci fonctionnant sous Android il est nous est possible de nous y connecter en utilisant ADB

Connecter la caméra à un PC

Utiliser un cable micro-USB - USB (Le même que pour la plupart des téléphones Android) pour brancher la caméra sur le PC

Windows

  • Télécharger et installer Android Minimal ADB and FastBoot ([1])
  • Installer Android SDK
  • Connecter la caméra en USB au PC
  • Ouvrir Minimal ADB and FastBoot
  • Entrer adb devices pour lister les appareils disponibles
  • Si la liste est vide
    • Ouvrir le gestionnaire de périphérique
    • La caméra doit apparaitre dans la catégorie "Android Devices" sous le nom Android. Faire un clic droit et sélectionner Mettre à jour le pilote..."
    • Sélectionner "Rechercher un pilote sur mon ordinateur"
    • Sélectionner "Choisir parmi une liste de pilotes de périphériques sur mon ordinateur"
    • Sélectionner "Afficher tous les périphériques"
    • Cliquer sur "Disque fourni..."
    • Cliquer sur "Parcourir" et aller dans [emplacement du sdk]\extras\google\usb_driver et sélectionner android_winusb.inf
    • Sélectionner 'Android ADB Interface' dans la liste.
    • Procéder à l'installation

Linux

Sous la plupart des distribution Linux le gestionnaire de packages permet d'installer très rapidement ADB Par exemple :

Debian, Ubuntu ...

 apt-get install adb

Fedora, SUSE ...

 yum install android-tools

Si cela n'est pas disponible pour votre distribution vous pouvez suivre ce [tutoriel]

Accéder au shell de la caméra

Une fois la caméra connecté au PC et ADB correctement installé il suffit, dans un terminal de commande d'entre la commande

 adb shell

Nous sommes alors dans le système d'exploitation de la TecTecTec.Première surprise nous somme connectés en root, ce qui vas nous faciliter la tâche.

Connecter la caméra à un réseau wifi

Une deuxième surprise nous attends en explorant les fichiers de la caméra, wpa_supplicant est installé alors qu'il est inutile au bon fonctionnement de la caméra. Ce outil nous permettra de connecter la caméra à un réseau wifi en ajoutant un fichier de configuration wpa_supplicant.conf

 update_config=1
 ctrl_interface=DIR=/data/system/wpa_supplicant GROUP=wifi
 eapol_version=1
 ap_scan=1
 fast_reauth=1
 network={
     ssid="SSID du réseau"
     psk="la passphrase du réseau"
     key_mgmt=WPA-PSK
     priority=241
 }

La commande ci dessous permet de se connecter au réseau préconfiguré.

 wpa_supplicant -i wlan0 -c <fichier de configuration>


Si une fois la caméra connectée au wifi celle-ci n'as toujours pas d'IP la commande suivante devrait lui en attribuer une.

 dhcpcd wlan0

Nous avons utilisé une carte Udoo afin de créer un Hotspot wifi pour y connecter la caméra. Une fois celle-ci joignable sur le réseau il nous a été possible de streamer sur un PC connecté à ce réseau. Afin de diffuser sur Internet il aurait fallut utiliser la deuxième interface réseau de la carte Udoo pour se connecter à l'internet et ensuite permettre à la caméra d'être joignable depuis cette deuxième interface.