4/1/18

Αποκρυπτογραφώντας τον HC7 με βήματα



CASE STUDY: Αποκρυπτογραφώντας τον  HC7

Background

Πρόσφατα ένας πελάτης μας, έδωσε πρόσβαση μέσω Remote Desktop σε έναν σερβερ ο οποίος όπως αποδείχτηκε ήταν ήδη "προσβεβλημένος" λόγω του συνθηματικού που χρησιμοποιούσε, το οποίο ήταν ασθενές.

Οι επιτιθέμενοι έριξαν μέσα ένα Ransomware το οποίο μέχρι τώρα δεν είχαμε ξαναδεί, και προσπάθησαν να διασπείρουν το εκτελέσιμο αρχείο του Ransomware μέσω PsExec

Το εκτελέσιμο ήταν το hc7.exe το οποίο κατάφερε να κρυπτογραφήσει τεράστιο αριθμό δεδομένων μέσα σε μικρό χρονικό διάστημα, σε πολλαπλά μηχανήματα.

Καταφέραμε και αποκρυπτογραφήσαμε τα δεδομένα :-)

Δείτε αναλυτικά παρακάτω τον τρόπο που λειτουργήσαμε.


Στο σημείο αυτό να πούμε ότι σαφώς και χρειαστήκαμε τη βοήθεια των Michael Gillespie, Fabian Woser και των extreme coders τους οποίους και ευχαριστούμε.
Να πούμε ότι ο Michael ήταν αυτός που είχε εντοπίσει το κλειδί για την προηγούμενη έκδοση, τον hc6. Το κλειδί ήταν hardcoded μέσα στον κώδικα κρυπτογράφησης και με αυτόν τον τρόπο ήμασταν σε θέση να αποκρυπτογραφήσουμε το στέλεχος  αυτό.
Δυστυχώς, το νέο στέλεχος δεν λειτουργεί τόσο απλά, οπότε η εύρεση του κλειδιού με αυτόν τον τρόπο είναι αδύνατη.

Έπρεπε να βρούμε μία άλλη πιο δημιουργική λύση.

Προϋποθέσεις και ενέργειες

Θελήσαμε να εκμεταλλευτούμε τη μνήμη RAM για να προσπαθήσουμε και να βρούμε το κλειδί αποκρυπτογράφησης.
Για να γίνει αυτό, απαραίτητη προϋπόθεση ήταν να
μην έχει κλείσει ο Η/Υ που έχει προσβληθεί, καθώς κάτι τέτοιο θα σημαίνει ότι η μνήμη RAM χάνεται, και τότε είναι οριστικό Game Over.

Δυστυχώς, ο πελάτης, σε μία σπασμωδική κίνηση έκλεισε τα μηχανήματά του μόλις αντιλήφθηκε τι συνέβη.
Ευτυχώς, ένα από τα μηχανήματα του ξέφυγε και το βρήκαμε ανοιχτό.

Έτσι, ξεκινήσαμε άμεσα τις διαδικασίες για να συλλέξουμε το αντίγραφο της μνήμης RAM, ενώ ταυτόχρονα φροντίζαμε για περιορισμούς και ανακτήσεις όπου αυτό ήταν εφικτό.

Για τη συλλογή της RAM χρησιμοποιήσαμε την εφαρμογή Magnet Forensics με το οποίο πήραμε ακριβές στιγμιαίο αντίγραφο του εν λόγω μηχανήματος. Βέβαια, για να γίνει αυτό, είναι απαραίτητο να υπάρχει αρκετός διαθέσιμος χώρος στο δίσκο, ανάλογο της  μνήμης RAM του εν λόγω μηχανήματος.
Στην προκειμένη περίπτωση, ο σταθμός εργασίας είχε 8GB διαθέσιμης RAM και αρκετό ελεύθερο χώρο για την αποθήκευση της RAM. 

Ξεκινήσαμε τη διαδικασία μέσω γραμμών εντολών:






Ψάχνοντας κλειδιά...

Μόλις ήμασταν έτοιμοι με το RAM dump, χρησιμοποιήσαμε το Volatility για να κάνουμε την ανάλυσή μας.

Το Volatility είναι ένα εξαιρετικό εργαλείο που χρησιμοποιείται  για την εξαγωγή χρήσιμων πληροφοριών από τη μνήμη RAM και μάλιστα λειτουργεί άψογα σε μεγάλη ποικιλία λειτουργικών συστημάτων. 

Αρχικά, βρήκαμε την ακριβή έκδοση των Windows του μηχανήματος από το οποίο πήραμε το αντίγραφο της RAM, με τη χρήση της εντολής 'ver'.
Στην περίπτωσή μας, είχαμε να κάνουμε με Windows10 x64 build 15064.

Αυτό είναι σημαντικό, καθώς το Volatility για να λειτουργήσει σωστά, θα πρέπει να ξέρει την ακριβή έκδοση του λειτουργικού συστήματος. 





Για να επιβεβαιώσουμε ότι το Volatility λειτουργεί σωστά, χρησιμοποιήσαμε βασικές εντολές για να σιγουρευτούμε ότι τα δεδομένα μεταφέρονται σωστά από το RAM dump που πήραμε.
Για να το κάνουμε αυτό, απλά τσεκάρουμε ότι μπορούμε να δούμε τη λίστα ενεργειών του μηχανήματος.




