Sploitus

Exploit for MIPS

kitploit · 2026-09-05

Exploit Code

MARKDOWN493 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-DONFANNING-MIPS-CVE-2014-9222
## Отказ от ответственности

Учебные материалы предназначены только для информационных и образовательных целей. Я считаю, что этичный хакинг, информационная безопасность и кибербезопасность должны быть знакомы каждому, кто использует цифровую информацию и компьютеры. Я считаю, что невозможно защититься от хакеров, не зная, как осуществляется взлом.

## Требования

root@kitploit:~
    
    
    $ IDA Pro +7.0 (можно использовать Radar2, так как IDA довольно дорогая)
    $ Маршрутизатор на базе Rompager 4.07: их огромное количество, например TP-Link TD-W8951*, ZyXEL P-660R, Billion BiPAC 51**/52**
    $ UART-USB переходник
    

Уязвимость «Misfortune Cookie» существует уже некоторое время, но до сих пор не хватает публичного анализа, демонстрирующего технические детали уязвимости. Согласно Check Point, уязвимым программным обеспечением является встроенный веб-сервер RomPager от AllegroSoft. Сканирование в масштабах Интернета показывает, что RomPager, вероятно, является самым популярным веб-серверным ПО в мире по количеству доступных конечных точек. RomPager обычно встраивается в прошивку, поставляемую с устройством. Эта конкретная уязвимость была внесена в кодовую базу в 2002 году. Более того, уязвимы устройства, использующие службы RomPager версий до 4.34 (и в частности версии 4.07).

> Для этого руководства я буду использовать ZXHN H108L с Rompager 4.07.

root@kitploit:~
    
    
    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:
    

Теперь воспользуемся последовательным портом; сначала нужно определить скорость передачи (Baud rate):

root@kitploit:~
    
    
    $ sudo stty -F /dev/ttyUSB0
    

> ВЫВОД :

root@kitploit:~
    
    
    speed 115200 baud; line = 0;
    -brkint -imaxbel
    

device

Я использую **minicom** , вы можете использовать что угодно от **screen** до **HyperTerminal** , но я предпочитаю этот из-за её стабильности ;)

### Сначала необходимо отключить **Аппаратное управление потоком** (Hardware Flow Control)

root@kitploit:~
    
    
    $ sudo minicom -s
    

root@kitploit:~
    
    
        +-----------------------------------------------------------------------+
        | A -    Serial Device      : /dev/modem                                |
        | B - Lockfile Location     : /var/lock                                 |
        | C -   Callin Program      :                                           |
        | D -  Callout Program      :                                           |
        | E -    Bps/Par/Bits       : 115200 8N1                                |
        | F - Hardware Flow Control : No                                        |
        | G - Software Flow Control : No                                        |
        |                                                                       |
        |    Change which setting?                                              |
        +-----------------------------------------------------------------------+
                | Screen and keyboard      |
                | Save setup as dfl        |
                | Save setup as..          |
                | Exit                     |
                | Exit from Minicom        |
                +--------------------------+
    

Теперь всё готово:

root@kitploit:~
    
    
    $ sudo minicom -D /dev/ttyUSB0 -b 115200
    

root@kitploit:~
    
    
    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 
    
    Press any key to enter debug mode within 3 seconds.
    ..........
    

Чтобы показать возможные команды:

`$ ATHE`

root@kitploit:~
    
    
    ======= Debug Command Listing =======
    AT          just answer OK
    ATHE          print help
    ATBAx         change baudrate. 1:38.4k, 2:19.2k, 3:9.6k 4:57.6k 5:115.2k
    ATENx,(y)     set BootExtension Debug Flag (y=password)
    ATSE          show the seed of password generator
    ATTI(h,m,s)   change system time to hour:min:sec or show current time
    ATDA(y,m,d)   change system date to year/month/day or show current date
    ATDS          dump RAS stack
    ATDT          dump Boot Module Common Area
    ATDUx,y       dump memory contents from address x for length y
    ATRBx         display the  8-bit value of address x
    ATRWx         display the 16-bit value of address x
    ATRLx         display the 32-bit value of address x
    ATGO(x)       run program at addr x or boot router
    ATGR          boot router
    ATGT          run Hardware Test Program
    ATRTw,x,y(,z) RAM test level w, from address x to y (z iterations)
    ATSH          dump manufacturer related data in ROM
    ATDOx,y       download from address x for length y to PC via XMODEM
    ATTD          download router configuration to PC via XMODEM
    ATUR          upload router firmware to flash ROM
    
    < press any key to continue >
    

