macOS Apps - Inspecting, debugging and Fuzzing
WhiteIntel è un motore di ricerca alimentato dal dark web che offre funzionalità gratuite per verificare se un'azienda o i suoi clienti sono stati compromessi da malware ruba-informazioni.
Il loro obiettivo principale è contrastare i sequestri di account e gli attacchi ransomware derivanti da malware che rubano informazioni.
Puoi visitare il loro sito web e provare il loro motore gratuitamente su:
Analisi Statica
otool
objdump
jtool2
Lo strumento può essere utilizzato come un sostituto per codesign, otool e objdump, e fornisce alcune funzionalità aggiuntive. Scaricalo qui o installalo con brew
.
Codesign / ldid
Codesign
può essere trovato in macOS mentre ldid
può essere trovato in iOS
SuspiciousPackage
SuspiciousPackage è uno strumento utile per ispezionare i file .pkg (installatori) e vedere cosa c'è dentro prima di installarli.
Questi installatori contengono script bash preinstall
e postinstall
che gli autori di malware di solito sfruttano per persistere il malware.
hdiutil
Questo strumento consente di montare le immagini disco Apple (.dmg) per ispezionarle prima di eseguire qualsiasi operazione:
Sarà montato in /Volumes
Objective-C
Metadati
Nota che i programmi scritti in Objective-C mantengono le loro dichiarazioni di classe quando compilati in binari Mach-O. Tali dichiarazioni di classe includono il nome e il tipo di:
La classe
I metodi della classe
Le variabili di istanza della classe
Puoi ottenere queste informazioni utilizzando class-dump:
Chiamata di funzione
Quando una funzione viene chiamata in un binario che utilizza Objective-C, il codice compilato invece di chiamare direttamente quella funzione, chiamerà objc_msgSend
. Questo a sua volta chiamerà la funzione finale:
I parametri che questa funzione si aspetta sono:
Il primo parametro (self) è "un puntatore che punta all'istanza della classe che deve ricevere il messaggio". O più semplicemente, è l'oggetto su cui il metodo viene invocato. Se il metodo è un metodo di classe, questo sarà un'istanza dell'oggetto della classe (nel suo complesso), mentre per un metodo di istanza, self punterà a un'istanza istanziata della classe come oggetto.
Il secondo parametro, (op), è "il selettore del metodo che gestisce il messaggio". Di nuovo, in modo più semplice, questo è semplicemente il nome del metodo.
I parametri rimanenti sono eventuali valori richiesti dal metodo (op).
Guarda come ottenere facilmente queste informazioni con lldb
in ARM64 in questa pagina:
x64:
Argomento | Registro | (per) objc_msgSend |
1° argomento | rdi | self: oggetto su cui il metodo viene invocato |
2° argomento | rsi | op: nome del metodo |
3° argomento | rdx | 1° argomento per il metodo |
4° argomento | rcx | 2° argomento per il metodo |
5° argomento | r8 | 3° argomento per il metodo |
6° argomento | r9 | 4° argomento per il metodo |
7°+ argomento | rsp+ (nello stack) | 5°+ argomento per il metodo |
Swift
Con i binari Swift, poiché c'è compatibilità con Objective-C, a volte è possibile estrarre le dichiarazioni utilizzando class-dump ma non sempre.
Con i comandi jtool -l
o otool -l
è possibile trovare diverse sezioni che iniziano con il prefisso __swift5
:
Puoi trovare ulteriori informazioni sull'informazione memorizzata in questa sezione in questo post del blog.
Inoltre, i binari Swift potrebbero avere simboli (ad esempio le librerie devono memorizzare i simboli in modo che le sue funzioni possano essere chiamate). I simboli di solito contengono le informazioni sul nome della funzione e sugli attributi in modo poco chiaro, quindi sono molto utili e ci sono "demanglers" che possono ottenere il nome originale:
Binari compressi
Controllare l'alta entropia
Controllare le stringhe (se non ci sono stringhe comprensibili, è compresso)
Il pacchetto UPX per MacOS genera una sezione chiamata "__XHDR"
Analisi dinamica
Nota che per eseguire il debug dei binari, SIP deve essere disabilitato (csrutil disable
o csrutil enable --without debug
) oppure copiare i binari in una cartella temporanea e rimuovere la firma con codesign --remove-signature <percorso-binario>
o consentire il debug del binario (puoi utilizzare questo script)
Nota che per strumentare i binari di sistema (come cloudconfigurationd
) su macOS, SIP deve essere disabilitato (rimuovere solo la firma non funzionerà).
Log unificati
MacOS genera molti log che possono essere molto utili quando si esegue un'applicazione cercando di capire cosa sta facendo.
Inoltre, ci sono alcuni log che conterranno il tag <private>
per nascondere alcune informazioni identificabili dall'utente o dal computer. Tuttavia, è possibile installare un certificato per divulgare queste informazioni. Segui le spiegazioni da qui.
Hopper
Pannello sinistro
Nel pannello sinistro di hopper è possibile vedere i simboli (Etichette) del binario, l'elenco delle procedure e delle funzioni (Proc) e le stringhe (Str). Queste non sono tutte le stringhe ma quelle definite in diverse parti del file Mac-O (come cstring o objc_methname
).
Pannello centrale
Nel pannello centrale è possibile vedere il codice disassemblato. E puoi vederlo come disassemblaggio grezzo, come grafico, come decompilato e come binario cliccando sull'icona rispettiva:
Facendo clic con il pulsante destro su un oggetto di codice è possibile vedere i riferimenti da/a quell'oggetto o persino cambiarne il nome (questo non funziona nel pseudocodice decompilato):
Inoltre, nella parte centrale in basso è possibile scrivere comandi python.
Pannello destro
Nel pannello destro è possibile vedere informazioni interessanti come la cronologia di navigazione (così sai come sei arrivato alla situazione attuale), il grafo delle chiamate dove puoi vedere tutte le funzioni che chiamano questa funzione e tutte le funzioni che questa funzione chiama, e le informazioni sulle variabili locali.
dtrace
Consente agli utenti di accedere alle applicazioni a un livello estremamente basso e fornisce un modo per gli utenti di tracciare i programmi e persino cambiare il loro flusso di esecuzione. Dtrace utilizza sonde che sono posizionate in tutto il kernel e si trovano in posizioni come l'inizio e la fine delle chiamate di sistema.
DTrace utilizza la funzione dtrace_probe_create
per creare una sonda per ogni chiamata di sistema. Queste sonde possono essere attivate nel punto di ingresso e di uscita di ogni chiamata di sistema. L'interazione con DTrace avviene tramite /dev/dtrace che è disponibile solo per l'utente root.
Per abilitare Dtrace senza disabilitare completamente la protezione SIP, è possibile eseguire in modalità di ripristino: csrutil enable --without dtrace
È anche possibile dtrace
o dtruss
i binari che hai compilato.
Le sonde disponibili di dtrace possono essere ottenute con:
Il nome della sonda è composto da quattro parti: il provider, il modulo, la funzione e il nome (fbt:mach_kernel:ptrace:entry
). Se non si specifica una parte del nome, Dtrace applicherà quella parte come un carattere jolly.
Per configurare DTrace per attivare le sonde e specificare quali azioni eseguire quando vengono attivate, dovremo utilizzare il linguaggio D.
Una spiegazione più dettagliata e ulteriori esempi possono essere trovati in https://illumos.org/books/dtrace/chp-intro.html
Esempi
Esegui man -k dtrace
per elencare gli script DTrace disponibili. Esempio: sudo dtruss -n binary
In linea
script
dtruss
ktrace
Puoi utilizzare questo anche con SIP attivato
ProcessMonitor
ProcessMonitor è uno strumento molto utile per controllare le azioni correlate ai processi che un processo sta eseguendo (ad esempio, monitorare quali nuovi processi un processo sta creando).
SpriteTree
SpriteTree è uno strumento che stampa le relazioni tra i processi.
È necessario monitorare il tuo Mac con un comando come sudo eslogger fork exec rename create > cap.json
(il terminale che avvia questo comando richiede FDA). E poi puoi caricare il json in questo strumento per visualizzare tutte le relazioni:
FileMonitor
FileMonitor consente di monitorare gli eventi dei file (come creazione, modifiche ed eliminazioni) fornendo informazioni dettagliate su tali eventi.
Crescendo
Crescendo è uno strumento GUI con l'aspetto e la sensazione che gli utenti di Windows potrebbero conoscere da Procmon di Microsoft Sysinternal. Questo strumento consente di avviare e interrompere la registrazione di vari tipi di eventi, consente di filtrare questi eventi per categorie come file, processo, rete, ecc., e fornisce la funzionalità per salvare gli eventi registrati in un formato json.
Apple Instruments
Apple Instruments fanno parte degli strumenti per sviluppatori di Xcode, utilizzati per monitorare le prestazioni dell'applicazione, identificare perdite di memoria e tracciare l'attività del filesystem.
fs_usage
Consente di seguire le azioni eseguite dai processi:
TaskExplorer
Taskexplorer è utile per vedere le librerie utilizzate da un binario, i file che sta utilizzando e le connessioni di rete. Controlla anche i processi binari su virustotal e mostra informazioni sul binario.
PT_DENY_ATTACH
In questo post sul blog puoi trovare un esempio su come debuggare un demone in esecuzione che utilizza PT_DENY_ATTACH
per impedire il debug anche se SIP era disabilitato.
lldb
lldb è lo strumento di debugging binario de facto per macOS.
Puoi impostare il flavor di intel quando utilizzi lldb creando un file chiamato .lldbinit
nella tua cartella home con la seguente riga:
All'interno di lldb, eseguire il dump di un processo con process save-core
(lldb) Comando | Descrizione |
run (r) | Avvia l'esecuzione, che continuerà senza interruzioni fino a quando non viene raggiunto un punto di interruzione o il processo termina. |
continue (c) | Continua l'esecuzione del processo in debug. |
nexti (n / ni) | Esegue l'istruzione successiva. Questo comando salterà le chiamate alle funzioni. |
stepi (s / si) | Esegue l'istruzione successiva. A differenza del comando nexti, questo comando entrerà nelle chiamate alle funzioni. |
finish (f) | Esegue il resto delle istruzioni nella funzione corrente ("frame") e si ferma. |
control + c | Sospende l'esecuzione. Se il processo è stato avviato (r) o continuato (c), questo causerà l'arresto del processo ...dove si sta eseguendo attualmente. |
breakpoint (b) | b main #Qualsiasi funzione chiamata main b <nomebinario>`main #Funzione principale del binario b set -n main --shlib <nome_libreria> #Funzione principale del binario indicato b -[NSDictionary objectForKey:] b -a 0x0000000100004bd9 br l #Elenco dei punti di interruzione br e/dis <num> #Abilita/Disabilita il punto di interruzione breakpoint delete <num> |
help | help breakpoint #Ottieni aiuto sul comando breakpoint help memory write #Ottieni aiuto per scrivere nella memoria |
reg | |
x/s <indirizzo_registro/memoria | Visualizza la memoria come stringa terminata da null. |
x/i <indirizzo_registro/memoria | Visualizza la memoria come istruzione assembly. |
x/b <indirizzo_registro/memoria | Visualizza la memoria come byte. |
print object (po) | Questo stamperà l'oggetto referenziato dal parametro po $raw
Nota che la maggior parte delle API o metodi Objective-C di Apple restituiscono oggetti e quindi dovrebbero essere visualizzati tramite il comando "print object" (po). Se po non produce un output significativo, utilizzare |
memory | memory read 0x000.... memory read $x0+0xf2a memory write 0x100600000 -s 4 0x41414141 #Scrivi AAAA in quell'indirizzo memory write -f s $rip+0x11f+7 "AAAA" #Scrivi AAAA nell'indirizzo |
disassembly | dis #Disassembla la funzione corrente dis -n <nomefunzione> #Disassembla la funzione dis -n <nomefunzione> -b <basename> #Disassembla la funzione dis -c 6 #Disassembla 6 linee dis -c 0x100003764 -e 0x100003768 # Da un indirizzo all'altro dis -p -c 4 # Inizia nell'indirizzo corrente disassemblando |
parray | parray 3 (char **)$x1 # Controlla l'array di 3 componenti nel registro x1 |
Quando si chiama la funzione objc_sendMsg
, il registro rsi contiene il nome del metodo come stringa terminata da null ("C"). Per stampare il nome tramite lldb fare:
(lldb) x/s $rsi: 0x1000f1576: "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) print (char*)$rsi:
(char *) $1 = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) reg read $rsi: rsi = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
Analisi Anti-Dinamica
Rilevamento di VM
Il comando
sysctl hw.model
restituisce "Mac" quando l'host è un MacOS ma qualcosa di diverso quando si tratta di una VM.Giocando con i valori di
hw.logicalcpu
ehw.physicalcpu
alcuni malware cercano di rilevare se si tratta di una VM.Alcuni malware possono anche rilevare se la macchina è basata su VMware in base all'indirizzo MAC (00:50:56).
È anche possibile scoprire se un processo viene debuggato con un codice semplice come:
if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //processo in fase di debug }
Può anche invocare la chiamata di sistema
ptrace
con il flagPT_DENY_ATTACH
. Questo impedisce a un debugger di collegarsi e tracciare.È possibile verificare se la funzione
sysctl
optrace
viene importata (ma il malware potrebbe importarla dinamicamente)Come indicato in questo articolo, “Sconfiggere le tecniche anti-debug: varianti di ptrace di macOS” : “Il messaggio Processo # è uscito con status = 45 (0x0000002d) è di solito un segno rivelatore che il target di debug sta utilizzando PT_DENY_ATTACH”
Fuzzing
ReportCrash analizza i processi che causano crash e salva un report di crash su disco. Un report di crash contiene informazioni che possono aiutare uno sviluppatore a diagnosticare la causa di un crash.
Per le applicazioni e altri processi che vengono eseguiti nel contesto di lancio per utente singolo, ReportCrash viene eseguito come LaunchAgent e salva i report di crash nella cartella ~/Library/Logs/DiagnosticReports/
dell'utente.
Per i daemon, altri processi che vengono eseguiti nel contesto di lancio di sistema e altri processi privilegiati, ReportCrash viene eseguito come LaunchDaemon e salva i report di crash nella cartella /Library/Logs/DiagnosticReports
del sistema.
Se sei preoccupato che i report di crash vengano inviati ad Apple, puoi disabilitarli. In caso contrario, i report di crash possono essere utili per capire come è avvenuto il crash di un server.
Sonno
Durante il fuzzing in un MacOS è importante non permettere al Mac di andare in modalità di sonno:
systemsetup -setsleep Never
pmset, Preferenze di Sistema
Disconnessione SSH
Se stai facendo fuzzing tramite una connessione SSH è importante assicurarsi che la sessione non vada inattiva. Quindi modifica il file sshd_config con:
TCPKeepAlive Yes
ClientAliveInterval 0
ClientAliveCountMax 0
Gestori Interni
Controlla la seguente pagina per scoprire come puoi trovare quale app è responsabile di gestire lo schema o protocollo specificato:
pagemacOS File Extension & URL scheme app handlersEnumerazione dei Processi di Rete
È interessante trovare i processi che gestiscono i dati di rete:
Oppure utilizza netstat
o lsof
Libgmalloc
Fuzzers
Funziona per strumenti CLI
Funziona con gli strumenti GUI di macOS. Nota che alcune app macOS hanno requisiti specifici come nomi file unici, l'estensione corretta, la necessità di leggere i file dalla sandbox (~/Library/Containers/com.apple.Safari/Data
)...
Alcuni esempi:
Ulteriori informazioni su Fuzzing MacOS
Riferimenti
WhiteIntel è un motore di ricerca alimentato dal dark web che offre funzionalità gratuite per verificare se un'azienda o i suoi clienti sono stati compromessi da malware stealer.
Il loro obiettivo principale è combattere i takeover degli account e gli attacchi ransomware derivanti da malware che rubano informazioni.
Puoi visitare il loro sito web e provare il loro motore gratuitamente su:
Last updated