วันพุธที่ 15 พฤษภาคม พ.ศ. 2562

การเข้า Serial Console เราเตอร์ D-Link DIR-878

สวัสดีครับ โพสในครั้งนี้ผมจะมาเล่าถึงการเจาะ firmware ของเราเตอร์เพื่อที่จะเข้า shell command ทาง serial port ซึ่งเราเตอร์ทั่วๆ ไปไม่ได้ล็อคการเข้า shell ทาง serial port แต่เราเตอร์ตัวนี้จะเข้าไม่ได้ครับ
ตัวเครื่อง
Serial Port จะอยู่ข้างปุ่มกดด้านหลังเครื่อง

ภายในเครื่อง
 ขา GND ผมต่อกับขาเหล็กของปุ่มเพราะว่าบัดกรีง่ายดีครับ ส่วนขา Rx Tx ก็ต่อตามรูปเลย ใช้ Baudrate 57600
การต่อ Serial Port
พอต่อเสร็จก็เปิดโปรแกรม Terminal ในคอมพิวเตอร์ตั้ง Baudrate เป็น 57600 ได้ผลตามรูปล่างครับ

Serial Console
มันจะขึ้นคำว่า cmd> แต่กดอะไรไปก็ไม่มีผลอะไรตอบกลับมานอกจากคำว่า cmd> เลย
ผมเลยต้องหาวิธีที่จะเข้า shell ให้ได้ ขั้นแรกคือหาก่อนว่าข้อความ 'cmd>' มาจากไหน ผมหาโดยโหลดไฟล์ GPL Source จากเว็บ D-Link

GPL Source
แล้วเข้าไปโฟลเดอร์ romfs แล้วเปิดไฟล์ init โดยโปรแกรม Notepad++ เพื่อใช้ฟังก์ชัน Find in Files

ไฟล์ init
พอเปิด Notepad++ ขึ้นมาก็กดปุ่ม ctrl+shift+F เพื่อเปิดหน้าต่าง Find in Files ในช่อง Find what: ใส่คำที่จะค้นหาซึ่งก็คือคำว่า 'cmd>' ครับ

Find in Files
กดปุ่ม Find All แล้วรอมันค้นหา พอค้นหาเสร็จผลการค้นหาจะอยู่แถบด้านล่างของโปรแกรมครับ จะเจอว่าคำนี้อยู่ในไฟล์ rc ดังนั้นขั้นต่อไปเราก็จะเอาไฟล์ rc มา disasmbly โดยใช้โปรแกรม IDA ครับ

ไฟล์ rc
เปิดโปรแกรม IDA แล้วเลือกไฟล์ rc ตัว IDA ก็จะวิเคราะห์แล้วสร้างแผนผังของโปรแกรม เราก็กด Search Text ใน IDA เพื่อหาส่วนของโปรแกรมที่พ่นคำว่า 'cmd>' ออกมา

ผังโปรแกรม
จากที่ไล่ดูหลังจากที่พ่น 'cmd>' ออกมาตัวโปรแกรมจะเรียกใช่ fgets เพื่ออ่าน input จาก stdin แล้วเอามาตัด \n ออก แล้วเช็ค Input กับค่าในตัวแปล var_11C ด้วยฟังก์ชัน strcmp

ผังโปรแกรมส่วนที่เรียก /bin/sh
 ในส่วนของ var_11C เราก็ต้องไล่ขึ้นไปดูว่าค่าของมันมาจากไหน ซึ่งก็พบว่ามันถูกให้ค่าโดยฟังก์ชัน nvram_safe_get ซึงเป็นฟังก์ชันในการอ่านค่าจาก nvram โดยค่าที่ต้องการอ่านคือ console_pwd
คำสั่งนี้มีค่าเท่ากับการพิมพ์ 'nvram_get 2860 console_pwd'
# nvram_get
Usage:
  nvram_get <command> [<platform>] [<file>]

command:
  rt2860_nvram_show - display rt2860 values in nvram
  rtdev_nvram_show   - display 2nd ralink device values in nvram
  wifi3_nvram_show   - display 3rd ralink device values in nvram
  config2_nvram_show   - display configuration in 2nd nvram
  show    - display values in nvram for <platform>
  gen     - generate config file from nvram for <platform>
  renew   - replace nvram values for <platform> with <file>
  clear   - clear all entries in nvram for <platform>
platform:
  2860    - rt2860
  rtdev    - 2nd ralink device
  wifi3    - 3rd ralink device
  config2    - 2nd nvram
file:
          - file name for renew command
# nvram_get 2860 console_pwd
dlink
#
ค่าของ var_11C
เนื่องจากตอนนี้เรายังเข้า shell ไม่ได้ เราจึงหาวิธีอื่นที่จะอ่านค่า config ของเราเตอร์ ก็พบว่าตัว U-Boot มีคำสั่งที่ไว้อ่านข้อมูลใน spi flash ด้วย
===================================================================
                MT7621   stage1 code 10:33:55 (ASIC)
                CPU=500000000 HZ BUS=166666666 HZ