Эта прошивка содержит набор скрытых команд, которые очень полезны для нашего динамического анализа. Проблема в том, что мы не можем видеть регистры или устанавливать точки останова, но, к счастью, с помощью этих скрытых команд у нас будут такие возможности. Чтобы увидеть и использовать их, нам нужно использовать **ATEN**. Однако эта команда требует пароль. Что же делать? Давайте реверсим прошивку, чтобы найти алгоритм генератора паролей.

(Статический анализ) Сначала посмотрим на файл прошивки:

root@kitploit:~
    
    
    $ binwalk ras
    

binwalk1

root@kitploit:~
    
    
    $ 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
    

Теперь посмотрим на сигнатуры в извлечённых файлах:

root@kitploit:~
    
    
    $ binwalk -Y rom1
    

root@kitploit:~
    
    
    DECIMAL       HEXADECIMAL     DESCRIPTION
    --------------------------------------------------------------------------------
    0             0x0             MIPS executable code, 32/64-bit, big endian, at least 1250 valid instructions
    

**string** — отличный инструмент, чтобы получить представление о том, чем является бинарный файл или что он содержит. Посмотрим, сможем ли мы найти алгоритм пароля:

root@kitploit:~
    
    
    $ strings rom1 | grep -i aten
    $ strings rom2 | grep -i aten
    

По-видимому, мы не видим его, потому что прошивка всё ещё сжата, что означает, что мы должны сдампить её с маршрутизатора, используя режим отладки:

root@kitploit:~
    
    
    $ ATDO bfc00000, 1f0000
    

xmodem

Первое, что приходит на ум — начать поиск таблицы диспетчеризации. Почему? Просто интуиция; единственная альтернатива — if-elif, но это будет длинный набор проверок на валидность пароля, введённого пользователем. Вот что я получил:

root@kitploit:~
    
    
    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
    

Помните, что слово MIPS — это 4 байта. Теперь посмотрим на **CMD_ATEN** :

root@kitploit:~
    
    
    ROM:8000FF84                 lw      $a0, 8($s0)
    ROM:8000FF88                 jal     sub_80013654
    ROM:8000FF8C                 li      $a1, 0
    ROM:8000FF90                 jal     passwd_generator
    

и теперь: **passwd_generator**

root@kitploit:~
    
    
    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)   # take the seed part, generated by the ATSE command
    ROM:80010A3C                 lbu     $t8, 0x6D($t8)   # take the last byte of the MAC Address
    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    # take jump if $t6 != 0
    ROM:80010A70                 srl     $t6, $t9, 1    # $t6 = $t9 >> 1
    ROM:80010A74                 jr      $ra      # all done, exit
    ROM:80010A78                 xor     $v0, $t9, $v1    # $v0 = $t9 ^ $v1
    

Что мы можем заключить:

  * $v1 — это значение seed (генерируется командой ATSE, ноль, если ATSE не используется)
  * $t8 изначально содержит последний байт MAC-адреса (последний октет)
  * 0xA11F5AC6 — это магическое значение, которое мы искали!
  * Эти две инструкции: "$v1 = v1 << 8" и "$v1 = v1 >> 8" эквивалентны "seed = seed & 0x00FFFFFF"
  * Цикл с последовательностью (sll-or-srl) — это не что иное, как инструкция ROR (инструкция ROR на MIPS является псевдоинструкцией, что означает, что она обычно эмулируется с помощью последовательности sll-or-srl)
  * $v0 — это результат



Теперь напишем программу на C, которая делает то же самое, и скомпилируем её:

root@kitploit:~
    
    
    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;
    }
    

Теперь выполним **ATSE** , чтобы получить seed, и используем его (например, я получил 088521A78838):

root@kitploit:~
    
    
    $ ./gen_pass 088521A78838
    

Выполним магическую команду, которую мы только что взломали :p

root@kitploit:~
    
    
    $ ATEN1, A12F5AC6
    

