Reversing Tools & Basic Methods

Impara l'hacking AWS da zero a eroe con htARTE (Esperto Red Team AWS di HackTricks)!

Altri modi per supportare HackTricks:

Try Hard Security Group


Strumenti di Reversing basati su ImGui

Software:

Decompilatore Wasm / Compilatore Wat

Online:

Software:

Decompilatore .NET

dotPeek è un decompilatore che decompila ed esamina vari formati, inclusi librerie (.dll), file di metadati di Windows (.winmd) ed eseguibili (.exe). Una volta decompilato, un assembly può essere salvato come progetto Visual Studio (.csproj).

Il merito qui è che se un codice sorgente perso richiede il ripristino da un assembly legacy, questa azione può risparmiare tempo. Inoltre, dotPeek fornisce una comoda navigazione all'interno del codice decompilato, rendendolo uno degli strumenti perfetti per l'analisi degli algoritmi Xamarin.

Con un modello di add-in completo e un'API che estende lo strumento per adattarlo alle tue esigenze esatte, .NET Reflector risparmia tempo e semplifica lo sviluppo. Diamo un'occhiata alla moltitudine di servizi di reverse engineering che questo strumento fornisce:

  • Fornisce una visione di come i dati scorrono attraverso una libreria o un componente

  • Fornisce una visione dell'implementazione e dell'uso dei linguaggi e dei framework .NET

  • Trova funzionalità non documentate e non esposte per ottenere di più dalle API e dalle tecnologie utilizzate.

  • Trova dipendenze e diverse librerie

  • Rintraccia l'esatta posizione degli errori nel tuo codice, nei componenti di terze parti e nelle librerie.

  • Esegue il debug del codice sorgente di tutto il codice .NET con cui lavori.

Plugin ILSpy per Visual Studio Code: Puoi averlo in qualsiasi OS (puoi installarlo direttamente da VSCode, non è necessario scaricare il git. Fai clic su Estensioni e cerca ILSpy). Se hai bisogno di decompilare, modificare e ricompilare di nuovo puoi usare dnSpy o un fork attivamente mantenuto di esso, dnSpyEx. (Fai clic destro -> Modifica Metodo per cambiare qualcosa all'interno di una funzione).

Registrazione DNSpy

Per fare in modo che DNSpy registri alcune informazioni in un file, potresti usare questo snippet:

using System.IO;
path = "C:\\inetpub\\temp\\MyTest2.txt";
File.AppendAllText(path, "Password: " + password + "\n");

Debugging con DNSpy

Per eseguire il debug del codice utilizzando DNSpy è necessario:

Prima di tutto, modificare gli attributi dell'Assembly relativi al debugging:

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]

A:

Strumenti di Reverse Engineering: Metodi di Base

Il reverse engineering è un'attività fondamentale nel campo della sicurezza informatica. Utilizzando gli strumenti di reverse engineering corretti, è possibile analizzare il funzionamento interno di un software e identificare potenziali vulnerabilità. In questo documento, esploreremo alcuni strumenti di base e metodi utilizzati nel reverse engineering.

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default |
DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]

E clicca su compila:

Quindi salva il nuovo file tramite File >> Salva modulo...:

Questo è necessario perché se non lo fai, a runtime verranno applicate diverse ottimizzazioni al codice e potrebbe essere possibile che durante il debug un punto di interruzione non venga mai raggiunto o alcune variabili non esistano.

Poi, se la tua applicazione .NET viene eseguita da IIS puoi riavviarla con:

iisreset /noforce

Quindi, per iniziare il debug, dovresti chiudere tutti i file aperti e all'interno della scheda Debug selezionare Attacca al processo...:

Successivamente seleziona w3wp.exe per attaccarti al server IIS e clicca su attacca:

Ora che stiamo effettuando il debug del processo, è il momento di fermarlo e caricare tutti i moduli. Prima clicca su Debug >> Interrompi tutto e poi clicca su Debug >> Finestre >> Moduli:

Clicca su qualsiasi modulo su Moduli e seleziona Apri tutti i moduli:

Fai clic con il tasto destro su qualsiasi modulo in Esplora assembly e clicca su Ordina assembly:

Decompilatore Java

https://github.com/skylot/jadx https://github.com/java-decompiler/jd-gui/releases