==================================================================
Change MPLL source from XTAL to CR...
do MEMPLL setting..
MEMPLL Config : 0x11100000
3PLL mode + External loopback
=== XTAL-40Mhz === DDR-1200Mhz ===
PLL4 FB_DL: 0x2, 1/0 = 582/442 09000000
PLL2 FB_DL: 0x8, 1/0 = 609/415 21000000
PLL3 FB_DL: 0x1b, 1/0 = 552/472 6D000000
do DDR setting..[01F40000]
Apply DDR3 Setting...(use customer AC)
          0    8   16   24   32   40   48   56   64   72   80   88   96  104  112  120
      --------------------------------------------------------------------------------
0000:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0001:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0002:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0003:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0004:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0005:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0006:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0007:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0008:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0009:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
000A:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
000B:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
000C:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
000D:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    1    1
000E:|    0    0    0    0    0    0    0    0    1    1    1    1    1    1    1    1
000F:|    0    0    0    1    1    1    1    1    1    1    1    1    1    0    0    0
0010:|    1    1    1    1    1    1    1    1    0    0    0    0    0    0    0    0
0011:|    1    1    1    0    0    0    0    0    0    0    0    0    0    0    0    0
0012:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0013:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0014:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0015:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0016:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0017:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0018:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0019:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
001A:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
001B:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
001C:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
001D:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
001E:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
001F:|    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
rank 0 coarse = 15
rank 0 fine = 64
B:|    0    0    0    0    0    0    0    0    1    1    1    0    0    0    0    0
opt_dle value:9
DRAMC_R0DELDLY[018]=00002021
==================================================================
                RX      DQS perbit delay software calibration
==================================================================
1.0-15 bit dq delay value
==================================================================
bit|     0  1  2  3  4  5  6  7  8  9
--------------------------------------
0 |    9 8 9 11 8 7 10 6 6 8
10 |    7 9 9 11 9 9
--------------------------------------

==================================================================
2.dqs window
x=pass dqs delay value (min~max)center
y=0-7bit DQ of every group
input delay:DQS0 =33 DQS1 = 32
==================================================================
bit     DQS0     bit      DQS1
0  (1~63)32  8  (1~61)31
1  (1~63)32  9  (1~60)30
2  (1~62)31  10  (1~62)31
3  (2~64)33  11  (1~60)30
4  (1~62)31  12  (1~64)32
5  (1~65)33  13  (1~62)31
6  (1~63)32  14  (1~64)32
7  (1~66)33  15  (1~61)31
==================================================================
3.dq delay value last
==================================================================
bit|    0  1  2  3  4  5  6  7  8   9
--------------------------------------
0 |    10 9 11 11 10 7 11 6 7 10
10 |    8 11 9 12 9 10
==================================================================
==================================================================
     TX  perbyte calibration
==================================================================
DQS loop = 15, cmp_err_1 = ffff0000
dqs_perbyte_dly.last_dqsdly_pass[0]=15,  finish count=1
dqs_perbyte_dly.last_dqsdly_pass[1]=15,  finish count=2
DQ loop=15, cmp_err_1 = ffff00a0
dqs_perbyte_dly.last_dqdly_pass[1]=15,  finish count=1
DQ loop=14, cmp_err_1 = ffff0080
DQ loop=13, cmp_err_1 = ffff0000
dqs_perbyte_dly.last_dqdly_pass[0]=13,  finish count=2
byte:0, (DQS,DQ)=(9,8)
byte:1, (DQS,DQ)=(8,8)
20,data:89
[EMI] DRAMC calibration passed

===================================================================
                MT7621   stage1 code done
                CPU=500000000 HZ BUS=166666666 HZ
===================================================================


U-Boot 1.1.3 (Jul 19 2017 - 20:51:21)

Board: Ralink APSoC DRAM:  128 MB
relocate_code Pointer at: 87fb4000

Config XHCI 40M PLL
flash manufacture id: ef, device id 40 18
find flash: W25Q128BV
============================================
Ralink UBoot Version: 5.0.0.0
--------------------------------------------
ASIC MT7621A DualCore (MAC to MT7530 Mode)
DRAM_CONF_FROM: Auto-Detection
DRAM_TYPE: DDR3
DRAM bus: 16 bit
Xtal Mode=3 OCP Ratio=1/3
Flash component: SPI Flash
Date:Jul 19 2017  Time:20:51:21
============================================
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:256, ways:4, linesz:32 ,total:32768

 ##### The CPU freq = 880 MHZ ####
 estimate memory size =128 Mbytes
#Reset_MT7530
set LAN/WAN LLLLW

