Reverse engineering di un router domestico con binwalk. Ti fidi del software del tuo router?

Reverse engineering di un router domestico con binwalk. Ti fidi del software del tuo router?

Qualche giorno fa, ho deciso di eseguire il reverse engineering del firmware del mio router usando binwalk.

Ho comprato per me un router domestico TP-Link Archer C7. Non è il miglior router, ma per le mie esigenze è più che sufficiente.

Ogni volta che acquisto un nuovo router, installo OpenWRT. Perché? Di solito i produttori non si prendono molto cura del supporto per i propri router e nel tempo il software diventa obsoleto, sorgono vulnerabilità e così via, insomma, avete capito. Pertanto, preferisco un firmware open-source ben supportato dalla comunità come OpenWRT.

Scaricando OpenWRT, ho anche scaricato l'ultima immagine del firmware per il mio nuovo Archer C7 dal sito ufficiale e ho deciso di analizzarlo. Giusto per divertimento e per parlare di binwalk.

Cos'è binwalk?

Binwalk è uno strumento open source per analizzare, fare reverse engineering e estrarre immagini di firmware.

Creato nel 2010 da Craig Heffner, binwalk può scansionare le immagini di firmware e trovare file, identificare e estrarre immagini di file system, codice eseguibile, archivi compressi, bootloader e kernel, formati di file come JPEG e PDF, e molto altro.

Puoi usare binwalk per fare reverse engineering del firmware per capire come è strutturato. Cercare vulnerabilità nei file binari, estrarre file e cercare backdoor o certificati digitali. Puoi anche trovare opcodes per una miriade di CPU diverse.

Puoi estrarre immagini di file system per cercare file specifici di password (passwd, shadow, ecc.) e cercare di rompere gli hash delle password. Puoi eseguire un'analisi binaria tra due o più file. Puoi eseguire un'analisi di entropia dei dati per cercare dati compressi o chiavi di crittografia codificate. Tutto questo senza necessità di accesso al codice sorgente.

Insomma, c'è tutto ciò che serve 🙂

Come funziona binwalk?

La caratteristica principale di binwalk è la sua scansione basata su firme. Binwalk può scansionare un'immagine di firmware per cercare vari tipi di file e file system incorporati.

Conosci l'utilità da riga di comando file?

file /bin/bash
/bin/bash: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=12f73d7a8e226c663034529c8dd20efec22dde54, stripped

Team fileguarda l'intestazione del file e cerca una firma (numero magico) per determinare il tipo di file. Ad esempio, se il file inizia con una sequenza di byte 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A, sa sa che si tratta di un file PNG. Su Wikipedie c'è un elenco delle firme di file più comuni.

Binwalk funziona allo stesso modo. Ma invece di cercare le firme solo all'inizio del file, binwalk scannerà l'intero file. Inoltre, binwalk può estrarre file trovati nell'immagine.

Strumenti file e binwalk usa la libreria libmagic per identificare le firme dei file. Ma binwalk supporta anche un elenco di firme magiche personalizzate per cercare file compressi / archiviati, intestazioni di firmware, kernel Linux, bootloader, file system e così via.

Divertiamoci?

Installazione di binwalk

Binwalk è supportato su diverse piattaforme, tra cui Linux, OSX, FreeBSD e Windows.

Per installare l'ultima versione di binwalk, puoi scaricare il codice sorgente e seguire le istruzioni di installazione o guida rapida, disponibile sul sito del progetto.

Binwalk ha molte opzioni differenti:

$ binwalk

Binwalk v2.2.0
Craig Heffner, ReFirmLabs
https://github.com/ReFirmLabs/binwalk

Uso: binwalk [OPZIONI] [FILE1] [FILE2] [FILE3] ...

Opzioni di scansione delle firme:
    -B, --signature              Scansiona il file di destinazione per firme di file comuni
    -R, --raw=              Scansiona il file di destinazione per la sequenza di byte specificata
    -A, --opcodes                Scansiona il file di destinazione per firme di opcode eseguibili comuni
    -m, --magic=           Specifica un file magico personalizzato da utilizzare
    -b, --dumb                   Disabilita le parole chiave delle firme intelligenti
    -I, --invalid                Mostra risultati contrassegnati come non validi
    -x, --exclude=          Esclude risultati che corrispondono a 
    -y, --include=          Mostra solo i risultati che corrispondono a 

