Angr
Αυτό το cheatsheet βασίζεται σε μέρος στην τεκμηρίωση του angr.
Εγκατάσταση
Βασικές Ενέργειες
Εισαγωγή
Το angr είναι ένα εργαλείο ανάλυσης δυναμικής εκτέλεσης που χρησιμοποιείται για την ανάλυση και την αυτοματοποίηση της αντίστροφης μηχανικής λογισμικού. Παρέχει μια πληθώρα βασικών ενεργειών που μπορούν να χρησιμοποιηθούν για την εξερεύνηση και την ανάλυση εκτελέσιμων αρχείων.
Βασικές Ενέργειες
Παρακάτω παρουσιάζονται οι βασικές ενέργειες που μπορούν να εκτελεστούν με το angr:
load_binary(): Φορτώνει ένα εκτελέσιμο αρχείο για ανάλυση.
project.factory.entry_state(): Δημιουργεί ένα αρχικό κατάσταση εκτέλεσης για το εκτελέσιμο αρχείο.
project.factory.simgr(): Δημιουργεί έναν αρχικό διαχειριστή καταστάσεων για το εκτελέσιμο αρχείο.
simgr.explore(): Εξερευνά τον χώρο καταστάσεων του εκτελέσιμου αρχείου.
simgr.active: Επιστρέφει τις ενεργές καταστάσεις από τον διαχειριστή καταστάσεων.
state.solver.eval(): Υπολογίζει την τιμή μιας μεταβλητής σε μια κατάσταση εκτέλεσης.
state.solver.constraints: Επιστρέφει τους περιορισμούς που ισχύουν για μια κατάσταση εκτέλεσης.
state.solver.add(): Προσθέτει έναν περιορισμό σε μια κατάσταση εκτέλεσης.
state.solver.satisfiable(): Ελέγχει αν οι περιορισμοί μιας κατάστασης εκτέλεσης είναι ικανοποιήσιμοι.
state.solver.eval_upto(): Υπολογίζει τις πρώτες n τιμές μιας μεταβλητής σε μια κατάσταση εκτέλεσης.
state.solver.BVS(): Δημιουργεί μια μεταβλητή με μη γνωστή τιμή (Symbolic Variable).
state.solver.Solver(): Δημιουργεί έναν αντικείμενο Solver για την επίλυση περιορισμών.
state.solver.add(): Προσθέτει έναν περιορισμό στον Solver.
state.solver.check(): Ελέγχει αν οι περιορισμοί του Solver είναι ικανοποιήσιμοι.
state.solver.model(): Επιστρέφει μια μοντελοποίηση που ικανοποιεί τους περιορισμούς του Solver.
state.solver.eval(): Υπολογίζει την τιμή μιας μεταβλητής στο πλαίσιο της μοντελοποίησης.
The loaded data refers to the information that is stored in the memory when a program is executed. This data includes variables, constants, and other resources that are necessary for the program to run properly.
Main Object
The main object is the central component of a program. It is responsible for controlling the flow of execution and coordinating the actions of other objects. In many programming languages, the main object is the entry point of the program, meaning that it is the first object to be created and executed.
Information about the Loaded Data and Main Object
When analyzing a program, it is important to gather information about the loaded data and the main object. This information can provide valuable insights into how the program works and can help in identifying vulnerabilities or potential areas of exploitation.
To gather information about the loaded data, you can use various techniques such as static analysis, dynamic analysis, or debugging. These techniques can help you identify the types of data that are loaded into memory, their locations, and their values.
Similarly, to gather information about the main object, you can use techniques such as reverse engineering or code analysis. These techniques can help you understand the structure and behavior of the main object, including its methods, properties, and interactions with other objects.
By gathering information about the loaded data and the main object, you can gain a deeper understanding of the program and its inner workings. This knowledge can be invaluable when it comes to hacking or reverse engineering the program, as it can help you identify potential vulnerabilities or weaknesses that can be exploited.
Κύριος Στόχος
The main objective of this document is to provide an introduction to the angr framework and its basic usage. It aims to help beginners understand the fundamentals of angr and how to use it for binary analysis and reverse engineering tasks. By the end of this document, readers should have a clear understanding of angr's capabilities and be able to apply it to solve simple challenges.
Σύμβολα και Επανατοποθετήσεις
Symbols and relocations are important concepts in reverse engineering and binary analysis. They play a crucial role in understanding the structure and behavior of a binary executable.
Symbols
Symbols are identifiers used to represent various elements in a binary executable, such as functions, variables, and data structures. They provide a way to refer to these elements within the binary and are essential for analyzing and modifying the binary.
Symbols can be classified into two types: global symbols and local symbols. Global symbols are accessible from other parts of the binary, while local symbols are only accessible within a specific scope, such as a function or a module.
In reverse engineering, symbols are often used to identify and analyze specific functions or variables within a binary. They can be used to understand the flow of execution, identify vulnerabilities, and modify the behavior of the binary.
Relocations
Relocations are instructions or records in a binary executable that specify how to modify the binary's code or data during the linking process. They are used to resolve references to symbols that are not yet known at compile time.
When a binary is compiled, references to symbols are typically represented as placeholders or offsets. During the linking process, relocations are applied to these placeholders to calculate the actual addresses of the symbols.
Relocations are important in reverse engineering because they provide information about the binary's structure and help in understanding how the binary is linked and loaded into memory. By analyzing relocations, reverse engineers can identify and modify the behavior of a binary.
Conclusion
Symbols and relocations are fundamental concepts in reverse engineering and binary analysis. They provide valuable information about the structure and behavior of a binary executable, enabling reverse engineers to understand, analyze, and modify the binary.
Μπλοκ
Τα μπλοκ είναι ένα σημαντικό χαρακτηριστικό του angr που χρησιμοποιείται για την αναπαράσταση των διαφόρων τμημάτων του προγράμματος που αναλύουμε. Ένα μπλοκ αντιπροσωπεύει μια συνεχή ακολουθία εντολών στον κώδικα. Κάθε μπλοκ έχει έναν μοναδικό αριθμό αναγνώρισης (address) που το αναγνωρίζει μοναδικά. Οι μπλοκ μπορούν να περιέχουν εντολές υποκατάστασης (call instructions) που αναφέρονται σε άλλα μπλοκ, δημιουργώντας έτσι ένα γραφοκατάσταση (control flow graph) του προγράμματος.
Οι μπλοκ μπορούν να ανακτηθούν από ένα αντικείμενο angr.Project
χρησιμοποιώντας τη μέθοδο project.factory.block()
. Μπορούμε να προσπελάσουμε τις εντολές ενός μπλοκ χρησιμοποιώντας την ιδιότητα block.instructions
. Επίσης, μπορούμε να πάρουμε τη διεύθυνση (address) ενός μπλοκ χρησιμοποιώντας την ιδιότητα block.addr
.
Για να εξερευνήσουμε τον γράφο κατάστασης (state graph) του προγράμματος, μπορούμε να προσπελάσουμε τους γείτονες ενός μπλοκ χρησιμοποιώντας τη μέθοδο block.successors()
. Αυτή η μέθοδος επιστρέφει μια λίστα από αντικείμενα angr.Block
που αντιπροσωπεύουν τους γείτονες του μπλοκ. Μπορούμε επίσης να πάρουμε την κατάσταση (state) που προκύπτει από την εκτέλεση ενός μπλοκ χρησιμοποιώντας τη μέθοδο block.final_state()
.
Δυναμική Ανάλυση
Διαχειριστής Προσομοίωσης, Καταστάσεις
Ο διαχειριστής προσομοίωσης (Simulation Manager) είναι ένα εργαλείο που χρησιμοποιείται στο πλαίσιο του angr για τη διεξαγωγή δυναμικής ανάλυσης. Ο διαχειριστής προσομοίωσης είναι υπεύθυνος για τη διαχείριση των καταστάσεων (states) κατά την εκτέλεση του προγράμματος.
Οι καταστάσεις (states) αναπαριστούν την κατάσταση του προγράμματος κατά την εκτέλεση. Κάθε κατάσταση περιέχει πληροφορίες όπως την τρέχουσα εντολή, την κατάσταση των μνημών και των μεταβλητών, καθώς και την κατάσταση των μηχανισμών ελέγχου (control flow) του προγράμματος.
Ο διαχειριστής προσομοίωσης επιτρέπει τη δημιουργία και την επεξεργασία καταστάσεων, καθώς και την παρακολούθηση της εκτέλεσης του προγράμματος. Μπορεί επίσης να χρησιμοποιηθεί για την εξαγωγή πληροφοριών από τις καταστάσεις, όπως τις τιμές των μεταβλητών και τις εντολές που εκτελούνται.
Ο διαχειριστής προσομοίωσης είναι ένα ισχυρό εργαλείο που μπορεί να χρησιμοποιηθεί για την ανάλυση και την εξαγωγή πληροφοριών από εκτελέσιμα αρχεία.
Κλήση συναρτήσεων
Μπορείτε να περάσετε μια λίστα ορισμάτων μέσω του
args
και ένα λεξικό με μεταβλητές περιβάλλοντος μέσω τουenv
στους κατασκευαστέςentry_state
καιfull_init_state
. Οι τιμές σε αυτές τις δομές μπορούν να είναι συμβολοσειρές ή bitvectors και θα αποθηκευτούν στην κατάσταση ως ορίσματα και περιβάλλον για την προσομοιωμένη εκτέλεση. Το προεπιλεγμένοargs
είναι μια κενή λίστα, οπότε αν το πρόγραμμα που αναλύετε αναμένει να βρει τουλάχιστον έναargv[0]
, πρέπει πάντα να το παρέχετε!Εάν θέλετε το
argc
να είναι συμβολικό, μπορείτε να περάσετε ένα συμβολικό bitvector ωςargc
στους κατασκευαστέςentry_state
καιfull_init_state
. Προσέχετε, όμως: αν κάνετε αυτό, πρέπει επίσης να προσθέσετε ένα περιορισμό στην παραγόμενη κατάσταση ότι η τιμή του argc σας δεν μπορεί να είναι μεγαλύτερη από τον αριθμό των ορισμάτων που περάσατε στοargs
.Για να χρησιμοποιήσετε την κατάσταση κλήσης, πρέπει να την καλέσετε με
.call_state(addr, arg1, arg2, ...)
, όπουaddr
είναι η διεύθυνση της συνάρτησης που θέλετε να καλέσετε καιargN
είναι το Nth όρισμα για αυτήν τη συνάρτηση, είτε ως ακέραιος αριθμός, συμβολοσειρά ή πίνακας python, ή ως bitvector. Εάν θέλετε να γίνει εκχώρηση μνήμης και να περάσετε πραγματικά έναν δείκτη σε ένα αντικείμενο, πρέπει να το τυλίξετε σε έναν PointerWrapper, δηλαδήangr.PointerWrapper("point to me!")
. Τα αποτελέσματα αυτής της διεπαφής μπορεί να είναι λίγο απρόβλεπτα, αλλά δουλεύουμε πάνω σε αυτό.
BitVectors
Συμβολικοί BitVectors και Περιορισμοί
Οι συμβολικοί BitVectors είναι μια τεχνική που χρησιμοποιείται στην ανάπτυξη αντιστροφής λογισμικού για να αναπαραστήσει και να επεξεργαστεί δεδομένα συμβολικά. Αντί να αντιμετωπίζουμε τα δεδομένα ως συγκεκριμένες τιμές, τα αναπαριστούμε ως μεταβλητές που μπορούν να πάρουν οποιαδήποτε τιμή από ένα συγκεκριμένο εύρος.
Οι περιορισμοί είναι συνθήκες που επιβάλλονται στις μεταβλητές για να περιορίσουν τις δυνατές τιμές που μπορούν να πάρουν. Οι περιορισμοί μπορούν να περιλαμβάνουν συνθήκες ισότητας, ανισότητας, αριθμητικές πράξεις και λογικές πράξεις.
Χρησιμοποιώντας τους συμβολικούς BitVectors και τους περιορισμούς, μπορούμε να δημιουργήσουμε μια αναπαράσταση του προγράμματος που είναι ανεξάρτητη από τις συγκεκριμένες τιμές των δεδομένων. Αυτό μας επιτρέπει να αναλύσουμε το πρόγραμμα και να εξάγουμε πληροφορίες για τη συμπεριφορά του, ακόμα και χωρίς να γνωρίζουμε τις συγκεκριμένες τιμές των δεδομένων.
Οι συμβολικοί BitVectors και οι περιορισμοί είναι ιδιαίτερα χρήσιμοι για την αντιστροφή προγραμμάτων, την εύρεση ευπαθειών και την ανάλυση κρυπτογραφικών αλγορίθμων. Με τη χρήση αυτών των τεχνικών, μπορούμε να αυτοματοποιήσουμε τη διαδικασία της ανάλυσης και να εξοικονομήσουμε χρόνο και πόρους.
Σύνδεση (Hooking)
Η σύνδεση (hooking) είναι μια τεχνική που χρησιμοποιείται στον τομέα του χάκινγκ για να τροποποιηθεί ή να παρακολουθηθεί τη λειτουργία ενός προγράμματος. Με τη χρήση της συγκεκριμένης τεχνικής, ο χάκερ μπορεί να εισχωρήσει στον κώδικα του προγράμματος και να τον τροποποιήσει ή να παρακολουθήσει την εκτέλεση των συναρτήσεων.
Η σύνδεση μπορεί να γίνει σε διάφορα επίπεδα, όπως στο επίπεδο του λειτουργικού συστήματος, του εφαρμογών ή ακόμη και σε επίπεδο υλικού. Οι πιο συνηθισμένες μέθοδοι σύνδεσης περιλαμβάνουν την αντικατάσταση συναρτήσεων (function hooking), την παρακολούθηση κλήσεων συστήματος (system call hooking) και την παρακολούθηση της εκτέλεσης ενός προγράμματος (code hooking).
Η σύνδεση μπορεί να χρησιμοποιηθεί για διάφορους σκοπούς, όπως η παρακολούθηση της δραστηριότητας ενός προγράμματος, η αποκάλυψη ευπαθειών, η αποκρυπτογράφηση κρυπτογραφημένων δεδομένων και η εκτέλεση κακόβουλου κώδικα.
Η σύνδεση είναι μια ισχυρή τεχνική που απαιτεί προηγούμενες γνώσεις και εμπειρία στον τομέα του χάκινγκ. Είναι σημαντικό να χρησιμοποιείται με προσοχή και να τηρούνται όλες οι νομικές προϋποθέσεις και περιορισμοί.
Επιπλέον, μπορείτε να χρησιμοποιήσετε την εντολή proj.hook_symbol(name, hook)
, παρέχοντας το όνομα ενός συμβόλου ως πρώτο όρισμα, για να συνδέσετε τη διεύθυνση όπου βρίσκεται το σύμβολο.
Παραδείγματα
Last updated