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

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

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

Ho acquistato 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 preoccupano molto del supporto dei propri router e col passare del tempo il software diventa obsoleto, sorgono vulnerabilità e così via, insomma, avete capito. Per questo motivo preferisco un firmware open-source ben supportato dalla comunità, OpenWRT.

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

Che cos'è binwalk?

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

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

Puoi utilizzare binwalk per il reverse engineering del firmware per capire come è strutturato. Cerca vulnerabilità nei file binari, estrai file e cerca backdoor o certificati digitali. Puoi anche trovare opcodes per diversi CPU.

Puoi decomprimere le immagini del file system per cercare determinati file di password (passwd, shadow, ecc.) e tentare di rompere gli hash delle password. Puoi eseguire un'analisi binaria tra due o più file. Puoi effettuare un'analisi dell'entropia dei dati per cercare dati compressi o chiavi di crittografia codificate. Tutto questo senza la necessità di accedere al codice sorgente.

In generale, tutto il necessario è qui 🙂

Come funziona binwalk?

La caratteristica principale di binwalk è la scansione basata su firme. Binwalk può eseguire la scansione dell'immagine del firmware per cercare diversi tipi di file e file system incorporati.

Conosci l'utilità della 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, per GNU/Linux 3.2.0, BuildID[sha1]=12f73d7a8e226c663034529c8dd20efec22dde54, stripped

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

Binwalk funziona in modo simile. Ma invece di cercare firme solo all'inizio del file, binwalk esaminerà l'intero file. Inoltre, binwalk può estrarre file trovati nell'immagine.

Strumenti file e binwalk utilizza la libreria libmagic per identificare le firme dei file. Ma binwalk supporta anche un elenco di firme magiche personalizzate per la ricerca di file compressi / archivi, intestazioni di firmware, kernel Linux, bootloader, filesystem e altro.

Divertiamoci?

Installazione di binwalk

Binwalk è supportato su più 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 la guida rapida, disponibile sul sito web del progetto.

Binwalk ha molte opzioni diverse:

$ 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/i target per firme di file comuni
    -R, --raw=              Scansiona il file/i target per la sequenza di byte specificata
    -A, --opcodes                Scansiona il file/i target per le firme di opcode eseguibili comuni
    -m, --magic=           Specifica un file magic personalizzato da usare
    -b, --dumb                   Disabilita le parole chiave di firma intelligenti
    -I, --invalid                Mostra i risultati contrassegnati come non validi
    -x, --exclude=          Escludi i risultati che corrispondono a 
    -y, --include=          Mostra solo i risultati che corrispondono a 

Opzioni di estrazione:
    -e, --extract                Estrai automaticamente i tipi di file conosciuti
    -D, --dd=      Estrai le firme , assegna ai file un'estensione di  e esegui 
    -M, --matryoshka             Scansiona ricorsivamente i file estratti
    -d, --depth=            Limita la profondità di ricorsione matryoshka (default: 8 livelli)
    -C, --directory=        Estrai file/cartelle in una directory personalizzata (default: directory di lavoro corrente)
    -j, --size=             Limita la dimensione di ogni file estratto
    -n, --count=            Limita il numero di file estratti
    -r, --rm                     Elimina i file scolpiti dopo l'estrazione
    -z, --carve                  Scolpisci dati dai file, ma non eseguire le utilità di estrazione
    -V, --subdirs                Estrai 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ù veloce, ma meno dettagliata
    -J, --save                   Salva il grafico come PNG
    -Q, --nlegend                Ometti la legenda dal grafico dell'entropia
    -N, --nplot                  Non generare un grafico dell'entropia
    -H, --high=           Imposta la soglia del trigger dell'entropia del bordo ascendente (default: 0.95)
    -L, --low=            Imposta la soglia del trigger dell'entropia del bordo discendente (default: 0.85)

Opzioni di differenziazione binaria:
    -W, --hexdump                Esegui un hexdump / differenza di uno o più file
    -G, --green                  Mostra solo le righe che contengono byte che sono uguali tra tutti i file
    -i, --red                    Mostra solo le righe che contengono byte che sono diversi tra tutti i file
    -U, --blue                   Mostra solo le righe che contengono byte che sono diversi tra alcuni file
    -u, --similar                Mostra solo le righe che sono uguali tra tutti i file
    -w, --terse                  Differenzia tutti i file, ma mostra solo un hexdump del primo file

Opzioni di compressione raw:
    -X, --deflate                Scansiona per flussi di compressione deflate raw
    -Z, --lzma                   Scansiona per flussi di compressione LZMA raw
    -P, --partial                Esegui una scansione superficiale, ma più veloce
    -S, --stop                   Fermati 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=             Aggiungi un indirizzo base a tutti gli offset stampati
    -K, --block=            Imposta la dimensione del blocco del file
    -g, --swap=             Inverti ogni n byte prima della scansione
    -f, --log=             Registra i risultati in un file
    -c, --csv                    Registra i risultati in un file in formato CSV
    -t, --term                   Format output to fit the terminal window
    -q, --quiet                  Suppress output to stdout
    -v, --verbose                Enable verbose output
    -h, --help                   Show help output
    -a, --finclude=         Scansiona solo i file i cui nomi corrispondono a questa regex
    -p, --fexclude=         Non scansionare i file i cui nomi corrispondono a questa regex
    -s, --status=           Abilita il server di stato sulla porta specificata

Scansione delle immagini

Iniziamo a cercare le firme dei file all'interno dell'immagine (immagine dal sito TP-Link).

Esecuzione di binwalk con il parametro —signature:

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

DECIMALE       ESASIMALE     DESCRIZIONE
------------------------------------------------------------------------------------------
21876         0x5574          Stringa di versione U-Boot, "U-Boot 1.1.4-g4480d5f9-dirty (20 Maggio
                              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 Entrata:
                              0x80010000, CRC dati: 0xC9CD1E38, SO: 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 Entrata:
                              0x80060000, CRC dati: 0xBB9D4F94, SO: 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 inodes,
                              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 (header dell'immagine all'indirizzo 0x5AC0 e l'immagine compressa del bootloader all'indirizzo 0x5B00). Basandoci sull'header uImage all'indirizzo 0x13270, sappiamo che l'architettura del processore è MIPS e il kernel Linux è la versione 3.3.8. E basandoci sull'immagine trovata all'indirizzo 0x11CEA5, possiamo vedere che rootfs è il file system 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 estrarla:

$ 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 dici 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

La variabile d'ambiente di U-Boot bootargs è utilizzata per passare parametri al kernel Linux. E da quanto sopra, comprendiamo meglio la memoria flash del dispositivo.

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

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

Possiamo verificare che l'immagine è 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, Ven 26 Lug 07:46:14 2019, Load Address: 0x80060000, Entry Point: 0x80060000, Header CRC: 0x78A267FF, Data CRC: 0xBB9D4F94

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

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

L'immagine è compressa, quindi procediamo a decomprimerla:

$ unlzma Image.lzma

Ora abbiamo l'immagine del kernel 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 per trovare la versione del kernel Linux e informazioni sull'ambiente utilizzato per la compilazione del 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 Lun Mag 20 18:53:02 CST 2019

Nonostante il firmware sia stato rilasciato lo scorso anno (2019), mentre scrivo questo articolo, utilizza una vecchia versione del kernel Linux (3.3.8), rilasciata nel 2012, compilata con una versione molto datata di GCC (4.6) anch'essa del 2012!
(nota del traduttore: continuate a fidarvi dei vostri 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
DECIMALE       ESADECIMALE     DESCRIZIONE
--------------------------------------------------------------------------------
2400          0x960           Istruzioni MIPS, epilogo della funzione
2572          0xA0C           Istruzioni MIPS, epilogo della funzione
2828          0xB0C           Istruzioni MIPS, epilogo della funzione

E per quanto riguarda il filesystem root? Invece di estrarre manualmente l'immagine, utilizziamo l'opzione binwalk --extract:

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

L'intero filesystem root sarà estratto in una sottodirectory:

$ 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
 ---------------------------------------------------------------
   For those about to rock... (%C, %R)
 ---------------------------------------------------------------

Ora possiamo fare molte cose diverse.

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

Con 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 (2019-05-20 18:13:49 CST) multi-call binary.
Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko
and others. Licensed under GPLv2.
See source distribution for full notice.

Usage: busybox [function] [arguments]...
   or: busybox --list[-full]
   or: function [arguments]...

    BusyBox è un binario multi-call che combina molte utilità Unix
    comuni in un unico eseguibile. La maggior parte delle persone creerà un
    collegamento a busybox per ogni funzione che desiderano utilizzare e BusyBox
    si comporterà come qualsiasi altra funzione 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

Ciao! Ma tieni presente che la versione di BusyBox è 1.19.4. Questa è una versione molto vecchia di BusyBox, rilasciata nell'aprile 2012.

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

Ora capisci perché installo sempre OpenWRT sui miei router?

Questo non è tutto

Binwalk può anche eseguire analisi di entropia, stampare dati di entropia grezzi e generare grafici di entropia. Di solito, un'alta entropia si osserva quando i byte nell'immagine sono casuali. Questo può significare che l'immagine contiene file crittografati, compressi o offuscati. Una chiave di crittografia hardcoded? Perché no.

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

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

Signatures personalizzate possono essere aggiunte a binwalk 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 binwalk

Esiste un'API binwalk, implementato come un modulo Python, può essere utilizzato da qualsiasi script Python per eseguire programmaticamente la scansione binwalk; la utility da riga di comando binwalk può essere quasi completamente duplicata con sole due righe di codice Python!

import binwalk
binwalk.scan()

Con l'API Python puoi anche creare plugin in Python per personalizzare ed estendere binwalk.

Esiste anche un plugin IDA e una versione cloud Binwalk Pro..

Allora perché non scaricare un'immagine del firmware da Internet e provare binwalk? Ti prometto che ti divertirai molto 🙂

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