Opzioni di estrazione:
    -e, --extract                Estrae automaticamente tipi di file noti
    -D, --dd=      Estrae firme di , assegna ai file un'estensione di  ed esegue 
    -M, --matryoshka             Scansiona ricorsivamente i file estratti
    -d, --depth=            Limita la profondità di ricorsione matryoshka (default: 8 livelli)
    -C, --directory=        Estrae file/cartelle in una directory personalizzata (default: directory di lavoro corrente)
    -j, --size=             Limita la dimensione di ciascun file estratto
    -n, --count=            Limita il numero di file estratti
    -r, --rm                     Elimina i file ritagliati dopo l'estrazione
    -z, --carve                  Estrae dati dai file, ma non esegue le utilità di estrazione
    -V, --subdirs                Estrae in sottodirectory denominate in base all'offset

Opzioni di entropia:
    -E, --entropy                Calcola l'entropia del file
    -F, --fast                   Usa un'analisi dell'entropia più rapida, ma meno dettagliata
    -J, --save                   Salva il grafico come PNG
    -Q, --nlegend                Om Ramme la legenda dal grafico dell'entropia
    -N, --nplot                  Non genera un grafico dell'entropia
    -H, --high=           Imposta la soglia di attivazione dell'entropia dell'edge ascendente (default: 0.95)
    -L, --low=            Imposta la soglia di attivazione dell'entropia dell'edge discendente (default: 0.85)

Opzioni di differenza binaria:
    -W, --hexdump                Esegue un hexdump / differenza di uno o più file
    -G, --green                  Mostra solo le righe contenenti byte che sono gli stessi tra tutti i file
    -i, --red                    Mostra solo le righe contenenti byte che sono differenti tra tutti i file
    -U, --blue                   Mostra solo le righe contenenti byte che sono differenti tra alcuni file
    -u, --similar                Mostra solo le righe che sono uguali tra tutti i file
    -w, --terse                  Differenza di tutti i file, ma mostra solo un hexdump del primo file

Opzioni di compressione raw:
    -X, --deflate                Scansiona per flussi di compressione raw deflate
    -Z, --lzma                   Scansiona per flussi di compressione raw LZMA
    -P, --partial                Esegue una scansione superficiale, ma più veloce
    -S, --stop                   Si ferma dopo il primo risultato

Opzioni generali:
    -l, --length=           Numero di byte da scansionare
    -o, --offset=           Inizia la scansione a questo offset del file
    -O, --base=             Aggiunge un'indirizzo di base a tutti gli offset stampati
    -K, --block=            Imposta la dimensione del blocco del file
    -g, --swap=             Riserva ogni n byte prima della scansione
    -f, --log=             Registra i risultati su un file
    -c, --csv                    Registra i risultati su un file in formato CSV
    -t, --term                   Format output to fit the terminal window
    -q, --quiet                  Sopprime l'output su stdout
    -v, --verbose                Abilita output dettagliato
    -h, --help                   Mostra output di aiuto
    -a, --finclude=         Scansiona solo file i cui nomi corrispondono a questa regex
    -p, --fexclude=         Non scansionare file i cui nomi corrispondono a questa regex
    -s, --status=           Abilita il server di stato sulla porta specificata

Scansione delle immagini

Iniziamo con la ricerca delle firme dei file all'interno dell'immagine (immagine dal sito TP-Link).

Avviando binwalk con l'opzione —signature:

$ binwalk --signature --term archer-c7.bin

DECIMALI       ESADECIMALE     DESCRIZIONE
------------------------------------------------------------------------------------------
21876         0x5574          Stringa di versione U-Boot, "U-Boot 1.1.4-g4480d5f9-dirty (May
                              20 2019 - 18:45:16)"
