Una caratteristica fondamentale per la sopravvivenza del #malware è la sua capacità di nascondersi ai sistemi di detection.
Per fare questo è fondamentale che la propria firma #hash vari in continuazione, altrimenti sarebbe facilmente identificabile.
Nascono così i malware polimorfici, ovvero una tipologia in grado di cambiare continuamente la propria firma hash andando semplicemente a modificare la propria chiave di crittazione. Ad ogni copia la chiave varia, quindi varierà il proprio hash.
Questo è ok per evadere sistemi di identificazione basati semplicemente su hash, ma i sistemi attuali sono più sofisticati e spesso la semplice variazione della chiave non è sufficiente.
E' necessario che il malware modifichi il proprio codice! Nascono così i malware metamorfici, ovvero quelli in grado di modificare il proprio codice sorgente. Come viene fatto?
Innanzitutto il malware contiene un proprio modulo di decompilazione e ricompilazione. Ci sono differenti tecniche una delle quali prevede che una volta decompilatosi (che brutta parola) è in grado di aggiungere dentro il proprio codice istruzioni nuove, che possono variare da semplici NOP a sequenze di istruzioni assembler, che vengono definite Dead Code Injection, ovvero iniezione di codice morto che alla fine non fa nulla, se non modificare il codice sorgente.
Se vi appassiona questo argomento vi consiglio di leggere "Malware Obfuscation Techniques: A Brief Survey" di Ilsun You e Kangbin Yim
Oggi provo a parlarvi delle socket semplificando molto le cose 😉
Le socket sono gli endpoint di un canale di comunicazione bidirezionale. Consentono la comunicazione in rete ma anche tra differenti processi della stessa macchina.
Le socket di rete possono essere di tipo Server o Client. Le socket di tipo server si mettono in ascolto su una specifica porta aspettando che un’altra socket di tipo Client ci si connetta.
In questa pillola vediamo una server socket ed utilizzerò come linguaggio Python
import socket
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv.bind(('127.0.0.1', 8080))
serv.listen(5)
while True:
conn, addr = serv.accept()
while True:
data = conn.recv(4096)
print data
conn.send("Sono il server")
conn.close()
print 'client disconnesso
In questo programma dopo aver definito la porta di ascolto (la 8080) creeremo una socket con la chiamata socket.socket(), e subito dopo utilizzando bind() collegheremo la socket all’host locale ed alla porta definita.
Una volta eseguite queste azioni diciamo alla socket di mettersi in ascolto per ricevere connessioni utilizzando la chiamata listen()
Il numero 5 come argomento della listen indica il numero delle connessioni che potranno mettersi in coda.
Fatto questo si attende dentro il ciclo while che arrivi una connessione.
La chiamata accept consente di accettare una connessione entrante. Dopo questa chiamata il server rimane in ascolto sulla porta. Alla ricezione della connessione viene inizializzata la variabile conn che conterra i valori identificativi della connessione entrante.
Ricevuta una connessione, con la chiamata conn.recv, la variabile data conterrà il valore ricevuto. Qui avrei dovuto fare un controllo su data per capire se è vuota o meno, ma ve lo risparmio.
Ricevuto il valore con la conn.send il server invia la stringa “Sono il server” al client.
Infine si chiude la connessione.
Le socket sono importanti nelle attività di penetration testing, in quanto consentono al pentester di creare connessioni e testare in modo efficiente i server da analizzare. Naturalmente questo si fa con socket di tipo client che vedremo nella prossima pillola.