Debugging DLL

Utilizzando IDA

  • Carica rundll32 (64 bit in C:\Windows\System32\rundll32.exe e 32 bit in C:\Windows\SysWOW64\rundll32.exe)

  • Seleziona il debugger Windbg

  • Seleziona "Sospendi al caricamento/scaricamento della libreria"

  • Configura i parametri dell'esecuzione inserendo il percorso del DLL e la funzione che desideri chiamare:

Quindi, quando inizi il debug, l'esecuzione si fermerà quando ogni DLL viene caricato, quindi, quando rundll32 carica il tuo DLL, l'esecuzione si fermerà.

Ma, come puoi accedere al codice del DLL che è stato caricato? Utilizzando questo metodo, non lo so.

Utilizzando x64dbg/x32dbg

  • Carica rundll32 (64 bit in C:\Windows\System32\rundll32.exe e 32 bit in C:\Windows\SysWOW64\rundll32.exe)

  • Cambia la riga di comando ( File --> Cambia riga di comando ) e imposta il percorso del dll e la funzione che desideri chiamare, ad esempio: "C:\Windows\SysWOW64\rundll32.exe" "Z:\shared\Cybercamp\rev2\\14.ridii_2.dll",DLLMain

  • Cambia Opzioni --> Impostazioni e seleziona "DLL Entry".

  • Quindi avvia l'esecuzione, il debugger si fermerà su ogni dll principale, a un certo punto ti fermerai nell'ingresso DLL del tuo dll. Da lì, cerca i punti in cui desideri inserire un breakpoint.

Nota che quando l'esecuzione viene interrotta per qualsiasi motivo in win64dbg, puoi vedere in quale codice ti trovi guardando nella parte superiore della finestra di win64dbg:

Quindi, guardando questo, puoi vedere quando l'esecuzione è stata interrotta nel dll che desideri eseguire il debug.

App GUI / Videogiochi

Cheat Engine è un programma utile per trovare dove sono salvati i valori importanti nella memoria di un gioco in esecuzione e modificarli. Ulteriori informazioni in:

pageCheat Engine

PiNCE è uno strumento di front-end/ingegneria inversa per il GNU Project Debugger (GDB), focalizzato sui giochi. Tuttavia, può essere utilizzato per qualsiasi attività correlata all'ingegneria inversa.

Decompiler Explorer è un front-end web per diversi decompilatori. Questo servizio web ti consente di confrontare l'output di diversi decompilatori su piccoli eseguibili.

ARM & MIPS

Shellcode

Debugging di uno shellcode con blobrunner

Blobrunner alloca lo shellcode all'interno di uno spazio di memoria, ti indica l'indirizzo di memoria in cui lo shellcode è stato allocato e ferma l'esecuzione. Successivamente, devi collegare un debugger (Ida o x64dbg) al processo e impostare un breakpoint all'indirizzo di memoria indicato e riprendere l'esecuzione. In questo modo sarai in grado di eseguire il debug dello shellcode.

La pagina dei rilasci su GitHub contiene zip contenenti i rilasci compilati: https://github.com/OALabs/BlobRunner/releases/tag/v0.0.5 Puoi trovare una versione leggermente modificata di Blobrunner al seguente link. Per compilarlo, basta creare un progetto C/C++ in Visual Studio Code, copiare e incollare il codice e compilarlo.

pageBlobrunner

Debugging di uno shellcode con jmp2it

jmp2it è molto simile a blobrunner. Alloca lo shellcode all'interno di uno spazio di memoria e avvia un loop eterno. Successivamente devi collegare il debugger al processo, avviare l'esecuzione, attendere 2-5 secondi e premere stop e ti troverai all'interno del loop eterno. Salta alla prossima istruzione del loop eterno poiché sarà una chiamata allo shellcode e infine ti troverai ad eseguire lo shellcode.

Puoi scaricare una versione compilata di jmp2it nella pagina dei rilasci.

Debugging dello shellcode utilizzando Cutter

Cutter è l'interfaccia grafica di radare. Utilizzando Cutter puoi emulare lo shellcode e ispezionarlo dinamicamente.