21940         0x55B4          Tabella polinomiale CRC32, big endian
23232         0x5AC0          intestazione uImage, dimensione intestazione: 64 byte, CRC intestazione:
                              0x386C2BD5, creata: 2019-05-20 10:45:17, dimensione immagine:
                              41162 byte, Indirizzo dati: 0x80010000, Punto d'ingresso:
                              0x80010000, CRC dati: 0xC9CD1E38, OS: Linux, CPU: MIPS,
                              tipo immagine: Firmware Image, tipo compressione: lzma, nome immagine:
                              "immagine u-boot"
23296         0x5B00          Dati compressi LZMA, proprietà: 0x5D, dimensione dizionario:
                              8388608 byte, dimensione non compressa: 97476 byte
64968         0xFDC8          Documento XML, versione: "1.0"
78448         0x13270         intestazione uImage, dimensione intestazione: 64 byte, CRC intestazione:
                              0x78A267FF, creata: 2019-07-26 07:46:14, dimensione immagine:
                              1088500 byte, Indirizzo dati: 0x80060000, Punto d'ingresso:
                              0x80060000, CRC dati: 0xBB9D4F94, OS: Linux, CPU: MIPS,
                              tipo immagine: Multi-File Image, tipo compressione: lzma,
                              nome immagine: "MIPS OpenWrt Linux-3.3.8"
78520         0x132B8         Dati compressi LZMA, proprietà: 0x6D, dimensione dizionario:
                              8388608 byte, dimensione non compressa: 3164228 byte
1167013       0x11CEA5        filesystem Squashfs, little endian, versione 4.0,
                              compressione:xz, dimensione: 14388306 byte, 2541 inode,
                              dimensione blocco: 65536 byte, creata: 2019-07-26 07:51:38
15555328      0xED5B00        dati compressi gzip, da Unix, ultima modifica: 2019-07-26
                              07:51:41

Ora abbiamo molte informazioni su questa immagine.

L'immagine utilizza U-Boot come bootloader (intestazione dell'immagine all'indirizzo 0x5AC0 e immagine compressa del bootloader all'indirizzo 0x5B00). Basandoci sull'intestazione uImage all'indirizzo 0x13270, sappiamo che l'architettura della CPU è MIPS e che il kernel Linux è versione 3.3.8. E sulla base dell'immagine trovata all'indirizzo 0x11CEA5, possiamo vedere che rootfs è un filesystem squashfs.

Ora estraiamo il bootloader (U-Boot) usando il comando dd:

$ dd if=archer-c7.bin of=u-boot.bin.lzma bs=1 skip=23296 count=41162
41162+0 record in
41162+0 record out
41162 byte (41 kB, 40 KiB) copiati, 0,0939608 s, 438 kB/s

Poiché l'immagine è compressa con LZMA, dobbiamo decomprimerla:

$ unlzma u-boot.bin.lzma

Ora abbiamo l'immagine U-Boot:

$ ls -l u-boot.bin
-rw-rw-r-- 1 sprado sprado 97476 Feb  5 08:48 u-boot.bin

Che ne dite di cercare il valore predefinito per bootargs?

$ strings u-boot.bin | grep bootargs
bootargs
bootargs=console=ttyS0,115200 board=AP152 rootfstype=squashfs init=\/etc\/preinit mtdparts=spi0.0:128k(factory-uboot),192k(u-boot),64k(ART),1536k(uImage),14464k@0x1e0000(rootfs) mem=128M

Variabile d'ambiente U-Boot bootargs viene utilizzato per trasmettere parametri al kernel di Linux. E da quanto sopra, comprendiamo meglio la memoria flash del dispositivo.

Che ne dici di estrarre l'immagine del kernel di Linux?

$ dd if=archer-c7.bin of=uImage bs=1 skip=78448 count=1088572
1088572+0 record in
1088572+0 record out
1088572 bytes (1,1 MB, 1,0 MiB) copiati, 1,68628 s, 646 kB/s

Possiamo verificare che l'immagine sia stata estratta con successo utilizzando il comando file:

$ file uImage
uImage: u-boot legacy uImage, MIPS OpenWrt Linux-3.3.8, Linux/MIPS, Multi-File Image (lzma), 1088500 bytes, Fri Jul 26 07:46:14 2019, Load Address: 0x80060000, Entry Point: 0x80060000, Header CRC: 0x78A267FF, Data CRC: 0xBB9D4F94

