Ciao e benvenuto.
In questo video, parleremo delle basi del linguaggio assembly per l'analisi delle minacce informatiche del linguaggio nativo . file exe.
Che cos'è lo stack?
Stack è l'acronimo di struttura dati LIFO, last in, first out.
Memorizza le variabili locali e gli indirizzi di ritorno delle funzioni.
Vi si accede tramite le istruzioni
push, pop, call e ret e la disposizione della memoria RAM per lo stack è la seguente.
Inizia con un indirizzo alto, come mostrato nel diagramma qui, e man mano che vengono inseriti altri valori, vengono
utilizzati indirizzi sempre più piccoli e gli indirizzi più bassi si trovano in cima allo stack.
Quindi l'intera faccenda è una pila.
Qui c'è una parte della memoria RAM e l'EBP, il puntatore alla base, è il registro che memorizza l'indirizzo della parte
inferiore dello stack.
L'ESP è un altro puntatore che memorizza l'indirizzo della parte superiore dello stack.
Si tratta quindi di registri utili per la creazione di una pila.
Che cos'è l'heap?
L'heap viene utilizzato per memorizzare globalmente la memoria.
Tutte le funzioni possono accedervi perché è memorizzato a livello globale.
In genere vengono memorizzati nella sezione dati di un programma.
Nell'API Win32, RtlAllocateHeap
può essere utilizzato per creare un heap.
Il malware
utilizza l'heap come area di memorizzazione per qualsiasi cosa che intende utilizzare; è possibile consultare la guida
MSDN su Google per la descrizione di questa funzione API.
Successivamente, esaminiamo i registri della CPU.
I registri della CPU sono costituiti
dai seguenti
registri: EAX fino a EIP. EAX è tipicamente noto come accumulatore per le operazioni aritmetiche.
EBX è il puntatore di base per puntare ai dati.
ECX è di solito un contatore per lo spostamento, la rotazione delle istruzioni e il looping.
EDX è per dati, aritmetica e I/O. ESI è un indice di origine,
è un puntatore all'origine
nelle operazioni di stringa. EDI è un indice di destinazione, un puntatore alla destinazione nelle operazioni sulle stringhe.
EBP è un puntatore alla base che punta alla base dello stack, che abbiamo visto.
ESP è un puntatore allo stack che punta alla parte superiore dello stack, mentre EIP è il puntatore all'istruzione, che memorizza
l'indirizzo della prossima istruzione che verrà eseguita.
Esistono anche registri di segmento.
SS è un puntatore allo stack.
CS è un puntatore di codice.
DS è il puntatore ai dati e così via.
I più importanti sono SS, CS e DS, chiamati registri di segmento.
È possibile accedere a parti di un registro, ad esempio al
registro EAX.
In questo esempio è un registro a 32 bit, composto da quattro byte, noto anche come DWORD, quattro
byte, 32 bit.
Se si volesse accedere solo alla metà, cioè alla parola, ai due byte inferiori,
che sono 16 bit, si può usare questo simbolo, AX, invece di EAX.
Se invece si vuole accedere al byte più basso, cioè agli otto bit, si può usare AL.
Quindi AL accede al byte inferiore.
AH accede al byte superiore.
Un esempio è questo.
Supponiamo che EAX abbia i seguenti valori esadecimali: uno, due, tre, quattro, cinque, sei, sette e otto.
Se si intende accedere a EAX, si tratta di una DWORD.
Se si vuole accedere alla parola, si utilizza AX.
Se si vuole accedere al byte superiore, si usa AH, mentre per il byte inferiore si usa AL.
Ecco cosa otterrete.
AX ve ne darà cinque, sei, sette, otto.
AH vi darà cinque, sei, e AL vi darà sette, otto.
La stessa cosa vale per tutti gli altri registri.
Ad esempio, se si accede a EBX, si utilizzerà BX per la parola, mentre il byte inferiore sarà BL,
quello superiore BH e così via.
Abbiamo anche il registro EFLAGS.
È il registro in cui ogni bit agisce come un flag contenente un uno o uno zero.
I più importanti sono i seguenti.
Il CF è un flag di riporto.
Viene impostato quando il risultato di un'operazione è troppo grande per l'operando di destinazione.
Il flag di zero, viene impostato
quando il risultato di un'operazione è uguale a zero.
Il flag di segno viene impostato se il risultato di un'operazione è negativo.
Il flag TF, noto anche come flag di trappola, viene impostato se
si sta eseguendo il debug passo-passo e i malware possono rilevarlo a volte se dispongono di funzionalità
anti-debug.
Istruzioni in linguaggio assembly,
tre categorie principali.
Flusso di dati, ad
esempio l'istruzione
MOV.
Flusso di controllo,
ad esempio
push,
call e jump.
Aritmetica e logica,
ad esempio
XOR, OR, AND, MUL e ADD.
Esempi di istruzioni di trasferimento dati
sono MOV.
Lo scopo è quello di spostarsi,
ad esempio, dalla sorgente alla destinazione.
Un esempio è quello di spostare il valore memorizzato nell'indirizzo nel registro EAX.
MOVZX, che significa sposta zero esteso, ad esempio sposta la sorgente alla destinazione.
In questo modo si sposta l'esadecimale 123 in EAX e si riempiono i bit di ordine superiore con degli zeri.
LEA, caricare l'indirizzo effettivo, ad esempio caricare la sorgente sulla destinazione.
In questo modo si carica l'indirizzo EBP meno 40 in esadecimale da EBP e si memorizza
l'indirizzo risultante in EAX. XCHG serve a scambiare i valori tra due registri.
Ad esempio, lo scambio di sorgente e destinazione scambierà qualsiasi cosa contenuta nella sorgente con la destinazione e qualsiasi cosa contenuta
nella destinazione con la sorgente.
Esempi di istruzioni di flusso di controllo: salti.
Si tratta quindi di un salto incondizionato, che salta indipendentemente dalla condizione precedente.
Esempio: JMP, salto al valore memorizzato in questo indirizzo.
JZ è un salto condizionato.
Salta solo se il flag zero è uno.
Ad esempio, l'indirizzo JZ. JNZ, jump not zero, salta se il flag zero è zero.
Il salto JZ è preceduto da un'istruzione di test o di confronto.
Tuttavia, JMP è un salto incondizionato e non preceduto da alcun test o confronto.
Ecco un esempio di salto.
Quindi questo salto avverrà solo se il confronto è uguale a zero.
Ad esempio, se EAX meno ESI è zero, si salta.
Questo JB viene saltato di seguito.
Pertanto, il salto sottostante avviene solo se EAX meno il valore memorizzato in EAX più C è minore di zero.
Poi salterà.
E qui, il salto non è
uguale.
Il salto non uguale
avviene solo se EAX meno EDI
non è uguale a
zero.
Solo allora salterà.
Esempi di istruzioni aritmetiche: ADD, SUB, IMUL e INC.
Un esempio potrebbe essere ADD source to destination,
che significa che si prende ciò che si trova nell'origine, si aggiunge alla destinazione e si memorizza il risultato
nella destinazione.
SUB è la stessa cosa, ma solo in negativo.
IMUL consiste nel moltiplicare l'origine per il valore e memorizzare il risultato nella destinazione.
Incremento, INC, significa incrementare di uno qualsiasi elemento del registro.
E questi sono esempi qui.
Esempi di istruzioni logiche.
XOR esegue un XOR bitwise, ad esempio XOR sorgente,
destinazione.
E poi qui, spostatevi a sinistra.
Ciò significa che si spostano tutti i bit a sinistra del numero di bit indicato nella sorgente.
Ad esempio, se CL è uno, si sposta ogni bit a sinistra di uno. AND esegue il bitwise AND.
Si esegue quindi un'operazione AND con un'origine e una destinazione.
TEST e confronto delle istruzioni.
Qui si esegue un AND bitwise su due operandi.
Se il risultato è zero, viene impostato il flag zero.
Spesso utilizzato con i salti condizionali.
Con CMP si confronta il primo operando con il secondo operando mediante sottrazione.
Questo è un esempio in cui si prende l'argomento uno meno l'argomento due. Le istruzioni di salto arrivano sempre subito dopo un test
o un confronto, come ho appena dimostrato. Valori di ritorno: il registro EAX viene utilizzato
per contenere il valore di ritorno di una chiamata di funzione.
Il valore di ritorno può essere un numero intero, uno zero o addirittura un valore negativo, indicato in esadecimale da tutte
le F.
Può anche essere un indirizzo, ad esempio questo indirizzo esadecimale.
Si prenda, ad esempio, questo output da x64dbg.
Qui vedrete un push seven.
Quindi push seven spingerà sette nello stack qui sotto e poi chiamerà" "dopo aver chiamato questa funzione,
restituirà il risultato della chiamata in EAX.
Questo è tutto per quanto riguarda questo primo capitolo sul linguaggio assembly.
Grazie per aver guardato.