Malware analysis e reverse engineering
Analisi statica e dinamica, tecniche di evasion, reverse engineering di binari.
Livello: Avanzato
Obiettivo: Analizzare malware con approcci statici e dinamici, comprendere tecniche di evasion, eseguire reverse engineering di binari.
1. Setup Ambiente di Analisi
REGOLA ASSOLUTA: Analizza malware SOLO in ambiente isolato. Mai su sistemi di produzione.
1.1 Laboratorio sicuro
[Internet]
↑ NAT/Host-only (bloccato o monitorato)
[Kali Linux — Host di analisi]
↕ Rete isolata host-only
[VM Windows — Sandbox malware]
- Snapshot pre-analisi
- INetSim / FakeNet per simulare rete
- Nessuna condivisione cartelle con host
# Impostare rete host-only in VirtualBox
VBoxManage modifyvm "Windows10-Malware" --nic1 hostonly
VBoxManage modifyvm "Windows10-Malware" --hostonlyadapter1 vboxnet0
# Configurare INetSim su Kali (simula servizi di rete per il malware)
sudo apt install inetsim
sudo nano /etc/inetsim/inetsim.conf
# service_bind_address = 192.168.56.1 (IP Kali sulla rete host-only)
sudo inetsim
1.2 Tool essenziali
# Installazione tool su Kali
sudo apt install -y \
binutils \ # strings, objdump, nm, readelf
hexedit \ # editor esadecimale
yara \ # pattern matching su malware
radare2 \ # RE framework avanzato
clamav \ # antivirus CLI
ssdeep \ # fuzzy hashing
# Tool aggiuntivi
pip3 install pefile capstone angr
# Ghidra (NSA reverse engineering tool)
sudo apt install ghidra
# IDA Free
# Download da https://hex-rays.com/ida-free/
2. Analisi Statica
L'analisi statica esamina il binario senza eseguirlo.
2.1 Identificazione del file
# Tipo di file (magic bytes)
file malware.exe
file -b --mime-type malware.bin
# → application/x-dosexec (PE Windows)
# → application/x-elf (Linux)
# → application/x-sharedlib (libreria)
# Magic bytes manuali
xxd malware.exe | head -5
# MZ (4D 5A) = PE Windows
# ELF (7F 45 4C 46) = Linux ELF
# PK (50 4B) = ZIP/DOCX/APK
# %PDF = PDF
# Entropia (alta entropia → packedè/cifrato)
python3 -c "
import math, sys
with open(sys.argv[1], 'rb') as f:
data = f.read()
freq = {}
for b in data:
freq[b] = freq.get(b, 0) + 1
entropy = -sum((c/len(data)) * math.log2(c/len(data)) for c in freq.values())
print(f'Entropia: {entropy:.2f}/8.0')
" malware.exe
# > 7.0 = quasi certamente compresso/cifrato/packed
2.2 Estrazione stringhe
# Strings base
strings malware.exe | less
strings -a -n 6 malware.exe > strings.txt # minimo 6 caratteri
# Stringhe Unicode (Windows)
strings -e l malware.exe # little-endian 16-bit
# Filtrare stringhe interessanti
strings malware.exe | grep -iE "http|ftp|cmd|powershell|registry|password|key|decrypt"
strings malware.exe | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" # IP
strings malware.exe | grep -E "HKEY_" # chiavi registro Windows
# FLOSS — estrae stringhe offuscate e decodifica
pip3 install floss
floss malware.exe > floss_output.txt
2.3 Analisi PE (Windows Executable)
# pefile — analisi struttura PE
python3 << 'EOF'
import pefile, sys
pe = pefile.PE('malware.exe')
# Header
print(f"Machine: {hex(pe.FILE_HEADER.Machine)}") # 0x14c = x86, 0x8664 = x64
print(f"Timestamp: {pe.FILE_HEADER.TimeDateStamp}")
print(f"Entry point: {hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint)}")
# Sezioni
print("\n--- SEZIONI ---")
for section in pe.sections:
print(f"{section.Name.decode().strip(chr(0))} | VirtAddr: {hex(section.VirtualAddress)} | Size: {section.SizeOfRawData}")
# Import (DLL e funzioni chiamate)
print("\n--- IMPORT ---")
for entry in pe.DIRECTORY_ENTRY_IMPORT:
print(f"\n{entry.dll.decode()}")
for imp in entry.imports:
print(f" {imp.name.decode() if imp.name else 'ordinal_'+str(imp.ordinal)}")
# Export (se è una DLL)
if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
print(f"Export: {exp.name.decode()}")
EOF
Import sospette da cercare:
| DLL | Funzioni sospette | Indizio |
|---|---|---|
kernel32.dll | CreateRemoteThread, WriteProcessMemory | Process injection |
kernel32.dll | VirtualAllocEx, VirtualProtect | Shellcode injection |
advapi32.dll | RegOpenKey, RegSetValue | Persistenza registro |
ws2_32.dll | connect, send, recv, WSAConnect | Comunicazione rete |
wininet.dll | InternetOpen, HttpSendRequest | HTTP C2 |
ntdll.dll | NtCreateThreadEx, NtUnmapViewOfSection | Process hollowing |
2.4 Hashing e Ricerca su VirusTotal
# Calcola hash
md5sum malware.exe
sha1sum malware.exe
sha256sum malware.exe
# Fuzzy hash (trova varianti simili)
ssdeep malware.exe
# VirusTotal CLI
pip3 install vt-py
vt file malware.exe # richiede API key
# Ricerca manuale su VirusTotal:
# 1. Carica il file (ATTENZIONE: rende il file pubblico)
# 2. Oppure cerca solo l'hash (sicuro, non espone il binario)
2.5 YARA — Pattern Matching
YARA permette di scrivere regole per identificare famiglie di malware:
# Esempio regola YARA
cat << 'EOF' > detect_ransomware.yar
rule Ransomware_Wannacry {
meta:
description = "Rileva WannaCry"
author = "Analista"
strings:
$s1 = "WNcrypt" nocase
$s2 = "tasksche.exe" nocase
$s3 = ".WNCRY" nocase
$hex1 = { 45 44 52 } // "EDR"
condition:
3 of them
}
EOF
# Applicare la regola
yara detect_ransomware.yar malware.exe
yara -r detect_ransomware.yar /suspect_folder/ # ricorsivo
# Database regole community (YARA-Rules)
git clone https://github.com/Yara-Rules/rules
yara -r rules/ malware.exe
3. Analisi Dinamica
Esegui il malware in ambiente controllato e osserva il comportamento.
3.1 Monitoring dei processi (Windows Sandbox)
Tool da usare su VM Windows:
- Process Monitor (ProcMon) — ogni syscall, file, registro, rete
- Process Hacker — processi, thread, memoria, handle
- Wireshark — traffico di rete
- Regshot — snapshot registro prima/dopo esecuzione
- API Monitor — intercetta chiamate API
Workflow analisi dinamica:
- Avvia INetSim/FakeNet su Kali (simula rete)
- Avvia Wireshark sulla VM (o sull'host)
- Avvia ProcMon con filtro sul processo da analizzare
- Scatta snapshot registro con Regshot (BEFORE)
- Esegui il malware
- Osserva per 2-5 minuti
- Scatta snapshot registro (AFTER)
- Analizza diff di Regshot
- Esamina log ProcMon: file scritti, chiavi registro, processi creati
- Analizza traffico Wireshark
3.2 strace / ltrace (Linux)
# strace — traccia syscall
strace -f -e trace=network,file,process ./malware 2>&1 | tee strace_out.txt
# Filtri utili
strace -f -e openat,read,write,connect,execve ./malware
strace -f -p 1234 # attaccarsi a processo esistente
# ltrace — traccia chiamate librerie
ltrace ./malware 2>&1 | tee ltrace_out.txt
# Combinato
strace -f -e trace=all ./malware 2>&1 | grep -E "connect|open|exec|fork"
# Analisi: cercare
grep "connect" strace_out.txt # connessioni rete
grep "open(" strace_out.txt # file aperti
grep "execve" strace_out.txt # processi lanciati
grep "write(" strace_out.txt # scritture (potenziale ransom?)
3.3 Sandbox automatizzate
# Cuckoo Sandbox (self-hosted)
sudo pip3 install cuckoo
cuckoo init
cuckoo -d & # modalità debug
cuckoo web -H 0.0.0.0 -p 8080 # interfaccia web
# Invio campione a Cuckoo
curl -F file=@malware.exe http://localhost:8080/tasks/create/file
# Alternative cloud (non esporre malware sensibile):
# - any.run (interattivo nel browser)
# - hybrid-analysis.com (gratuito)
# - app.any.run
# - joesandbox.com
4. Disassembly e Reverse Engineering
4.1 Radare2
# Aprire un binario
r2 malware.exe
r2 -d malware.exe # con debugger
# Comandi base r2
[0x00400000]> aaa # analisi automatica completa
[0x00400000]> afl # lista di tutte le funzioni
[0x00400000]> pdf @ main # disassembla main
[0x00400000]> s main # vai a main
[0x00400000]> pdf # disassembla funzione corrente
[0x00400000]> pdd # decompila (con r2ghidra plugin)
[0x00400000]> iz # stringhe nelle sezioni dati
[0x00400000]> iI # info PE/ELF
[0x00400000]> ii # imports
[0x00400000]> VV # modalità grafo (visual)
[0x00400000]> q # esci
4.2 Ghidra — Decompiler
Ghidra è il tool NSA open-source per reverse engineering, produce pseudo-codice C:
# Avviare Ghidra
ghidra
# Workflow:
# 1. New Project → Non-Shared Project
# 2. Import file → malware.exe
# 3. Auto-analyze (YES, abilita tutto)
# 4. Symbol Tree → Functions → main
# 5. Decompiler mostra il pseudo-C a destra
# 6. Rinomina variabili/funzioni per chiarezza
# 7. Cerca stringhe: Search → For Strings
4.3 Analisi Assembly — Concetti Chiave
; Registri x86-64
; RAX - valore di ritorno
; RBX, RCX, RDX - registri generici
; RSP - stack pointer
; RBP - base pointer (frame dello stack)
; RIP - instruction pointer
; Chiamata di funzione
push rdi ; salva parametro
call 0x401234 ; chiama funzione
add rsp, 8 ; ripristina stack
; Confronto e salto
cmp eax, 0 ; confronta eax con 0
jz 0x401300 ; jump if zero (eax == 0)
jnz 0x401300 ; jump if not zero
jl 0x401300 ; jump if less (signed)
; Accesso a memoria
mov rax, [rbp-8] ; leggi da stack
mov [rbp-8], rax ; scrivi nello stack
mov rax, [rdi+4] ; campo di struttura (offset 4)
; Istruzione sospetta: XOR per cifratura
xor eax, eax ; azzera eax (comune)
xor al, 0x55 ; decifratura byte con chiave 0x55
; CALL con indirizzo dinamico (anti-RE)
call [rax] ; chiama funzione il cui addr è in rax
jmp [rip+0x1000] ; jump to imported function
5. Tecniche di Evasion e Anti-Analysis
5.1 Tecniche anti-debug
# Rilevamento debugger (Windows)
# IsDebuggerPresent API
import ctypes
def is_debugged():
return ctypes.windll.kernel32.IsDebuggerPresent() != 0
# Timing attack (l'esecuzione in debugger è più lenta)
import time
start = time.time()
# operazione
elapsed = time.time() - start
if elapsed > 0.1: # troppo lento → debugger presente
exit()
# In assembly: RDTSC (Read Time-Stamp Counter)
# rdtsc ; leggi timestamp
# [operazione]
# rdtsc ; leggi di nuovo
# sub eax, [primo_valore] ; differenza
# cmp eax, 0x10000 ; soglia
# jg debugger_detected
# Come bypassare in GDB/radare2:
# Patch del byte di ritorno di IsDebuggerPresent:
r2 -w malware.exe
[0x00401000]> s sym.imp.IsDebuggerPresent
[0x00401000]> wx 31c0c3 # xor eax,eax; ret → forza ritorno 0
5.2 Obfuscation e packing
# Rilevare packer
upx -t malware.exe # verifica se è UPX
die malware.exe # Detect-It-Easy: identifica packer
# Unpack UPX
upx -d malware.exe -o unpacked.exe
# Per packer sconosciuti: dump dalla memoria durante esecuzione
# 1. Esegui in debugger
# 2. Metti breakpoint sull'entry point originale (OEP)
# 3. Quando il packer completa il decompressing, dump memoria
# Tool: OllyDump, PE-bear, Scylla
# Analisi codice offuscato Python
# Deoffusca codice base64 comune
python3 -c "import base64; print(base64.b64decode(b'ENCODED_STRING'))"
# PowerShell deoffuscation
# Base64 decodifica
[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("BASE64"))
5.3 Process Injection
Tecnica per nascondere codice in processi legittimi:
Tipi principali:
1. DLL Injection → forza un processo a caricare una DLL malevola
2. Process Hollowing → crea processo sospeso, svuota memoria, inietta shellcode
3. Thread Injection → crea thread remoto in processo legittimo
4. Reflective DLL → DLL si carica da sola in memoria (no file su disco)
5. Process Doppelgänging → usa NTFS transactions per eludere AV
# Esempio: Thread Injection (didattico)
import ctypes
# Shellcode da iniettare (esempio: msfvenom -p windows/x64/shell_reverse_tcp LHOST=... -f py)
shellcode = b"\x90" * 100 # NOP sled (esempio)
# Trovare PID processo target
pid = 1234 # notepad.exe
PROCESS_ALL_ACCESS = 0x1F0FFF
MEM_COMMIT = 0x1000
PAGE_EXECUTE_READWRITE = 0x40
# Open process
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
# Alloca memoria nel processo target
addr = ctypes.windll.kernel32.VirtualAllocEx(handle, 0, len(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
# Scrivi shellcode
ctypes.windll.kernel32.WriteProcessMemory(handle, addr, shellcode, len(shellcode), None)
# Crea thread remoto
ctypes.windll.kernel32.CreateRemoteThread(handle, None, 0, addr, None, 0, None)
6. Analisi Malware Comuni
6.1 Ransomware
Indicatori:
- Molte operazioni di lettura/scrittura su file
- Generazione di chiavi crittografiche
- Connessione a C2 per scambio chiavi
- Cancellazione delle Shadow Copies Windows
- Note di riscatto create
# Cosa cercare in analisi statica
strings ransomware.exe | grep -iE "vssadmin|shadowcopy|encrypt|aes|rsa|bitcoin|ransom"
strings ransomware.exe | grep -E "\.locked|\.encrypted|\.WNCRY|\.crypted"
# In analisi dinamica con ProcMon:
# Filtra per: Process Name = ransomware.exe
# Cerca: CreateFile, WriteFile, DeleteFile in massa
# Cerca: "vssadmin delete shadows /all /quiet"
6.2 RAT (Remote Access Trojan)
Indicatori:
- Connessione persistente verso IP esterno (C2)
- Screenshot e keylogging
- Modifica registro per persistenza all'avvio
- Raccolta info sistema
# In analisi di rete
# Traffico periodico (beacon) → esempio ogni 30 secondi
tshark -r capture.pcap -T fields -e frame.time -e ip.dst -e tcp.dstport -e frame.len | sort -k3
# Pattern beacon: stessa destinazione, stesso intervallo, dati simili
# Analisi con zeek
zeek -r capture.pcap && cat conn.log | zeek-cut id.resp_h duration | sort | uniq -c | sort -rn
6.3 Rootkit
# Rootkit kernel nasconde processi, file, connessioni
# Rilevazione comparando output user-space vs kernel
# Confronto pslist vs psscan (Volatility)
python3 vol.py -f memory.dmp linux.pslist | awk '{print $2}' | sort > pslist.txt
python3 vol.py -f memory.dmp linux.psscan | awk '{print $2}' | sort > psscan.txt
diff pslist.txt psscan.txt # processi nascosti!
# rkhunter
sudo apt install rkhunter
sudo rkhunter --check --sk
# chkrootkit
sudo apt install chkrootkit
sudo chkrootkit
# Verifica integrità binari di sistema
debsums -c # Debian/Ubuntu: controlla hash dei pacchetti
7. Lab Pratico — Analisi di un Campione Reale
Scenario: Analisi di un binario sospetto trovato su un sistema.
# Step 1: Identificazione sicura
cp suspicious_file /tmp/malware_analysis/malware.bin
file /tmp/malware_analysis/malware.bin
md5sum malware.bin; sha256sum malware.bin
# Step 2: Verifica hash su VirusTotal (solo hash, non carica il file!)
# Cerca l'hash sha256 su https://www.virustotal.com
# Step 3: Analisi stringhe
strings malware.bin | tee strings_output.txt
grep -iE "http|ftp|socket|cmd|exec|download|upload" strings_output.txt
# Step 4: Analisi ELF (se Linux)
readelf -h malware.bin # header
readelf -S malware.bin # sezioni
readelf -d malware.bin # sezione dinamica (librerie)
nm -D malware.bin # simboli dinamici
objdump -d malware.bin | head -200 # disassembly parziale
# Step 5: Analisi dinamica in ambiente isolato
strace -f ./malware.bin 2>&1 | head -200
# Step 6: RE con radare2
r2 malware.bin
[0x00000000]> aaa
[0x00000000]> s main
[0x00000000]> pdf
# Step 7: YARA scan con regole community
yara -r rules/ malware.bin
Quiz di autoverifica
- Cos'è l'entropia di un binario e perché un valore alto è sospetto?
- Cosa rivelano le Import Table di un file PE?
- Qual è la differenza tra analisi statica e dinamica? Quando conviene usare una o l'altra?
- Descrivi il processo di "Process Hollowing". Come lo rileveresti?
- Come funziona un timing attack per rilevare la presenza di un debugger?
Precedente: 04 — Analisi Forense
Prossimo: 06 — Linux Kernel & Internals
Continua a leggere
Linux kernel e internals
Internals del kernel, syscall, moduli, privilege escalation e basi di kernel exploitation.
Vai al capitolo