Il formato del file uImage è fondamentalmente un'immagine del kernel di Linux con un'intestazione aggiuntiva. Rimuoviamo questa intestazione per ottenere l'immagine finale del kernel di Linux:

$ dd if=uImage of=Image.lzma bs=1 skip=72
1088500+0 record in
1088500+0 record out
1088500 bytes (1,1 MB, 1,0 MiB) copiati, 1,65603 s, 657 kB/s

L'immagine è compressa, quindi scompattiamola:

$ unlzma Image.lzma

Ora abbiamo l'immagine del kernel di Linux:

$ ls -la Image
-rw-rw-r-- 1 sprado sprado 3164228 Feb  5 10:51 Image

Cosa possiamo fare con l'immagine del kernel? Potremmo, ad esempio, cercare le stringhe nell'immagine e trovare la versione del kernel di Linux e scoprire l'ambiente utilizzato per compilare il kernel:

$ strings Image | grep "Linux version"
Linux version 3.3.8 (leo@leo-MS-7529) (gcc version 4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02) ) #1 Mon May 20 18:53:02 CST 2019

Anche se il firmware è stato rilasciato lo scorso anno (2019), mentre scrivo questo articolo, utilizza una vecchia versione del kernel di Linux (3.3.8), rilasciata nel 2012, compilata con una versione di GCC molto vecchia (4.6) anch'essa del 2012!
(nota del traduttore: continui a fidarti dei tuoi router in ufficio e a casa?)

Con l'opzione --opcodes possiamo anche utilizzare binwalk per cercare istruzioni macchina e determinare l'architettura del processore dell'immagine:

$ binwalk --opcodes Image
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
2400          0x960           istruzioni MIPS, epilogo della funzione
2572          0xA0C           istruzioni MIPS, epilogo della funzione
2828          0xB0C           istruzioni MIPS, epilogo della funzione

Che ne dite del filesystem radice? Invece di estrarre manualmente l'immagine, utilizziamo l'opzione binwalk --extract:

$ binwalk --extract --quiet archer-c7.bin

L'intero filesystem radice verrà estratto in una sottocartella:

$ cd _archer-c7.bin.extracted/squashfs-root/

$ ls
bin  dev  etc  lib  mnt  overlay  proc  rom  root  sbin  sys  tmp  usr  var  www

$ cat etc/banner
     MM           NM                    MMMMMMM          M       M
   $MMMMM        MMMMM                MMMMMMMMMMM      MMM     MMM
  MMMMMMMM     MM MMMMM.              MMMMM:MMMMMM:   MMMM   MMMMM
MMMM= MMMMMM  MMM   MMMM       MMMMM   MMMM  MMMMMM   MMMM  MMMMM'
MMMM=  MMMMM MMMM    MM       MMMMM    MMMM    MMMM   MMMMNMMMMM
MMMM=   MMMM  MMMMM          MMMMM     MMMM    MMMM   MMMMMMMM
MMMM=   MMMM   MMMMMM       MMMMM      MMMM    MMMM   MMMMMMMMM
MMMM=   MMMM     MMMMM,    NMMMMMMMM   MMMM    MMMM   MMMMMMMMMMM
MMMM=   MMMM      MMMMMM   MMMMMMMM    MMMM    MMMM   MMMM  MMMMMM
MMMM=   MMMM   MM    MMMM    MMMM      MMMM    MMMM   MMMM    MMMM
MMMM$ ,MMMMM  MMMMM  MMMM    MMM       MMMM   MMMMM   MMMM    MMMM
  MMMMMMM:      MMMMMMM     M         MMMMMMMMMMMM  MMMMMMM MMMMMMM
    MMMMMM       MMMMN     M           MMMMMMMMM      MMMM    MMMM
     MMMM          M                    MMMMMMM        M       M
       M
 ---------------------------------------------------------------
   Per chi sta per rock... (%C, %R)
 ---------------------------------------------------------------

Ora possiamo fare molte cose diverse.

Possiamo cercare file di configurazione, hash delle password, chiavi crittografiche e certificati digitali. Possiamo analizzare file binari per cercare errori e vulnerabilità.