Συνήθως, οι ενσωματωμένες λειτουργίες του Volatility όπως το cmdscan ή το consoles θα μας έδινε τις  πληροφορίες που θέλαμε. Στην περίπτωσή μας, τα πράγματα περιπλέχθηκαν λίγο, καθώς δεν παίρναμε την πληροφορία που θέλαμε μέσω καμίας μεθόδου.
Αντ' αυτού, επιλέξαμε να εξαγάγουμε όλα τα strings του RAM dump με σκοπό να τα ψάξουμε στη συνέχεια για περισσότερες πληροφορίες.
Για να το κάνουμε αυτό, χρησιμοποιήσαμε το strings.exe, εργαλείο της SysInternals, με το οποίο γράψαμε τα raw strings σε ένα αρχείο κειμένου :-)

Έτσι, πρώτα χρησιμοποιήσαμε το strings plugin μέσα στο Volatility για να μετατρέψουμε τα δεδομένα σε κάτι πιο χειροπιαστό.
Για να το κάνουμε αυτό, ανεβάσαμε το ram_strings.txt στο Volatility. 


Στο επόμενο βήμα, αναζητήσαμε για το string psexesvc μέσα στο RAM Strings.txt που είχαμε δημιουργήσει.




Μπουμ! Βρήκαμε κάτι το οποίο μοιάζει με password! :-) :-)

Ήμασταν απολύτως σίγουροι ότι το παραπάνω ήταν κάποιο password σχετικό με το θέμα μας, καθώς περιείχε και χαρακτηριστικά σχετικά με το όνομα του πελάτη μας.
Στο σημείο αυτό, ήμασταν πλέον πεπεισμένοι ότι μπορούμε να ανακτήσουμε τα  δεδομένα του πελάτη. 



Decompiling Python...

Συνεχίσαμε προσπαθώντας να κάνουμε decompile το hc7.exe.
Για το σκοπό αυτό, χρησιμοποιήσαμε το pyinstxtractor για να εξάγουμε τα περιεχόμενα του εκτελέσιμου αλλά τα βρήκαμε σκούρα στην εξαγωγή του κυρίως hc9 script. Ζητήσαμε τη βοήθεια του Michael Gillespie ο οποίος είχε με επιτυχία αντιμετωπίσει στο παρελθόν κάτι παρόμοιο και όντως μας έδωσε λύση, η οποία είχε να κάνει με την εισαγωγή του Python 2.7 magic header στο εκτελέσιμο.






Αποκρυπτογράφηση!

Χρησιμοποιήσαμε το σχετικό blog post του 0xec σχετικά με τον hc6 και ήμασταν σε θέση να  επαναλάβουμε τα βήματά τους. 

Χρησιμοποιώντας Hex Editor, εισάγαμε τα σχετικά bytes στο ξεκίνημα του αρχείου και το κάναμε decompile χρησιμοποιώντας pycdc. Ελέγξαμε τον κώδικα και, όπως αναμενόταν, είχε μεγάλες ομοιότητες με το hc6. Έτσι, οι δημιουργοί του hc6/hc7 είχαν κάνει όλη τη δουλειά για μας, αφήνοντας αυτούσια μια ρουτίνα αποκρυπτογράφησης.

Την εκμεταλλευτήκαμε, εισάγαμε το password που βρήκαμε μέσα στη RAM προηγουμένως, και αποκρυπτογραφήσαμε με επιτυχία ένα αρχείο!

from Crypto.Hash import SHA256
from Crypto.Cipher import AES
import os
import random
import sys
import base64

FILE_EXTENSION = '.GOTYA'

def getDigest(password):
   hasher = SHA256.new(password)
   return hasher.digest()

def decrypt(key, FileName):
   OutputFile = os.path.join(os.path.dirname(FileName), os.path.basename(FileName.replace(FILE_EXTENSION, '')))
   chunkS = 65536
   with open(FileName, 'rb') as infile:
       fileS = infile.read(16)
       IniVect = infile.read(16)
       decryptor = AES.new(key, AES.MODE_CBC, IniVect)
       with open(OutputFile, 'wb') as outfile:
           while True:
               chunk = infile.read(chunkS)
               if len(chunk) == 0:
                   break
               outfile.write(decryptor.decrypt(chunk))
           outfile.truncate(int(fileS))


def run_decrypt():
   if len(sys.argv) < 3:
       print('Error')
       sys.exit(0)
   password = sys.argv[1]
   filename = sys.argv[2]
   decrypt(getDigest(password), filename)

if __name__ == "__main__":
   run_decrypt()

Στη συνέχεια επικοινωνήσαμε με τον Michael και μας βοήθησε να αυτοματοποιήσουμε τη διαδικασία όσο το δυνατόν περισσότερο, οπότε τώρα αρκεί πλέον να βρεθεί το password και να μπει στον decrypter :-)

Πλέον, είμαστε σε θέση να αποκρυπτογραφήσουμε τον hc7, με τις προϋποθέσεις που αναφέρονται στο παρόν.



(c) 2017  Michael Young, Ryan Zisk, Dimitris Anderson