Nota che Cutter ti consente di "Aprire file" e "Aprire shellcode". Nel mio caso, quando ho aperto lo shellcode come file, lo ha decompilato correttamente, ma quando l'ho aperto come shellcode no:

Per avviare l'emulazione nel punto desiderato, imposta un breakpoint lì e apparentemente Cutter avvierà automaticamente l'emulazione da quel punto:

Puoi vedere lo stack ad esempio all'interno di un dump esadecimale:

Deobfuscation dello shellcode e ottenere le funzioni eseguite

Dovresti provare scdbg. Ti dirà quali funzioni sta utilizzando lo shellcode e se lo shellcode si sta decodificando in memoria.

scdbg.exe -f shellcode # Get info
scdbg.exe -f shellcode -r #show analysis report at end of run
scdbg.exe -f shellcode -i -r #enable interactive hooks (file and network) and show analysis report at end of run
scdbg.exe -f shellcode -d #Dump decoded shellcode
scdbg.exe -f shellcode /findsc #Find offset where starts
scdbg.exe -f shellcode /foff 0x0000004D #Start the executing in that offset

scDbg conta anche con un launcher grafico in cui puoi selezionare le opzioni desiderate ed eseguire lo shellcode

L'opzione Create Dump scaricherà lo shellcode finale se viene apportata qualsiasi modifica dinamicamente nello shellcode in memoria (utile per scaricare lo shellcode decodificato). L'offset di avvio può essere utile per avviare lo shellcode a un offset specifico. L'opzione Debug Shell è utile per eseguire il debug dello shellcode utilizzando il terminale scDbg (tuttavia trovo che una qualsiasi delle opzioni spiegate prima sia migliore per questa questione in quanto sarà possibile utilizzare Ida o x64dbg).

Disassemblaggio utilizzando CyberChef

Carica il tuo file shellcode come input e utilizza la seguente ricetta per decompilarlo: https://gchq.github.io/CyberChef/#recipe=To_Hex('Space',0)Disassemble_x86('32','Full%20x86%20architecture',16,0,true,true)

Questo offuscatore modifica tutte le istruzioni per mov (sì, davvero cool). Utilizza anche interruzioni per cambiare i flussi di esecuzione. Per ulteriori informazioni su come funziona:

Se sei fortunato demovfuscator deofuscherà il binario. Ha diverse dipendenze

apt-get install libcapstone-dev
apt-get install libz3-dev

E installa keystone (apt-get install cmake; mkdir build; cd build; ../make-share.sh; make install)

Se stai partecipando a un CTF, questo workaround per trovare la flag potrebbe essere molto utile: https://dustri.org/b/defeating-the-recons-movfuscator-crackme.html

Rust

Per trovare il punto di ingresso cerca le funzioni con ::main come in:

In questo caso il binario si chiamava authenticator, quindi è abbastanza ovvio che questa sia la funzione main interessante. Avendo il nome delle funzioni chiamate, cerca su Internet per apprendere i loro input e output.

Delphi

Per i binari compilati in Delphi puoi utilizzare https://github.com/crypto2011/IDR

Se devi invertire un binario Delphi ti consiglio di utilizzare il plugin di IDA https://github.com/Coldzer0/IDA-For-Delphi

Basta premere ATL+f7 (importa il plugin python in IDA) e seleziona il plugin python.

Questo plugin eseguirà il binario e risolverà dinamicamente i nomi delle funzioni all'inizio del debug. Dopo aver avviato il debug premi nuovamente il pulsante Start (quello verde o f9) e verrà colpito un breakpoint all'inizio del codice reale.

È anche molto interessante perché se premi un pulsante nell'applicazione grafica il debugger si fermerà nella funzione eseguita da quel pulsante.

Golang

Se devi invertire un binario Golang ti consiglio di utilizzare il plugin di IDA https://github.com/sibears/IDAGolangHelper

Basta premere ATL+f7 (importa il plugin python in IDA) e seleziona il plugin python.

Questo risolverà i nomi delle funzioni.

Python compilato

In questa pagina puoi trovare come ottenere il codice python da un binario compilato ELF/EXE python:

pageDecompile compiled python binaries (exe, elf) - Retreive from .pyc

GBA - Game Body Advance

Se ottieni il binario di un gioco GBA puoi utilizzare diversi strumenti per emularlo e debuggarlo:

