Malware & reverse engineering
12 min read

Malware analysis e reverse engineering

Analisi statica e dinamica, tecniche di evasion, reverse engineering di binari.

malware
reverse-engineering
evasion

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:

DLLFunzioni sospetteIndizio
kernel32.dllCreateRemoteThread, WriteProcessMemoryProcess injection
kernel32.dllVirtualAllocEx, VirtualProtectShellcode injection
advapi32.dllRegOpenKey, RegSetValuePersistenza registro
ws2_32.dllconnect, send, recv, WSAConnectComunicazione rete
wininet.dllInternetOpen, HttpSendRequestHTTP C2
ntdll.dllNtCreateThreadEx, NtUnmapViewOfSectionProcess 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:

  1. Avvia INetSim/FakeNet su Kali (simula rete)
  2. Avvia Wireshark sulla VM (o sull'host)
  3. Avvia ProcMon con filtro sul processo da analizzare
  4. Scatta snapshot registro con Regshot (BEFORE)
  5. Esegui il malware
  6. Osserva per 2-5 minuti
  7. Scatta snapshot registro (AFTER)
  8. Analizza diff di Regshot
  9. Esamina log ProcMon: file scritti, chiavi registro, processi creati
  10. 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

  1. Cos'è l'entropia di un binario e perché un valore alto è sospetto?
  2. Cosa rivelano le Import Table di un file PE?
  3. Qual è la differenza tra analisi statica e dinamica? Quando conviene usare una o l'altra?
  4. Descrivi il processo di "Process Hollowing". Come lo rileveresti?
  5. 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