Please choose the operation:
   1: Load system code to SDRAM via TFTP.
   2: Load system code then write to Flash via TFTP.
   3: Boot system code via Flash (default).
   4: Entr boot command line interface.
   6: System Enter UBoot to Update Img or Bin.
   7: Load Boot Loader code then write to Flash via Serial.
   9: Load Boot Loader code then write to Flash via TFTP.
default: 3

You choosed 4
                                                                                                                                                                                                                                           0


4: System Enter Boot Command Line Interface.

U-Boot 1.1.3 (Jul 19 2017 - 20:51:21)
MT7621 # 4
Unknown command '4' - try 'help'
MT7621 # ?
?       - alias for 'help'
bootm   - boot application image from memory
cp      - memory copy
erase   - erase SPI FLASH memory
go      - start application at address 'addr'
help    - print online help
loadb   - load binary file over serial line (kermit mode)
md      - memory display
mdio   - Ralink PHY register R/W command !!
mm      - memory modify (auto-incrementing)
nm      - memory modify (constant address)
printenv- print environment variables
reset   - Perform RESET of the CPU
rf      - read/write rf register
saveenv - save environment variables to persistent storage
setenv  - set environment variables
spi     - spi command
tftpboot- boot image via network using TFTP protocol
version - print monitor version
MT7621 # spi
Usage:
spi     - spi command

 use "help spi" for detail!
MT7621 # help spi
spi spi usage:
  spi id
  spi sr read
  spi sr write <value>
  spi read <addr> <len>
  spi erase <offs> <len>
  spi write <offs> <hex_str_value>
 แต่ก่อนจะดู config เราก็ต้องรู้ก่อนว่า config มันอยู่ตรงไหนใน flash เราสามารถดู layout ของ mtd partition ได้จาก bootlog ที่ขึ้นตอน boot เราเตอร์
flash manufacture id: ef, device id 40 18
W25Q128BV(ef 40180000) (16384 Kbytes)
mtd .name = raspi, .size = 0x01000000 (16M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
Creating 7 MTD partitions on "raspi":
0x000000000000-0x000001000000 : "ALL"
0x000000000000-0x000000030000 : "Bootloader"
0x000000030000-0x000000040000 : "Config"
0x000000040000-0x000000050000 : "Factory"
0x000000050000-0x000000060000 : "Config2"
0x000000060000-0x000000fb0000 : "Kernel"
0x000000fb0000-0x000001000000 : "Private"

ดูตรงนี้ก็จะรู้ว่า Config อยู่ใน spi flash ในช่วง address 0x30000-0x40000 มีขนาด 0x10000 (64kB) นั่นเอง เมื่อรู้ข้อมูลตรงนี้ก็เอาไปใช้ใน U-Boot ได้เลย
MT7621 # spi read 0x30000 0x10000
ผลลัพธ์ก็จะออกมาเยอะแยะมากมาย
MT7621 # spi read 0x30000 0x10000
read len: 65536
9c 53 41 a9 62 6f 6f 74 63 6d 64 3d 74 66 74 70 0 62 6f 6f 74 64 65 6c 61 79 3d 31 0 62 61 75 64 72 61 74 65 3d 35 37 36 30 30 0 65 74 68 61 64 64 72 3d 22 30 30 3a 41 41 3a 42 42 3a 43 43 3a 44 44 3a 31 30 22 0 69 70 61 64 64 72 3d 31 39 32 2e 31 36 38 2e 30 2e 31 0 73 65 72 76 65 72 69 70 3d 31 39 32 2e 31 36 38 2e 30 2e 31 30 31 0 42 6f 6f 74 54 79 70 65 3d 33 0 69 6e 69 74 3d 2f 62 69 6e 2f 73 68 0 73 74 64 69 6e 3d 73 65 72 69 61 6c 0 73 74 64 6f 75 74 3d 73 65 72 69 61 6c 0 73 74 64 65 72 72 3d 73 65 72 69 61 6c 0 72 64 69 6e 69 74 3d 2f 62 69 6e 2f 73 68 0 0 64 69 6e 3d 73 65 72 69 61 6c 0 73 74 64 6f 75 74 3d 73 65 72 69 61 6c 0 73 74 64 65 72 72 3d 73 65 72 69 61 6c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

ยังมีต่ออีกเยอะ เมื่อเอาค่า Hex ไปแปลงกลับเป็น Text ก็จะได้ประมาณในรูปล่าง เราก็กด ctrl+F เพื่อค้นหา console_pwd 

config partition
เจอแล้ว console_pwd=dlink แปลว่ารหัสเข้า shell command คือ dlink พอลองเอาไปใส่ในบรรทัด 'cmd>' ก็จะทะลุเข้า busybox ได้เลย

ทะลุเข้า busybox

ไม่มีความคิดเห็น:

โพสต์ความคิดเห็น