In no$gba, in Opzioni --> Configurazione Emulazione --> Controlli** ** puoi vedere come premere i pulsanti del Game Boy Advance

Quando premuto, ogni tasto ha un valore per identificarlo:

A = 1
B = 2
SELECT = 4
START = 8
RIGHT = 16
LEFT = 32
UP = 64
DOWN = 128
R = 256
L = 256

Quindi, in questo tipo di programma, la parte interessante sarà come il programma tratta l'input dell'utente. All'indirizzo 0x4000130 troverai la funzione comunemente trovata: KEYINPUT.

Nell'immagine precedente puoi vedere che la funzione viene chiamata da FUN_080015a8 (indirizzi: 0x080015fa e 0x080017ac).

In quella funzione, dopo alcune operazioni di inizializzazione (senza alcuna importanza):

void FUN_080015a8(void)

{
ushort uVar1;
undefined4 uVar2;
undefined4 uVar3;
ushort uVar4;
int iVar5;
ushort *puVar6;
undefined *local_2c;

DISPCNT = 0x1140;
FUN_08000a74();
FUN_08000ce4(1);
DISPCNT = 0x404;
FUN_08000dd0(&DAT_02009584,0x6000000,&DAT_030000dc);
FUN_08000354(&DAT_030000dc,0x3c);
uVar4 = DAT_030004d8;

È stato trovato questo codice:

do {
DAT_030004da = uVar4; //This is the last key pressed
DAT_030004d8 = KEYINPUT | 0xfc00;
puVar6 = &DAT_0200b03c;
uVar4 = DAT_030004d8;
do {
uVar2 = DAT_030004dc;
uVar1 = *puVar6;
if ((uVar1 & DAT_030004da & ~uVar4) != 0) {

L'ultimo if controlla se uVar4 è tra le ultime chiavi e non è la chiave corrente, chiamata anche rilascio di un pulsante (la chiave corrente è memorizzata in uVar1).

if (uVar1 == 4) {
DAT_030000d4 = 0;
uVar3 = FUN_08001c24(DAT_030004dc);
FUN_08001868(uVar2,0,uVar3);
DAT_05000000 = 0x1483;
FUN_08001844(&DAT_0200ba18);
FUN_08001844(&DAT_0200ba20,&DAT_0200ba40);
DAT_030000d8 = 0;
uVar4 = DAT_030004d8;
}
else {
if (uVar1 == 8) {
if (DAT_030000d8 == 0xf3) {
DISPCNT = 0x404;
FUN_08000dd0(&DAT_02008aac,0x6000000,&DAT_030000dc);
FUN_08000354(&DAT_030000dc,0x3c);
uVar4 = DAT_030004d8;
}
}
else {
if (DAT_030000d4 < 8) {
DAT_030000d4 = DAT_030000d4 + 1;
FUN_08000864();
if (uVar1 == 0x10) {
DAT_030000d8 = DAT_030000d8 + 0x3a;

Nel codice precedente puoi vedere che stiamo confrontando uVar1 (il luogo dove si trova il valore del pulsante premuto) con alcuni valori:

  • Prima, viene confrontato con il valore 4 (pulsante SELECT): In questa sfida questo pulsante cancella lo schermo.

  • Poi, viene confrontato con il valore 8 (pulsante START): In questa sfida controlla se il codice è valido per ottenere la flag.

  • In questo caso la variabile DAT_030000d8 viene confrontata con 0xf3 e se il valore è lo stesso viene eseguito del codice.

  • In tutti gli altri casi, viene controllato un cont (DAT_030000d4). È un cont perché viene aggiunto 1 subito dopo l'ingresso nel codice. Se è inferiore a 8, viene fatto qualcosa che coinvolge aggiungere valori a DAT_030000d8 (in pratica si aggiungono i valori dei tasti premuti in questa variabile finché il cont è inferiore a 8).

Quindi, in questa sfida, conoscendo i valori dei pulsanti, dovevi premere una combinazione con una lunghezza inferiore a 8 in modo che l'addizione risultante sia 0xf3.

Riferimento per questo tutorial: https://exp.codes/Nostalgia/

Game Boy

Corsi

Try Hard Security Group

Impara l'hacking di AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks:

Last updated