Utilizzando qemu e chroot possiamo persino eseguire (emulare) un file eseguibile dall'immagine:

$ ls
bin  dev  etc  lib  mnt  overlay  proc  rom  root  sbin  sys  tmp  usr  var  www

$ cp /usr/bin/qemu-mips-static .

$ sudo chroot . ./qemu-mips-static bin/busybox
BusyBox v1.19.4 (20-05-2019 18:13:49 CST) binario multi-chiamata.
Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko
e altri. Concesso in licenza sotto GPLv2.
Vedi distribuzione sorgente per nota completa.

Uso: busybox [funzione] [argomenti]...
   o: busybox --list[-full]
   o: funzione [argomenti]...

    BusyBox è un binario multi-chiamata che combina molte comuni
    utilità di Unix in un unico eseguibile. La maggior parte delle persone creerà un
    link a busybox per ogni funzione che desiderano utilizzare e BusyBox
    agirà come qualsiasi cosa venga invocata.

Funzioni attualmente definite:
    [, [[, addgroup, adduser, arping, ash, awk, basename, cat, chgrp, chmod, chown, chroot, clear, cmp, cp, crond, crontab, cut, date, dd, delgroup, deluser, dirname, dmesg, echo, egrep, env, expr, false,
    fgrep, find, free, fsync, grep, gunzip, gzip, halt, head, hexdump, hostid, id, ifconfig, init, insmod, kill, killall, klogd, ln, lock, logger, ls, lsmod, mac_addr, md5sum, mkdir, mkfifo, mknod, mktemp,
    mount, mv, nice, passwd, pgrep, pidof, ping, ping6, pivot_root, poweroff, printf, ps, pwd, readlink, reboot, reset, rm, rmdir, rmmod, route, sed, seq, sh, sleep, sort, start-stop-daemon, strings,
    switch_root, sync, sysctl, tail, tar, tee, telnet, test, tftp, time, top, touch, tr, traceroute, true, udhcpc, umount, uname, uniq, uptime, vconfig, vi, watchdog, wc, wget, which, xargs, yes, zcat

Ottimo! Ma fai attenzione, la versione di BusyBox è 1.19.4. Questa è una versione molto vecchia di BusyBox, rilasciata nell'aprile 2012.

Quindi, TP-Link rilascia un'immagine del firmware nel 2019 utilizzando software (GCC toolchain, kernel, BusyBox, ecc.) del 2012!

Ora capisci perché installo sempre OpenWRT sui miei router?

E non è tutto

Binwalk può anche eseguire un'analisi dell'entropia, stampare dati entropici grezzi e generare grafici dell'entropia. Di solito, una grande entropia è osservata quando i byte nell'immagine sono casuali. Questo può significare che l'immagine contiene un file crittografato, compresso o offuscato. Una chiave di crittografia scritta a mano? Perché no.

Reverse engineering di un router domestico con binwalk. Ti fidi del software del tuo router?

Possiamo anche utilizzare il parametro --raw per cercare una sequenza personalizzata di byte grezzi nell'immagine oppure il parametro --hexdump per eseguire un dump esadecimale che confronta due o più file di input.

Le firme personalizzate possono essere aggiunte a binwalk sia tramite un file di firme personalizzate specificato nella riga di comando con il parametro --magic, oppure aggiungendole nella directory $ HOME / .config / binwalk / magic.

Puoi trovare ulteriori informazioni su binwalk in documentazione ufficiale.

Estensione di binwalk

Esiste API di binwalk, implementata come modulo Python, che può essere utilizzata da qualsiasi script Python per eseguire scansioni binwalk programmaticamente, mentre l'utilità della riga di comando binwalk può essere quasi completamente duplicata con solo due righe di codice Python! import binwalk binwalk.scan()

Utilizzando l'API di Python puoi anche creare

plugin in Python per personalizzare e ampliare binwalk. Esiste anche

un plugin IDA e una versione cloud Binwalk Pro Allora perché non scarichi un'immagine firmware da Internet e provi binwalk? Prometto che ti divertirai un sacco 🙂.

🥇Reverse engineering di un router domestico con binwalk. Ti fidi del software del tuo router? | ProHoster

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster