
Amusons-nous en creusant dans le firmware d'un routeur Zyxel et l'architecture MIPS
Les tutoriels sont fournis à titre informatif et éducatif uniquement. Je crois que le hacking éthique, la sécurité de l'information et la cybersécurité devraient être des sujets familiers pour quiconque utilise des informations numériques et des ordinateurs. Je crois qu'il est impossible de se défendre contre les hackers sans savoir comment le hacking est effectué.
$ IDA Pro +7.0 (vous pouvez utiliser Radar2 car IDA est assez cher)
$ Routeur exécutant Rompager 4.07 : il en existe un nombre immense, comme TP-Link TD-W8951*, ZyXEL P-660R, Billion BiPAC 51**/52**
$ UART vers USB
La vulnérabilité Misfortune Cookie existe depuis un certain temps mais il manque encore une analyse publique illustrant les détails techniques de la vulnérabilité. Selon Check Point, le logiciel affecté est le serveur web embarqué RomPager d'AllegroSoft. Des analyses à l'échelle d'Internet suggèrent que RomPager est probablement le logiciel serveur web le plus populaire au monde en termes de nombre de points d'accès disponibles. RomPager est généralement intégré dans le firmware livré avec l'appareil. Cette vulnérabilité spécifique a été introduite dans la base de code en 2002. De plus, les appareils exposés sont ceux utilisant les services RomPager avec des versions antérieures à 4.34 (et plus précisément 4.07).
Pour ce tutoriel, j'utiliserai un ZXHN H108L qui utilise Rompager 4.07
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="ZXHN H108L"
Content-Type: text/html
Transfer-Encoding: chunked
Server: RomPager/4.07 UPnP/1.0
EXT:
Maintenant, utilisons le port série. D'abord, nous devons déterminer le débit en bauds
$ sudo stty -F /dev/ttyUSB0
SORTIE :
speed 115200 baud; line = 0;
-brkint -imaxbel
appareil
J'utilise minicom, vous pouvez utiliser n'importe quoi, de screen à HyperTerminal, mais je préfère celui-ci pour sa stabilité ;)
$ sudo minicom -s
+-----------------------------------------------------------------------+
| A - Périphérique série : /dev/modem |
| B - Emplacement fichier verrou : /var/lock |
| C - Programme d'appel : |
| D - Programme de sortie : |
| E - Bps/Parité/Bits : 115200 8N1 |
| F - Contrôle de flux matériel : Non |
| G - Contrôle de flux logiciel : Non |
| |
| Changer quel paramètre ? |
+-----------------------------------------------------------------------+
| Écran et clavier |
| Sauvegarder la config |
| Sauvegarder sous.. |
| Quitter |
| Quitter Minicom |
+--------------------------+
Maintenant, nous sommes prêts :
$ sudo minicom -D /dev/ttyUSB0 -b 115200
Bootbase Version: VTC_SPI1.26 | 2012/12/26 16:00:00
RAM: Size = 8192 Kbytes
Found SPI Flash 2MiB GD25Q16 at 0xbfc00000
SPI Flash Quad Enable
Turn off Quad Mode
RAS Version: ZXHN H108LV4.0.0a_ZRQ_MA
System ID: $2.12.162.0(G94.BY.2)3.20.19.0| 2014/03/21 20140321_v006 | 2014
Appuyez sur une touche pour entrer en mode debug dans les 3 secondes.
..........
Pour afficher les commandes possibles :
$ ATHE
======= Liste des commandes de debug =======
AT répond juste OK
ATHE affiche l'aide
ATBAx change le débit en bauds. 1:38.4k, 2:19.2k, 3:9.6k 4:57.6k 5:115.2k
ATENx,(y) définit le BootExtension Debug Flag (y=mot de passe)
ATSE affiche la graine du générateur de mot de passe
ATTI(h,m,s) change l'heure système en heure:min:sec ou affiche l'heure actuelle
ATDA(y,m,d) change la date système en année/mois/jour ou affiche la date actuelle
ATDS vide la pile RAS
ATDT vide la zone commune du module de démarrage
ATDUx,y vide le contenu mémoire de l'adresse x pour la longueur y
ATRBx affiche la valeur 8 bits de l'adresse x
ATRWx affiche la valeur 16 bits de l'adresse x
ATRLx affiche la valeur 32 bits de l'adresse x
ATGO(x) exécute le programme à l'adresse x ou démarre le routeur
ATGR démarre le routeur
ATGT exécute le programme de test matériel
ATRTw,x,y(,z) test RAM niveau w, de l'adresse x à y (z itérations)
ATSH vide les données liées au fabricant dans la ROM
ATDOx,y télécharge depuis l'adresse x pour la longueur y vers le PC via XMODEM
ATTD télécharge la configuration du routeur vers le PC via XMODEM
ATUR téléverse le firmware du routeur dans la flash ROM
< appuyez sur une touche pour continuer >
Ce firmware possède un ensemble de commandes cachées très utiles pour notre analyse dynamique. Le problème est que nous ne pouvons pas voir les registres ni définir des points d'arrêt, mais heureusement, avec ces commandes cachées, nous aurons ces fonctionnalités. Pour les voir et les utiliser, nous devons utiliser ATEN. Cependant, cette commande nécessite un mot de passe. Que pouvons-nous faire maintenant ? Analysons le firmware en sens inverse pour trouver l'algorithme du générateur de mot de passe.
(Analyse statique) Regardons d'abord le fichier firmware :
$ binwalk ras
binwalk1
$ dd if=ras of=rom1.lzma bs=1 skip=85043 count=66696
$ dd if=ras of=rom2.lzma bs=1 skip=350259 count=3350556
$ lzma -d <rom1.lzma> rom1
$ lzma -d <rom2.lzma> rom2
Voyons maintenant la signature dans les fichiers extraits :
$ binwalk -Y rom1
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Code exécutable MIPS, 32/64 bits, big endian, au moins 1250 instructions valides
string est un excellent outil pour avoir une idée de ce qu'est un fichier binaire ou de ce qu'il contient. Voyons si nous pouvons trouver l'algorithme du mot de passe :
$ strings rom1 | grep -i aten
$ strings rom2 | grep -i aten
Apparemment, nous ne pouvons pas le voir car le firmware est toujours compressé, ce qui signifie que nous devons le vider du routeur en utilisant le mode de débogage :
$ ATDO bfc00000, 1f0000
xmodem
La première chose qui vient à l'esprit est de commencer à chercher une table de répartition. Pourquoi ? Juste une intuition, la seule alternative est un if-elif mais ce serait un long ensemble de conditions pour vérifier la validité du mot de passe fourni par l'utilisateur, et voici ce que j'ai trouvé :
ROM:800158A0 CmdTable: .word unk_80015C20 # DATA XREF: sub_8000E3D8+4Co
ROM:800158A0 # sub_8000E3D8+90o ...
ROM:800158A4 .word sub_8000E6D0
ROM:800158A8 .byte 0
ROM:800158A9 .byte 0
ROM:800158AA .byte 0
ROM:800158AB .byte 0
ROM:800158AC .word aJustAnswerOk # " just answer OK"
ROM:800158B0 .word aAthe # "ATHE"
ROM:800158B4 .word CMD_SHOW_HELP_ATHE
ROM:800158B8 .byte 0
ROM:800158B9 .byte 0
ROM:800158BA .byte 0
ROM:800158BB .byte 0
ROM:800158BC .word aPrintHelp # " print help"
ROM:800158C0 .word aAtba # "ATBA"
ROM:800158C4 .word CMD_ATBA
...
ROM:800158D0 .word aAten # "ATEN"
ROM:800158D4 .word CMD_ATEN
Gardez à l'esprit qu'un mot MIPS fait 4 octets. Regardons maintenant le CMD_ATEN :
ROM:8000FF84 lw $a0, 8($s0)
ROM:8000FF88 jal sub_80013654
ROM:8000FF8C li $a1, 0
ROM:8000FF90 jal passwd_generator
et maintenant : passwd_generator
ROM:80010A2C passwd_generator: # CODE XREF: CMD_ATEN+50p
ROM:80010A2C lui $t9, 0xA11F
ROM:80010A30 lw $v1, ptrDO_GTABLE
ROM:80010A34 lw $t8, dword_80017050
ROM:80010A38 lw $v1, 0x18($v1) # prend la partie graine, générée par la commande ATSE
ROM:80010A3C lbu $t8, 0x6D($t8) # prend le dernier octet de l'adresse MAC
ROM:80010A40 sll $v1, 8 # $v1 = v1 << 8
ROM:80010A44 andi $t7, $t8, 7 # $t7 = t8 & 0x7
ROM:80010A48 li $t8, 0 # $t8 = 0
ROM:80010A4C srl $v1, 8 # $v1 = v1 >> 8
ROM:80010A50 li $t9, 0xA11F5AC6 # $t9 = MAGIC
ROM:80010A54 j loc_80010A68
ROM:80010A58 addu $t9, $v1, $t9 # $t9 = $v1 + $t9
ROM:80010A5C # ---------------------------------------------------------------------------
ROM:80010A5C
ROM:80010A5C loc_80010A5C: # CODE XREF: passwd_generator+40j
ROM:80010A5C sll $t9, 31 # $t9 = $t9 << 31
ROM:80010A60 or $t9, $t6, $t9 # $t9 = $t6 | $t9
ROM:80010A64 addiu $t8, 1 # $t8 = $t8 + 1
ROM:80010A68
ROM:80010A68 loc_80010A68: # CODE XREF: passwd_generator+28j
ROM:80010A68 sltu $t6, $t8, $t7 # $t6 = (t8 < t7? 1:0)
ROM:80010A6C bnez $t6, loc_80010A5C # prend le saut si $t6 != 0
ROM:80010A70 srl $t6, $t9, 1 # $t6 = $t9 >> 1
ROM:80010A74 jr $ra # tout est fait, sortie
ROM:80010A78 xor $v0, $t9, $v1 # $v0 = $t9 ^ $v1
Ce que nous pouvons conclure :
Créons maintenant un programme C qui fait la même chose et compilons-le :
U32 passwd_generator(U32 seed, U8 last_mac_octet)
{
U32 b = seed & 0x00FFFFFF;
U32 r = ROR(b + 0xA11F5AC6, last_mac_octet & 7);
return r^b;
}
Exécutons maintenant la commande ATSE pour obtenir la graine et l'utiliser (par exemple : j'ai obtenu 088521A78838) :
$ ./gen_pass 088521A78838
Exécutons la commande magique que nous venons de pirater :p
$ ATEN1, A12F5AC6
ATEN1, A12F5AC6
OK
ATHE
======= Liste des commandes de debug =======
AT répond juste OK
ATHE affiche l'aide
ATBAx change le débit en bauds. 1:38.4k, 2:19.2k, 3:9.6k 4:57.6k 5:115.2k
ATENx,(y) définit le BootExtension Debug Flag (y=mot de passe)
ATSE affiche la graine du générateur de mot de passe
ATTI(h,m,s) change l'heure système en heure:min:sec ou affiche l'heure actuelle
ATDA(y,m,d) change la date système en année/mois/jour ou affiche la date actuelle
ATDS vide la pile RAS
ATDT vide la zone commune du module de démarrage
ATDUx,y vide le contenu mémoire de l'adresse x pour la longueur y
ATWBx,y écrit l'adresse x avec la valeur 8 bits y
ATWWx,y écrit l'adresse x avec la valeur 16 bits y
ATWLx,y écrit l'adresse x avec la valeur 32 bits y
ATRBx affiche la valeur 8 bits de l'adresse x
ATRWx affiche la valeur 16 bits de l'adresse x
ATRLx affiche la valeur 32 bits de l'adresse x
ATGO(x) exécute le programme à l'adresse x ou démarre le routeur
ATGR démarre le routeur
ATGT exécute le programme de test matériel
AT%Tx Active le programme de test matériel au démarrage
ATBTx écriture de bloc0 activée (1=activé, autre=désactivé)
< appuyez sur une touche pour continuer >
ATRTw,x,y(,z) test RAM niveau w, de l'adresse x à y (z itérations)
ATWEa(,b,c,d) écrit l'adresse MAC, le code pays, EngDbgFlag, FeatureBit dans la flash ROM
ATCUx écrit le code pays dans la flash ROM
ATCB copie de la flash ROM vers le tampon de travail
ATCL efface le tampon de travail
ATSB sauvegarde le tampon de travail dans la flash ROM
ATBU vide les données liées au fabricant dans le tampon de travail
ATSH vide les données liées au fabricant dans la ROM
ATWMx définit les 6 chiffres bas de l'adresse MAC dans le tampon de travail
ATMHx définit les 6 chiffres hauts de l'adresse MAC dans le tampon de travail
ATBS affiche la graine bootbase du générateur de mot de passe
ATLBx xmodem upload bootbase, x est le mot de passe
ATSMx définit les 6 chiffres de l'adresse MAC dans le tampon de travail
ATCOx définit le code pays dans le tampon de travail
ATFLx définit EngDebugFlag dans le tampon de travail
ATSTx définit l'adresse ROMRAS dans le tampon de travail
ATSYx définit le type de système dans le tampon de travail
ATVDx définit le nom du vendeur dans le tampon de travail
ATPNx définit le nom du produit dans le tampon de travail
ATFEx,y,... définit les bits de fonction dans le tampon de travail
ATMP vérifie et vide memMapTab
ATDOx,y télécharge depuis l'adresse x pour la longueur y vers le PC via XMODEM
< appuyez sur une touche pour continuer >
ATTD télécharge la configuration du routeur vers le PC via XMODEM
ATUPx,y téléverse vers l'adresse RAM x pour la longueur y depuis le PC via XMODEM
ATUR téléverse le firmware du routeur dans la flash ROM
ATDC désactive la vérification de version matérielle pendant le téléversement du firmware
ATLC téléverse le fichier de configuration du routeur dans la flash ROM
ATUXx(,y) xmodem upload depuis le bloc flash x à y
ATERx,y efface la flash ROM du bloc x à y
ATWFx,y,z copie les données de l'adresse x vers l'adresse flash y, longueur z
ATXSx sélection xmodem : x=0 : mode CRC (par défaut); x=1 : mode somme de contrôle
ATLD Téléverse le fichier de configuration et le fichier ROM par défaut dans la Flash
ATBR Réinitialise au fichier Romfile par défaut
ATCD Convertit le fichier ROM en cours en fichier ROM par défaut dans la Flash
OK
Enfin, nous obtenons tout un nouvel ensemble de commandes qui nous permettent de vider la mémoire
$ ATMP
ROMIO image start at bfc30000
code version:
code start: 80008000
code length: 1A5D4E
memMapTab: 18 entries, start = bfc44000, checksum = 9770
$RAM Section:
0: BootExt(RAMBOOT), start=80030000, len=18000
1: HTPCode(RAMCODE), start=80048000, len=E0000
2: RasCode(RAMCODE), start=80048000, len=420000
$ROM Section:
3: BootBas(ROMIMG), start=bfc28000, len=4000
4: DbgArea(ROMIMG), start=bfc2c000, len=2000
5: RomDir2(ROMDIR), start=bfc2e000, len=2000
6: BootExt(ROMIMG), start=bfc30030, len=13FD0
7: MemMapT(ROMMAP), start=bfc44000, len=C00
8: HTPCode(ROMBIN), start=bfc44c00, len=8000
(Compressed)
Version: HTP_TC V 0.05, start: bfc44c30
Length: 10488, Checksum: CB32
Compressed Length: 41CF, Checksum: D5A5
9: termcap(ROMIMG), start=bfc4cc00, len=400
10: RomDefa(ROMIMG), start=bfc4d000, len=2000
11: LedDefi(ROMIMG), start=bfc4f000, len=400
12: LogoImg(ROMIMG), start=bfc4f400, len=2000
13: LogoImg2(ROMIMG), start=bfc51400, len=2000
14: StrImag(ROMIMG), start=bfc53400, len=32000
15: StrImag2(ROMIMG), start=bfc85400, len=32000
16: Rt11nE2p(ROMIMG), start=bfcb7400, len=400
17: RasCode(ROMBIN), start=bfcb7800, len=246C00
(Compressed)
Version: ADSL ATU-R, start: bfcb7830
Length: 321D2C, Checksum: 582D
Compressed Length: 11E54B, Checksum: B30B
$USER Section:
Msecs 128
Heap0 16 300 16
Heap1 32 64 4
Heap2 64 64 4
Heap3 128 160 4
Heap4 192 256 4
Heap5 256 80 4
Heap6 320 20 4
Heap7 384 4 2
Heap8 448 20 2
Heap9 512 34 2
Heap10 1024 52 4
Heap11 2048 20 2
Heap12 3172 4 2
Heap13 4096 2 2
Heap14 0 0
...
Ce que nous venons d'apprendre nous aidera à analyser les fichiers rom que nous avons extraits plus tôt
code start: 80008000
code length: 1A5D4E
Maintenant, nous pouvons définir l'adresse de début ROM et l'adresse de chargement à 0x80008000 après avoir vidé un nouveau fichier rom en utilisant :
$ ATDO 80008000, 1A5D4E
Nous savons que ATGR démarre le routeur, donc ce que nous pourrions faire est de le tracer pour trouver les instructions qui passent l'exécution à la 2ème partie du firmware.
atgr1
ROM:80011E8C loc_80011E8C: # CODE XREF: LoadAndRunImage+D8j
ROM:80011E8C jal sub_80009B24
ROM:80011E90 li $a0, 0x1F4
ROM:80011E94
ROM:80011E94 execute_image: # exécute l'image
ROM:80011E94 jalr $s0 # saut et lien vers l'adresse dans $s0
ROM:80011E98 nop
Maintenant, nous devons demander quelle est l'adresse stockée dans $s0 ? Évidemment, nous ne pouvons toujours pas définir un point d'arrêt, nous ne pouvons pas voir les registres, nous devons donc la divulguer en utilisant une astuce. Heureusement, nous pouvons lire et écrire la mémoire, jetez un œil à la commande suivante :
ATWL 80011E94, ae30001c
ATGR
D'après ce que cela semble être, cette commande patch l'instruction à 0x80011E94 avec ae30001c (la représentation en octets de l'instruction MIPS sw $s0, 0x1C($s1)). En écrasant le jalr $s0 original avec sw $s0, 0x1C($s1), nous avons forcé le programme à stocker le contenu du registre $s0 à l'adresse mémoire 0x8001FF1C. Ainsi, le firmware de la deuxième étape ne sera pas exécuté, à la place le message "ERROR" sera présenté et nous aurons toujours accès à la console de la première étape, Hourra ! Alors, regardons ce qui a été stocké à 0x8001FF1C.
ATRL 8001FF1C
8001FF1C: 80020000
Compris ! ... en utilisant 0x80020000, nous pouvons vider et analyser correctement la 2ème partie du firmware
À suivre ...