Aller au contenu

Nouveau membre ?! Pense à te présenter pour accéder au contenu du forum !

New member ?! Introduce yourself to get access to the forum !

Takuma

 tutoriel / partage Approche de sockets et subprocess : créons un "mini virus"

Messages recommandés

Salut !

 PS : Désolé l'éditeur Mybb a pété toute ma mise en page...

 

Dans le but de vous apprendre un peu plus Python, je vous propose aujourd'hui de coder un "mini virus".

Bon, on va dépasser le stade du "han ça spam message". Mais je compte pas vous apprendre à faire des virus trop poussés qui ne seront plus détectés par les anti viris. Bien qu'en parlant par expérience, c'est pas bien compliqué en Python.

 

Le but de notre projet

 

Notre objectif est assez simple, nous allons créer deux fichiers :

 

  • Un fichier serveur, qui va envoyer les commandes, et attendre une connexion
  • Un fichier client, lui va se connecter au serveur une fois lancer, et va envoyer les informations voulues.

Objectif :

 

  • Commencer l'apprentissage de socket, un module plus qu'obligatoire sur Python car il permet toutes les connexions.
  • Commencer à comprendre le traitement des données.
  • Voir de loin le traitement des messages convertis en bits.
  • Approfondir le module os.
  • Comprendre et utiliser le module subprocess.

 

 

 

 

Création de notre fichier server.py

 

Bien, les bases étant posées, on peut commencer. Créez un fichier nommée server.py (pour pouvoir suivre tout le reste de mon tutoriel sans rien changé).

Résumons le but principale de celui ci :

 

  • Démarrer,
  • Attendre une connexion,
  • Traiter les données.

 

Bien, pour ce fichier, nous n'avons pas de fonction d'initialisation à faire, c'est inutile. Pour l'instant nous allons juste importer le module socket.

184737Capture.PNG

Pour l'instant, rien de bien compliqué.

 

 

Bien, maintenant nous allons nous occuper de la connexion. Pour créer une connexion en Python, nous devons dire à python "d'écouter un port" en réalité, il attend une connexion sur ce port.

On créer deux variables :

 

  • hote = Qui va être vide, car elle se trouve sur le serveur, c'est un peu bête de la créer, je le sais, mais c'est obligatoire.
  • port = Il va contenir le port qui va recevoir la connexion. Pour ce tutoriel nous utiliserons le port "25567".

 

Nous allons maintenant créer une nouvelle connexion.

 

Avant de faire ça, je dois vous expliquer quelle connexion on utilise et comment elle marche.

 

Les connexions TPL 

 

TPL signifie Transmission Control Protocal. Il permet en gros de faire la connexion entre deux machines. 

Certain aime cette connexion car, si les données sont perdus entre les deux, elle va demander aux deux machines de se reconnecter, ou si la connexion est rompue. Bon serte, c'est évident, mais le protocole UDB (User Datagram Protocol), envoie quant à lui des informations sans se soucier du fait qu'elles arrivent à bon port ou non. Enfin bref, c'est le protocole TCP qui nous intéresse.

 

Vous savez le peu nécessaire, maintenant, voyons l'architecture.

 

Architecture serveur 

 

  • Démarrer,
  • Attendre une connexion de la part du client
  • Traiter des données du client, effectuer des échanges
  • Fermer la connexion

 

Architecture client

 

  • Démarrer
  • Se connecter au serveur
  • Envoyer les données nécessaires
  • Fermer la connexion.

 

Comment établir une connexion

Comme vous l'avez vu en haut, vous avez besoin de deux informations :

 

  • Un nom d'hôte. On l'avait nommé "hote" en haut car je fais mes variables en français. Vous verrez souvent "host" comme c'est le nom en anglais. ça peut être un nom de domaine, une IP, etc...
  • Un port. Désigné par un numéro, par exemple le défaut pour les serveurs web est 80, pour minecraft 25565 etc.... 

 

On reprend ! 

 

Cette petite aparté étant faite, nous pouvons reprendre notre server.py.

On va créer nos deux variables que nous avions vu en haut.

Ajoutons ensuite notre "main_co" qui va contenir une connexion :

 

main_co = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 

 

Cela donne :

184510Capture.PNG

Bien, il est tant de vous donner quelques explications :

Notre connexion TCP prends deux paramètres :

 

  • socket.AF_INET : la famille d'adresses, ici ce sont des adresses internet,
  • socket.SOCK_STREAM : On configure socket sur SOCK_STREAM, pour effectuer une connexion TCP.

 

Connecter le socket

On va utiliser la méthode bind. Elle prends un paramètre, un tuple. Ce tuple contient lui : (hote, port).

 

 