root@kitploit:~
    
    
    ATEN1, A12F5AC6
    OK
    ATHE
    ======= Debug Command Listing =======
    AT          just answer OK
    ATHE          print help
    ATBAx         change baudrate. 1:38.4k, 2:19.2k, 3:9.6k 4:57.6k 5:115.2k
    ATENx,(y)     set BootExtension Debug Flag (y=password)
    ATSE          show the seed of password generator
    ATTI(h,m,s)   change system time to hour:min:sec or show current time
    ATDA(y,m,d)   change system date to year/month/day or show current date
    ATDS          dump RAS stack
    ATDT          dump Boot Module Common Area
    ATDUx,y       dump memory contents from address x for length y
    ATWBx,y       write address x with  8-bit value y
    ATWWx,y       write address x with 16-bit value y
    ATWLx,y       write address x with 32-bit value y
    ATRBx         display the  8-bit value of address x
    ATRWx         display the 16-bit value of address x
    ATRLx         display the 32-bit value of address x
    ATGO(x)       run program at addr x or boot router
    ATGR          boot router
    ATGT          run Hardware Test Program
    AT%Tx         Enable Hardware Test Program at boot up
    ATBTx         block0 write enable (1=enable, other=disable)
    
    < press any key to continue >
    ATRTw,x,y(,z) RAM test level w, from address x to y (z iterations)
    ATWEa(,b,c,d) write MAC addr, Country code, EngDbgFlag, FeatureBit to flash ROM
    ATCUx         write Country code to flash ROM
    ATCB          copy from FLASH ROM to working buffer
    ATCL          clear working buffer
    ATSB          save working buffer to FLASH ROM
    ATBU          dump manufacturer related data in working buffer
    ATSH          dump manufacturer related data in ROM
    ATWMx         set low 6 digits MAC address in working buffer
    ATMHx         set hight 6 digits MAC address in working buffer
    ATBS          show the bootbase seed of password generator
    ATLBx         xmodem upload bootbase,x is password
    ATSMx         set 6 digits MAC address in working buffer
    ATCOx         set country code in working buffer
    ATFLx         set EngDebugFlag in working buffer
    ATSTx         set ROMRAS address in working buffer
    ATSYx         set system type in working buffer
    ATVDx         set vendor name in working buffer
    ATPNx         set product name in working buffer
    ATFEx,y,...   set feature bits in working buffer
    ATMP          check & dump memMapTab
    ATDOx,y       download from address x for length y to PC via XMODEM
    
    < press any key to continue >
    ATTD          download router configuration to PC via XMODEM
    ATUPx,y       upload to RAM address x for length y from PC via XMODEM
    ATUR          upload router firmware to flash ROM
    ATDC          hardware version check disable during uploading firmware
    ATLC          upload router configuration file to flash ROM
    ATUXx(,y)     xmodem upload from flash block x to y
    ATERx,y       erase flash rom from block x to y
    ATWFx,y,z     copy data from addr x to flash addr y, length z
    ATXSx         xmodem select: x=0: CRC mode(default); x=1: checksum mode
    ATLD          Upload Configuration File and Default ROM File to Flash
    ATBR              Reset to default Romfile
    ATCD          Convert Running ROM File to Default ROM File into Flash
    
    OK
    

Наконец, мы получили целый новый набор команд, которые позволяют нам сдампить память

root@kitploit:~
    
    
    $ ATMP
    

root@kitploit:~
    
    
    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
    ...
    

То, что мы только что узнали, поможет нам анализировать файлы ROM, которые мы извлекли ранее.

root@kitploit:~
    
    
    code start: 80008000
    code length: 1A5D4E
    

Теперь мы можем установить **Начальный адрес ROM** и **Адрес загрузки** в **0x80008000** после сброса нового ROM-файла с помощью:

root@kitploit:~
    
    
    $ ATDO 80008000, 1A5D4E
    

Мы знаем, что **ATGR** загружает маршрутизатор, поэтому мы могли бы отследить его, чтобы найти инструкции, передающие выполнение второй части прошивки.

atgr1

root@kitploit:~
    
    
    ROM:80011E8C loc_80011E8C:            # CODE XREF: LoadAndRunImage+D8j
    ROM:80011E8C                 jal     sub_80009B24
    ROM:80011E90                 li      $a0, 0x1F4
    ROM:80011E94
    ROM:80011E94 execute_image:           # execute image
    ROM:80011E94                 jalr    $s0        # jump and link to address in $s0
    ROM:80011E98                 nop
    

Теперь нужно спросить: какой адрес хранится в $s0? Очевидно, мы всё ещё не можем установить точку останова, мы не можем видеть регистры, поэтому нужно утечь его с помощью некоторой хитрости. К счастью, мы можем читать и писать память. Взгляните на следующую команду:

root@kitploit:~
    
    
    ATWL 80011E94, ae30001c
    ATGR
    

Судя по всему, эта команда заменяет инструкцию по адресу **0x80011E94** на **ae30001c** (байтовое представление инструкции MIPS **sw $s0, 0x1C($s1)**). Перезаписывая оригинальную инструкцию **jalr $s0** на **sw $s0, 0x1C($s1)** , мы заставили программу сохранить содержимое регистра **$s0** по адресу памяти **0x8001FF1C**. Таким образом, вторая часть прошивки не будет выполнена; вместо этого появится сообщение "ERROR", и у нас всё ещё будет доступ к консоли первой стадии. Ура! Итак, давайте посмотрим, что было сохранено по адресу **0x8001FF1C**.

root@kitploit:~
    
    
    ATRL 8001FF1C
    8001FF1C: 80020000
    

Попались! ... используя **0x80020000** , мы можем сбросить и должным образом проанализировать вторую часть прошивки.

Продолжение следует ...