[2/3] – Analyser le trafic d’un smartphone (l’enregistrement)

Suite mais pas fin de l’article [1/3] – Analyser le traffic d’un smartphone (le hotspot WIFI).

Ici nous allons voir comment enregistrer les paquets de données qui transitent sur votre hotspot. Vous comprendrez vite que l’écran et les boutons sont facultatifs, il ne font qu’appel à des lignes de commande qui peuvent être lancer depuis le terminal du Raspberry en session SSH.

Installation des paquets

Nous allons installer un petit utilitaire réseau très pratique et bien connu des bricoleurs réseau (et accessoirement des petits curieux que les gens on l’habitude d’appeler les PIRATE INFORMATIQUES ! Ouuuhh ! ), j’ai nommé tcpdump

sudo apt-install tcpdump

Et voila, c’est fini !

Enregistrement des paquets

Donc nous imaginons que votre Raspberry est branché, le hotspot est accessible et vous y avais connecté votre superbe smartphone chinois dessus.

Lancer la commande

sudo tcpdump -i wlan0 -s 0 -p

Même sans naviguer sur Internet avec votre smartphone, un certain nombre de lignes devraient apparaître dans votre terminal. Si ce n’est pas le cas, couper la couper avec Ctrl+c puis relancez la en remplaçant wlan0 par Br0.

Les lignes qui défilent correspondent aux paquets échangé entre le smartphone et la box et potentiellement avec Internet. En l’état, ce n’est pas réellement exploitable. Ajoutons donc un paramètre pour enregistrer ce résultats dans un fichier :

sudo tcpdump -i wlan0 -s 0 -p -w mon_tcpdump.pcap

Maintenant, faites-vous un café et naviguer sur votre smartphone à votre guise : application, réseaux sociaux, sites internet…

Je vous conseille de naviguer également sur une site qui n’est pas en https mais en http simple (sans le petit cadenas). Nous verrons dans le troisième volet de cet article le côté pédagogique de cette expérience en http !

Tant que le script n’est pas interrompu par Ctrl+c, tcpdump enregistre les paquets dans le fichier. Attention, en fonction de la navigation, le poids du fichier peut monter trèèèès vite (dites vous juste que les paquets enregistrés représentent l’intégralité de votre navigation, si vous téléchargez un fichier de 10 Mo, il y aura environ 10 Mo de paquets…)

Couper l’exécution du script au bout de quelques minutes, ça suffit pour le moment. Nous avons dorénavant un super fichier .pcap de l’ensemble de la navigation.

A noter qu’il s’agit de l’ensemble des paquets transitant sur le bridge du Raspberry, donc si vous avez connecté un deuxième périphérique dessus, votre fichier ne contiendra pas que vos résultats ! On verra lors de l’analyse qu’il est facile de filtrer ce que l’on souhaite.

Rendre le Raspberry autonome

C’est quand même plus sympa de pouvoir interagir directement avec le Raspberry sans avoir à y brancher un écran et un clavier ou même d’y accéder en SSH via un autre PC.

C’est ici qu’intervient le petit écran LCD et quelques boutons poussoirs. A noter que n’importe quel autre système indicateur peux convenir (une led verte, une led rouge et un bouton par exemple peuvent fair le job : vert quand c’est prêt à enregistrer, rouge quand ça enregistre, et juste un bouton pour lancer/stopper les enregistrements).

Ce que je vous propose c’est au moins 4 boutons.

  • Un bouton pour faire afficher l’adresse ip du Raspberry
  • Un bouton pour lancer l’enregistrement
  • Un bouton pour stopper l’enregistrement
  • Un bouton pour éteindre proprement le Raspberry

L’écran LCD va afficher :

  • Les statuts du Raspberry (en attente, en enregistrement…)
  • Son adresse ip
  • Le poids du fichier en cours d’enregistrement (toujours utile pour pas exploser la carte SD…)

Installation des paquets pour gérer les GPIO

sudo apt-get install i2c-tools
sudo apt-get install python-smbus
pip install RPi.GPIO
# Si vous avez une erreur car pip n'est pas installer, exécutez
sudp apt-get install python3-pip

Vérifier si les modules de communication sont bien actifs

lsmod | grep i2c_
lsmod | grep spi_

Ces deux commandes doivent vous retourner un résultat positif, si ce n’est pas le cas, activer les modules i2c et spi via le menu principal

sudo raspi-config
# Et rebooter le Raspberry
sudo reboot

Le programme principal

Créer un fichier dump.py

nano dump.py