En réalité, on ne connecte pas réellement notre serveur, mais on le configure pour qu'il écoute sur un port. C'est pour ça que le nom d'hôte est vide !

 

Nous tapons donc :

 

main_co.bind((hote, port))

 

Noter que la double parenthèses n'est pas une erreur, pour prendre en paramètre un tuple, on fait bien comme ceci.

On aurait pu directement remplir le tupe sans passer par des variables, mais je préfère faire ainsi, c'est plus facile si vous avez des changements à faire.

 

Maintenant, socket oblige un autre paramètre : Le nombre de connexion maximum simultanée à traiter. Nous allons rester sur un classique, et mettre 5. 

En réalité, vous pourrez avoir largement plus de 5 connexions, car c'est le traitement, qui contient l'analyse de la demande, et l'acceptation. Donc 5 clients peuvent se connecter exactement en même temps, mais pas 6. Vu la puissance de Python, et sa vitesse de traitement, à mois d'avoir des centaines de connectés simultanés, vous n'aurez pas de problème.

Pour cela on utilise listen(), qui prends en paramètre un intègre. Tapons :

 

main_co.listen(5)

 

 

Résumons... Nous avons :

185354Capture.PNG

Bien, continuons.

 

 

Accepter la connexion du client

Il reste une dernière étape avant d'avoir un serveur fonctionnel, c'est d'accepter la connexion venant d'un client.

Nous allons pour ça utiliser la methode accept. Cette méthode va bloquer le programme jusqu'à ce qu'une connexion se présente et soit accepter. Cette fonction renvoie deux informations :

 

  • Le socket connecté qui vient de créer, celui qui permet d'identifier et d'envoyer des données au client qui vient de se connecter.
  • Un tuple qui contient l'ip du client, et son port de connexion (port de sortie).

 

On va donc attribuer les deux paramètres à deux variables :

 

client_co , info = main_co.accept()

 

 

181435Capture.PNG

 

Configuration du client

 

Bien, créons notre client.py, et nous allons reprendre notre configuration serveur avec quelques modification.

 

import sockethote = "localhost"port = 25567

 

Les mêmes variables, sauf qu'ici, comme je veux me connecter à mon serveur, je met l'IP. Ici localhost car je fais la connexion de chez moi à la même localisation.

On va ensuite ajouter une variable "server_co(nnection) qui va contenir la connexion en TCP comme pour le serveur, je vais un peu plus vite, car c'est du déjà vu !

 

server_co = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 

 

On va par contre ici, lancer la connexion avec la méthode connect, qui prends en paramètre un tuple qui contient l'hote, et le port :

 

server_co.connect((hote, port))

 

Cette méthode va bloquer le client jusqu'à ce que la connexion soit détectée. Ajoutons par exemple un petit message après pour dire qu'il est connecté :

 

print("[*] Connected")

 

[*]

 

181837Capture.PNG

 

 

La première connexion

 

Bien, nous allons lancer nos deux scripts afin de voir si on ne s'est pas trompé...

 

Si vous ne vous souvenez plus de comment lancer les fichiers :

 

 

 

 

 

  • Ouvrez votre cmd
  • Tapez cd + la destination de vos fichiers
  • Tapez la localisation de votre python.exe un espace puis le fichier python à lancer.

[*]

 

 

Ici, nous lançons le serveur avant le serveur :

181631Capture.PNG

Rien ne ce passe, c'est normal, il attendant la connexion du client !  Lançons le sans plus attendre ! 

 

On reçoit dans le cmd client :

 

 

 

 

[ * ] Connected

 

[*]

 

 

 

Et le serveur c'est coupé... Parfait la connexion a été établie ! Félicitations ! 

 

 

Bien, maintenant nous allons créer un système de commande. Une fois le client connecté, le serveur pourra envoyer des messages, et/ou des commandes !

 

Pour cela, nous devons ajouter quelques trucs...

 

Les messages : Côté serveur 

On créer une variable msg, celle-ci codé en bit. Pour cela, tapons :

 

 

msg = b''

 

[*]

 

 

 

Pour vérifier en permanence la présence de message, nous allons faire ensuite une boucle infinie, jusqu'à ce que le serveur envoie stop. :

 

 

while msg != b'stop':

 

[*]

 

 

Nous allons ensuite demander à la console de taper un message, pour cela on utilise input :

 

 

msg = input('Serveur=>Client>')

 

[*]

 

 

Maintenant, on encode le message.

 

 

 

msg = msg.encode()

 

[*]

 

 

 

Et voilà ! Il ne nous reste plus qu'à envoyer le message :

 

 

client_co.send(msg)

 

[*]

 

 

Et je vais préparer l'affichage d'une réponse, car je compte envoyer des messages de validation du client au serveur, on définie une variable, recv (received) :

 

 

recv = client_co.recv(1024)

 

[*]

 

Il nous faut ensuite decoder le message, car il est encore encoder :

 

 

recv = recv.decode()

 

[*]

 

Et nous finissons par l'afficher :

 

 

print(recv)

 

[*]

 

181423Capture.PNG

 

Les messages : Côté client

 

Bien, juste après notre connecte, nous allons redéfinir encore notre variable msg, de la même façon que du côté serveur :

 

 

msg = b''

 

[*]

 

 

On remet encore notre variable while...

 

 

while msg != b'stop':

 

[*]

 

Nous allons ensuite créer deux fonctions :

 

 

  • cmdrecv :  CommandReceived qui va traiter la commande reçue.
  • senconfirmation : Qui va elle envoyer les confirmations à chaque commande.*

[*]

On peut déjà ajouter dans notre while :

 

 

cmdrecv()sendconfirmation()

 

[*]

 

On se met ensuite juste en dessous du import socket, et on crée nos fonctions.

On va d'abord créer la fonction cmdrecv, qui va se charger de recevoir la commande et de la décoder de la même façon que le fait le client pour le message :

 

 

def cmdrecv():   cmd = server_co.recv(1024)   cmd = cmd.decode()   print(cmd)

 

[*]

 

Notez, qu'on affiche la commande à la fin pour avoir un certain "rendu de test".

 

On crée ensuite l'autre fonction, elle utilisera la méthode send pour envoyer une commande.

 

 

def sendconfirmation():   server_co.send(b"C'est fait chef !")

 

[*]

 

Cela donne :

183100Capture.PNG

 

 

Résumons :

 

 

  • La connexion s'effectue
  • Vous avez bien accès au cmd de la personne
  • Hum...

[*]

 

Il ne vous reste plus qu'à pouvoir taper des commandes, et en avoir le retour !

 

 

Nos début avec subprocess

 

Bien, subprocess ici, nous allons l'utiliser pour envoyer par exemple un 'ipconfig' et recevoir le résultat. Je ne donnerais pas d'autre exemple, et je vais clôturer ce tutoriel sur ça, car je ne veux pas non plus insister la haine ou je ne sais quoi en vous montrant comment littéralement détruire un ordinateur >_<

 

Sachant que ce système peut aussi être utiliser d'une de vos machines à un autre en tant qu'administrateur réseau.

 

 

IpConfig, allons du côté du client

 

Tout d'abord, ajoutons en haut du fichier :

 

import subprocess

 

[*]

 

Bien, pour cela, on va vérifier que la commande envoyé est "ipconfig". Dans notre fonction cmdrecv, nous allons mettre une simple condition vérifiant si la commande envoyer est   b"ipconfig\r".

Tapons :

 

if cmd == b"ipconfig":

 

[*]

 

Notons que "\r" est obligatoire pour le return.

On crée ensuite une variable avec ce subprocess :

 

c = subprocess.Popen('ipconfig', stdout=subprocess.PIPE, shell=True)

 

 

 

[*]

Cette méthode va envoyer la commande et récupérer le retour, je m'attarde pas dessus, si vous voulez des cours avancés sur le réseaux, je vous laisse me le dire ;)

 

On crée deux variables, out (le retour), et error (en cas d'erreur)

On tape ensuite :

 

 

out, error = c.communicate()

 

 

 

[*]

Puis enfin :

 

 

server_co.send(out)

 

 

 

[*]

Cela donne :

185839Capture.PNG

 

Un petit changement côté serveur 

 

Changez cette ligne :

 

 

recv = recv.decode()

 

 

 

[*]

En :

 

 

recv = recv.decode(encoding="utf-8", errors="ignore")

 

 

 

[*]

Cela donne côté serveur :

185959Capture.PNG

 

 

Vous pouvez tester, ça marche.

 

Vous pouvez mettre ipconfig all pour avoir l'ip mac etc...

 

 

Bon, je vais m'arrêter là, vous avez compris le principe.

 

Je n'incite pas les gens à faire des virus de type rats etc, je voulais juste vous montrer que faire des virus c'est à la porter de toute le monde donc mefiez vous. Et si en plus j'peux vous apprendre un peu de Python voilà qui est bien !

 

 

Cordialement.

Partager ce message


Lien à poster
Partager sur d’autres sites

×

Information importante

By using this site, you agree to our Conditions d’utilisation.