Angr
Parte di questa cheatsheet si basa sulla documentazione di angr.
Installazione
Azioni di base
In this section, we will cover some basic actions that can be performed using angr. These actions include loading a binary, creating a project, and exploring the program's control flow.
Loading a Binary
To start analyzing a binary with angr, you need to load it into a project. This can be done using the angr.Project()
function, which takes the path to the binary as an argument. For example:
Creating a Project
Once the binary is loaded, you can create a project object that represents the binary and its execution environment. This project object provides various methods and attributes for analyzing and manipulating the binary. For example:
Exploring Control Flow
One of the main features of angr is its ability to explore the control flow of a program. This can be done using the explorer
object, which represents a state of the program at a specific point in its execution. The explorer object provides methods for navigating the program's control flow, such as step()
, run()
, and run_until()
. For example:
These are just a few examples of the basic actions that can be performed using angr. The library provides many more features and functionalities for advanced binary analysis and reverse engineering.
Dati caricati
When analyzing a binary with angr, the first step is to load the binary into an angr project. This can be done using the angr.Project()
function, which takes the path to the binary as an argument.
Durante l'analisi di un binario con angr, il primo passo è caricare il binario in un progetto angr. Ciò può essere fatto utilizzando la funzione angr.Project()
, che prende come argomento il percorso del binario.
Once the binary is loaded, we can access various information about the loaded binary using the project.loader
object. This object provides access to information such as the entry point address, the base address, and the sections of the binary.
Una volta caricato il binario, possiamo accedere a varie informazioni sul binario caricato utilizzando l'oggetto project.loader
. Questo oggetto fornisce accesso a informazioni come l'indirizzo del punto di ingresso, l'indirizzo di base e le sezioni del binario.
Main Object
The project.loader.main_object
object represents the main binary being analyzed. It provides access to various information about the binary, such as its entry point address, base address, and sections.
Oggetto principale
L'oggetto project.loader.main_object
rappresenta il binario principale in fase di analisi. Fornisce accesso a varie informazioni sul binario, come l'indirizzo del punto di ingresso, l'indirizzo di base e le sezioni.
Obiettivo principale
The main objective of the angr framework is to provide a powerful and flexible platform for analyzing and reverse engineering binary programs. It aims to automate the process of analyzing binaries by providing a set of tools and methods that can be used to explore and understand their behavior.
Obiettivo principale
L'obiettivo principale del framework angr è fornire una piattaforma potente e flessibile per l'analisi e l'ingegneria inversa di programmi binari. Si propone di automatizzare il processo di analisi dei binari fornendo un insieme di strumenti e metodi che possono essere utilizzati per esplorare e comprendere il loro comportamento.
Simboli e Rilocazioni
When reversing a binary, understanding symbols and relocations is crucial. Symbols are names or labels associated with specific addresses or memory locations in the binary. They can represent functions, variables, or other important elements of the program.
Relocations, on the other hand, are instructions or data that need to be modified or adjusted when the binary is loaded into memory. They are used to ensure that the binary can be executed correctly regardless of its actual memory location.
In the context of reverse engineering, symbols and relocations provide valuable information about the binary's structure and functionality. By analyzing symbols, you can identify important functions or variables that are relevant to your analysis. Relocations, on the other hand, can help you understand how the binary is linked and loaded into memory.
To work with symbols and relocations, you can use various tools and techniques. For example, you can use a disassembler or a debugger to view and analyze symbols in the binary. You can also use a tool like objdump
to extract symbol information from the binary.
Understanding symbols and relocations is an essential skill for reverse engineers. It allows you to navigate and analyze binaries more effectively, enabling you to uncover hidden functionality or vulnerabilities. By mastering the use of tools and techniques for working with symbols and relocations, you can enhance your reverse engineering capabilities and become a more proficient hacker.
Blocchi
Basic Block
A basic block is a sequence of instructions with a single entry point and a single exit point. It is a fundamental unit of analysis in reverse engineering and program analysis. In an executable binary, basic blocks are usually identified by their starting addresses.
Control Flow Graph (CFG)
A control flow graph is a graphical representation of the flow of control within a program. It consists of nodes, which represent basic blocks, and edges, which represent the flow of control between the basic blocks. The CFG provides a high-level view of the program's control flow and can be used to analyze the program's behavior.
Function
A function is a self-contained block of code that performs a specific task. In reverse engineering, functions are often the focus of analysis, as they encapsulate the logic and behavior of a program. Functions can be identified by their entry points and can be analyzed to understand how they work.
Procedure
A procedure is a sequence of instructions that performs a specific task within a function. Procedures are often used to implement higher-level functionality within a program. In reverse engineering, procedures can be analyzed to understand the inner workings of a function.
Basic Block Graph (BBG)
A basic block graph is a graphical representation of the control flow within a function. It consists of nodes, which represent basic blocks, and edges, which represent the flow of control between the basic blocks. The BBG provides a detailed view of the control flow within a function and can be used to analyze the function's behavior.
Blocco di base
Un blocco di base è una sequenza di istruzioni con un unico punto di ingresso e un unico punto di uscita. È un'unità fondamentale di analisi nell'ingegneria inversa e nell'analisi dei programmi. In un binario eseguibile, i blocchi di base sono di solito identificati dai loro indirizzi di inizio.
Grafo di flusso di controllo (CFG)
Un grafo di flusso di controllo è una rappresentazione grafica del flusso di controllo all'interno di un programma. È composto da nodi, che rappresentano i blocchi di base, e da archi, che rappresentano il flusso di controllo tra i blocchi di base. Il CFG fornisce una visione ad alto livello del flusso di controllo del programma e può essere utilizzato per analizzare il comportamento del programma.
Funzione
Una funzione è un blocco di codice autonomo che svolge un compito specifico. Nell'ingegneria inversa, le funzioni sono spesso il focus dell'analisi, in quanto racchiudono la logica e il comportamento di un programma. Le funzioni possono essere identificate dai loro punti di ingresso e possono essere analizzate per capire come funzionano.
Procedura
Una procedura è una sequenza di istruzioni che svolge un compito specifico all'interno di una funzione. Le procedure sono spesso utilizzate per implementare funzionalità di livello superiore all'interno di un programma. Nell'ingegneria inversa, le procedure possono essere analizzate per comprendere il funzionamento interno di una funzione.
Grafo dei blocchi di base (BBG)
Un grafo dei blocchi di base è una rappresentazione grafica del flusso di controllo all'interno di una funzione. È composto da nodi, che rappresentano i blocchi di base, e da archi, che rappresentano il flusso di controllo tra i blocchi di base. Il BBG fornisce una visione dettagliata del flusso di controllo all'interno di una funzione e può essere utilizzato per analizzare il comportamento della funzione.
Analisi dinamica
Gestore di simulazione, Stati
Il gestore di simulazione è il componente principale di angr che si occupa di eseguire la simulazione di un programma. Gestisce gli stati, che rappresentano i diversi punti di esecuzione del programma durante la simulazione.
Gli stati sono oggetti che contengono tutte le informazioni necessarie per rappresentare lo stato di un programma in un determinato punto di esecuzione. Queste informazioni includono il valore dei registri, la memoria, il puntatore di istruzioni e altre informazioni di contesto.
Il gestore di simulazione utilizza una struttura dati chiamata Simulation Manager per gestire gli stati durante la simulazione. Il Simulation Manager tiene traccia degli stati attivi, cioè gli stati che sono ancora in esecuzione, e degli stati completati, cioè gli stati che hanno terminato l'esecuzione.
Durante la simulazione, il gestore di simulazione può creare nuovi stati a partire da uno stato esistente, ad esempio quando viene eseguita un'istruzione di salto condizionale. Inoltre, il gestore di simulazione può prendere decisioni sul percorso di esecuzione da seguire, ad esempio quando si incontra un'istruzione di salto condizionale.
Il Simulation Manager utilizza una strategia di ricerca per determinare il percorso di esecuzione da seguire durante la simulazione. Ci sono diverse strategie di ricerca disponibili, come la ricerca in ampiezza (BFS) e la ricerca in profondità (DFS). Queste strategie possono essere utilizzate per esplorare diversi percorsi di esecuzione e trovare vulnerabilità o comportamenti indesiderati nel programma.
Inoltre, il Simulation Manager può essere configurato per eseguire diverse tecniche di analisi dinamica, come l'iniezione di input o la traccia delle chiamate di sistema. Queste tecniche possono essere utilizzate per analizzare il comportamento del programma durante la simulazione e identificare eventuali vulnerabilità o comportamenti anomali.
In conclusione, il gestore di simulazione e gli stati sono componenti fondamentali di angr che consentono di eseguire l'analisi dinamica di un programma. Utilizzando il Simulation Manager e le diverse tecniche di analisi dinamica disponibili, è possibile identificare vulnerabilità e comportamenti indesiderati nel programma e migliorare la sicurezza complessiva del sistema.
Chiamare funzioni
Puoi passare una lista di argomenti tramite
args
e un dizionario di variabili d'ambiente tramiteenv
inentry_state
efull_init_state
. I valori in queste strutture possono essere stringhe o bitvectors e verranno serializzati nello stato come argomenti e ambiente per l'esecuzione simulata. L'args
predefinito è una lista vuota, quindi se il programma che stai analizzando si aspetta di trovare almeno unargv[0]
, dovresti sempre fornirlo!Se desideri che
argc
sia simbolico, puoi passare un bitvector simbolico comeargc
ai costruttorientry_state
efull_init_state
. Tuttavia, fai attenzione: se lo fai, dovresti anche aggiungere un vincolo allo stato risultante che il valore di argc non può essere maggiore del numero di argomenti che hai passato inargs
.Per utilizzare lo stato di chiamata, devi chiamarlo con
.call_state(addr, arg1, arg2, ...)
, doveaddr
è l'indirizzo della funzione che desideri chiamare eargN
è l'N-esimo argomento di quella funzione, sia come intero, stringa o array python, o come bitvector. Se desideri allocare memoria e passare effettivamente un puntatore a un oggetto, dovresti incapsularlo in un PointerWrapper, ad esempioangr.PointerWrapper("puntami!")
. I risultati di questa API possono essere un po' imprevedibili, ma stiamo lavorando su di esso.
BitVectors
BitVector simbolici e vincoli
Gli Symbolic BitVectors (vettori di bit simbolici) sono una rappresentazione astratta dei dati binari utilizzati nell'analisi simbolica. Questi vettori di bit possono rappresentare sia valori concreti che simbolici.
I vincoli sono condizioni che vengono imposte sui Symbolic BitVectors per limitare i possibili valori che possono assumere. I vincoli possono essere utilizzati per modellare le restrizioni di un programma o di un algoritmo specifico.
L'uso di Symbolic BitVectors e vincoli consente di eseguire operazioni simboliche sui dati, come ad esempio l'aggiunta, la sottrazione o la moltiplicazione, senza dover conoscere i valori concreti dei bit. Questo è particolarmente utile nell'analisi di programmi o algoritmi complessi, in cui i valori concreti potrebbero essere sconosciuti o difficili da determinare.
Gli Symbolic BitVectors e i vincoli sono ampiamente utilizzati nell'analisi simbolica e nella reverse engineering per risolvere problemi complessi e ottenere informazioni utili sui programmi o sui sistemi che si stanno analizzando.
Hooking
Il hooking è una tecnica utilizzata nel reverse engineering per intercettare e modificare il comportamento di un'applicazione. Consiste nell'inserire del codice personalizzato (noto come "hook") all'interno di un'applicazione esistente, al fine di monitorare o alterare il flusso di esecuzione del programma.
Tipi di hooking
Esistono diversi tipi di hooking, tra cui:
API hooking: intercetta le chiamate alle API di sistema e sostituisce la funzionalità originale con una personalizzata.
Function hooking: intercetta le chiamate alle funzioni all'interno di un'applicazione e sostituisce il loro comportamento con uno personalizzato.
Inline hooking: modifica direttamente il codice dell'applicazione per intercettare e modificare il flusso di esecuzione.
Message hooking: intercetta i messaggi inviati tra le finestre di un'applicazione per monitorare o alterare il loro comportamento.
Utilizzo di hooking con Angr
Angr è un framework di analisi binaria che può essere utilizzato per eseguire hooking su un'applicazione. Per utilizzare Angr per il hooking, è necessario seguire i seguenti passaggi:
Caricare il file binario dell'applicazione all'interno di Angr.
Identificare la funzione o l'API che si desidera intercettare.
Creare un hook personalizzato per sostituire il comportamento originale.
Applicare il hook all'applicazione utilizzando le funzioni fornite da Angr.
Eseguire l'applicazione con il hook applicato e monitorare il suo comportamento modificato.
L'utilizzo di hooking con Angr può essere utile per scopi di reverse engineering, come l'analisi del comportamento di un'applicazione o l'individuazione di vulnerabilità. Tuttavia, è importante utilizzare questa tecnica in modo etico e nel rispetto delle leggi locali.
Inoltre, è possibile utilizzare proj.hook_symbol(name, hook)
, fornendo il nome di un simbolo come primo argomento, per agganciare l'indirizzo in cui si trova il simbolo.
Esempi
Last updated