et coller le code ci-dessous (alors oui il fonctionne mais je sais qu’il y a pas mal de coquilles, je l’ai fait en mode YOLO, je le mettrai à jour dès que je peux).

import smbus
import time
import os
import signal
import subprocess
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
from datetime import datetime

# GPIO 
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Button to GPIO23
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Button to GPIO24
GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Button to GPIO25
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Button to GPIO18

# Define some device parameters
I2C_ADDR  = 0x27 # I2C device address
LCD_WIDTH = 16   # Maximum characters per line

# Define some device constants
LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line

LCD_BACKLIGHT  = 0x08  # On
#LCD_BACKLIGHT = 0x00  # Off

ENABLE = 0b00000100 # Enable bit

# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005

#Open I2C interface
#bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
bus = smbus.SMBus(1) # Rev 2 Pi uses 1

def lcd_init():
	# Initialise display
	lcd_byte(0x33,LCD_CMD) # 110011 Initialise
	lcd_byte(0x32,LCD_CMD) # 110010 Initialise
	lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
	lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off 
	lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
	lcd_byte(0x01,LCD_CMD) # 000001 Clear display
	time.sleep(E_DELAY)

def lcd_byte(bits, mode):
	# Send byte to data pins
	# bits = the data
	# mode = 1 for data
	#        0 for command

	bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
	bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT

	# High bits
	bus.write_byte(I2C_ADDR, bits_high)
	lcd_toggle_enable(bits_high)

	# Low bits
	bus.write_byte(I2C_ADDR, bits_low)
	lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
	# Toggle enable
	time.sleep(E_DELAY)
	bus.write_byte(I2C_ADDR, (bits | ENABLE))
	time.sleep(E_PULSE)
	bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
	time.sleep(E_DELAY)

def lcd_string(message,line):
	# Send string to display

	message = message.ljust(LCD_WIDTH," ")

	lcd_byte(line, LCD_CMD)

	for i in range(LCD_WIDTH):
		lcd_byte(ord(message[i]),LCD_CHR)

def print_file():
	w = subprocess.check_output("du -sh tcpdump.pcap", shell=True);
	w = w.split()
	lcd_string("File : " + w[0],LCD_LINE_2)

def main():
	# Main program block
	# Initialise display
	lcd_init()
	# Variables 
	cap = False
	# 'sudo tcpdump -v -i wlan0 -s 0 -p -w tcpdump.pcap'
	lcd_string("Wait for command",LCD_LINE_1)
	while True:
		button_state_stop = GPIO.input(23)
		button_state_run = GPIO.input(24)
		button_state_ip = GPIO.input(25)
		button_state_poweroff = GPIO.input(18)
		if button_state_poweroff == False and cap == False:
			lcd_string("Go to sleep",LCD_LINE_1)
			lcd_string("Bye bye ! ",LCD_LINE_1)
			time.sleep(2)	
			subprocess.check_output("sudo shutdown -h now", shell=True);
			time.sleep(1)
			break
		if button_state_ip == False and cap == False:
			ip = subprocess.check_output("ip -4 addr show br0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'", shell=True);
			lcd_string("IP address : ",LCD_LINE_1)
			lcd_string(str(ip),LCD_LINE_2)
		if button_state_run == False and cap == False:
			now = datetime.now()
			dt_string = now.strftime("%Y%m%d-%H%M%S")
			lcd_string("Run capture now!",LCD_LINE_1)
			pro = subprocess.Popen('sudo tcpdump -i wlan0 -s 0 -p -w ' + dt_string +'_tcpdump.pcap', stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid) 
			cap = True
			time.sleep(2)
		if button_state_stop == False and cap == True:    
			lcd_string("Stop capture",LCD_LINE_1)
			os.killpg(os.getpgid(pro.pid), signal.SIGTERM) if cap == True else lcd_string("Erreur",LCD_LINE_1)# Send the signal to all the process groups
			cap = False  
			time.sleep(1)	
			subprocess.check_output("mv " + dt_string  + "_tcpdump.pcap /var/www/html/", shell=True); 
		else: 
			if cap == True:
				w = subprocess.check_output("du -sh " + dt_string  + "_tcpdump.pcap", shell=True);
				w = w.split()
				lcd_string("File : " + w[0],LCD_LINE_2)
        time.sleep(0.5)	 
	exit()
	
if __name__ == '__main__':

	try:
		main()
	except KeyboardInterrupt:
		pass
	finally:
		lcd_byte(0x01, LCD_CMD)

Le câblage

A faire…

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *