สวัสดีครับ โพสในครั้งนี้ผมจะมาเล่าถึงการเจาะ 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 |
ไม่มีความคิดเห็น:
แสดงความคิดเห็น