Gorgias
固件提取系列-使用FlashROM读取Flash
固件提取系列-UBI文件系统提取以及重打包
固件提取系列 固件载体
固件 (Firmware), 在港澳台称作韧体, 在手机领域又称作字库。它位于非易失性存储(Non-Volatile Memory,NVM)中,可以被读写。在嵌入式领域,最常见的NVM类型是ROM(read-only memory)和Flash Memory, 其中ROM包括Mask ROM、PROM、EPROM、EEPROM;现在主流的ROM就是EEPROM,一般是在MCU内部;而更加主流的外存一般都是Flash Memory。
在嵌入式设备中,除了使用最基本的NAND或者NOR Flash芯片,还可能会使用eMMC;扩展存储会用到SD卡,CF卡,HDD等;这些都是有一个主控再加一个存储区,主控和上位机通信,只要能访问主控,就能读写存储芯片的内容。对于eMMC、SD卡、CF卡、HDD之类的设备,它的主控对外有通用的接口,只要用读卡器或者烧录座就可以读取。但是对于SoC直接管理的存储芯片,并没有对外部的通用接口,但是主控都是驱动控制的,所以只要能访问内存(外围设备的地址)就行了,因此有一些JTAG读固件、IAP读取固件、U-Boot读取固件的技巧,是而且理论上主控坏了,我们还能从存储区读取出固件。
只要是这些设备存放了操作系统,我把这原始的文件都称作固件。在嵌入式安全研究中,固件提取总是最初的工作,也是最重要的工作,决定了研究是否能继续下去。因此我决定整理这几年关于固件提取的知识分享出来。
EEPROM vs NOR vs NAND-Flash由于EEPROM产品比Flash产品在擦写次数上有着更大的优势,再加上更小的尺寸和较低的擦写电流,因此成为车载应用中首选的存储技术。
但是对于性能较高的设备,就要用到Flash。NAND对比NOR,支持XIP,而且读取速度很快,但是写入和擦除速度很慢。NAND 的容量要大很多,速度快,价格也相对便宜,但是可靠性较低。 NAND以块为单位来访问数据,而NOR Flash可以随机访问数据。
要与固件载体通信,修改里面的数据,就要有相应的协议。对于EEPROM,协议主要有I2C, SPI,其中SPI有多种模式。而NAND Flash使用的是Raw NAND协议,现在几乎都遵循ONFI标准。对于NOR Flash一般有SPI协议;SPI的Flash一般遵循JEDEC SFDP(JESD216)标准,而Parallel NOR支持JEDEC CFI(JESD68)标准。
JEDEC:全称是Joint Electron Device Engineering Council 即电子元件工业联合会。JEDEC是由生产厂商们制定的国际性协议,JEDEC用来帮助程序读取Flash的制造商ID和设备ID,以确定Flash的大小和算法。
注意:不一定所有芯片都遵循这些标准。
NOR PackageNOR Flash 有并行和串行两种,串行一般是SOP封装,使用SPI协议。并行只有极少数BGA封装,一般是TSOP封装,TSOP-56, TFBGA-56, LFBGA-64。
NOR Flash Pin AssignmentNOR Flash支持随机访问,因此擦除单位是Byte。这里指的是并行信号引脚,NOR的信号线和SRAM基本上是一样的。如果飞线会特别麻烦。
Symbol Pin Name Functions A[MAX:0] Address 读写操作发送的地址数据 DQ[7:0] Data Inputs/Outputs 用于输入输出命令和数据。 DQ[14:8] Data Inputs/Outputs 用于输入输出命令和数据。 DQ15/A-1 Data Inputs/Outputs 数据或地址输入 BYTE# Byte/word organization select 选择8位或者16位 CE# Chip Enable 芯片使能 RE# Read Enable 读使能,数据在RE#脉冲的下降沿生效。 OE# Output Enable 输出使能,当OE#是LOW时,读取周期会输出数据。当OE#是HIGH时,数据输出将处于高阻状态 WE# Write Enable 写使能 WP# Write Protect 提供意外情况的读、擦除保护,当WP#是低电平时,其他操作将无法进行。 RST# Reset RY/BY# Read / Busy Output 如果处于编程、擦除或随机写入操作,R/B#信号将变低,当操作完成时会变回高电平。如果芯片未被选中或输出被禁用时,该信号是漏极开路并处于高阻状态,需要采用上拉电阻。 Vcc Power 3.3V或1.8V常电 Vss Ground 接地 NC No Connection 无连接TSOP-56
NAND FlashNAND Flash属于非易失性存储器,对于嵌入式设备,一般使用SLC,单位是1-bit,是一种浮栅结构,可以捕获电子并且外部绝缘,断电之后可以保留数据。Flash都不支持覆盖,即写入操作只能在空或已擦除的单元内进行。
擦除方法是在源极加正电压利用第一级浮空栅与漏极之间的隧道效应,将注入到浮空栅的负电荷吸引到源极。由于利用源极加正电压擦除,因此各单元的源极联在一起,这样,擦除不能按字节擦除,而是全片或者分块擦除。
NAND PackageONFI标准定义了一些常用的NAND封装,NAND Flash一般是TSOP和BGA的封装,都使用SMT的贴装方式。下图是不同封装的引脚定义。
TSOP-48
BGA-63
NAND Flash Pin AssignmentNAND Flash并行输入输出,一般是8位I/O,也就是x8。图中具有上划线的引脚(在这里使用"#“号表示),是低电平有效,该引脚默认应该是上拉的状态。
Symbol Pin Name Functions I/O x Data Inputs/Outputs 用于输入输出命令、地址和数据。如果芯片未被选中或输出被禁用时,I/O口将处于高阻状态。 CLE Command Latch Enable 指令锁存使能,当CLE为高时,在WE#脉冲的上升沿,指令被锁存到NAND指令寄存器中 ALE Address Latch Enable 地址锁存使能,当ALE为高时,在WE#脉冲的上升沿,地址被锁存到NAND地址寄存器中。 CE# Chip Enable 芯片使能,如果没有检测到CE信号,那么,NAND器件就保持待机模式,不对任何控制信号作出响应。 RE# Read Enable 读使能,数据在RE#脉冲的下降沿生效。 WE# Write Enable 写使能,WE#负责将数据、地址或指令写入NAND之中。这些操作将在WE#脉冲上升沿生效。 WP# Write Protect 提供意外情况的读、擦除保护,当WP#是低电平时,其他操作将无法进行。 R/B# Read / Busy Output 如果NAND处于编程、擦除或随机写入操作,R/B#信号将变低,当操作完成时会变回高电平。如果芯片未被选中或输出被禁用时,该信号是漏极开路并处于高阻状态,需要采用上拉电阻。 Vcc Power 3.3V或1.8V常电 Vss Ground 接地 NC No Connection 无连接 Array OrganizationESMT厂商的某款8位NAND的阵列组织如下,一页有2048存储+64Cache字节,一个块含有64个页,该NAND Flash有1024个块,加上Cache就是1056M-bit。也就是128MB容量+4MB的缓存。
固件读取的工具这里说的是非扩展存储。固件提取按照读取方式,分为下列几种:脱机读取(Chip-Off),在线读取,内部备份。
内部备份,指拿到了设备权限,从块设备备份数据,或者从I2C、SPI驱动接口读取数据。
在线读取,指在设备上外接工具、使用设备主芯片特有的调试接口,或者是存储芯片的通用接口读取数据。一般准备USB线束,或者使用JLink,USBDM之类的调试工具(也有很多冷门芯片需要特殊调试工具),属于IAP方式提取固件。
脱机读取,把目标存储芯片拆下,使用烧录座和编程器读取。该方式读取成本较高,而且编程器和与芯片相配的主控不一定兼容,因此还要手动修复固件。
在了解了芯片的标准和通信协议后,对于一些冷门的存储芯片,其实可以不依赖编程器。使用STM32、AVR或者树莓派都能完成固件提取工作。
嵌入式设备的应用NOR Flash和普通的内存比较像的一点是他们都可以支持随机访问,这使它也具有支持片内执行(XIP, eXecute In Place)的特性,可以像普通ROM一样执行程序。这点让它成为BIOS等开机就要执行的代码的绝佳载体。
与NOR Flash不同的是,NAND不支持XIP,因此不能存放最开始的Bootloader。
最早的手机等设备之中既有NOR Flash也有NAND Flash。NOR Flash很小,因为支持XIP,所以负责初始化系统并提供NAND Flash的驱动,类似Bootloader。而NAND Flash则存储数据和OS镜像。三星最早提出NOR less的概念,在它的CPU on die ROM中固化了NAND Flash的驱动,会把NAND flash的开始一小段拷贝到内存低端作为bootloader,这样昂贵的NOR Flash就被节省下来了,降低了手机主板成本和复杂度。渐渐NOR Flash在手机中慢慢消失了。
NAND Flash相对NOR Flash更可能发生比特翻转,就必须采用错误探测/错误更正(EDC/ECC)算法,同时NAND Flash随着使用会渐渐产生坏块;通常需要有一个特殊的软件层,实现坏块管理、擦写均衡、ECC、垃圾回收等的功能,这一个软件层称为 FTL(Flash Translation Layer)。根据 FTL 所在的位置的不同,可以把 Flash Memory 分为 Raw Flash 和 Managed Flash 两类:
最早大家都是使用Raw Flash,FTL全由驱动程序实现。后来发展到SD和eMMC等,则由硬主控实现。
因此要读取原始NAND,还要考虑坏块管理,擦写平衡,ECC等功能。
其中ECC是最难的地方,因为从编程器读取NAND很大可能会出现错误,需要纠错。大部分NAND Flash使用了硬件ECC,算法由硬件决定,对于SLC颗粒,一般使用hanming,BCH之类的算法,这些实现在网上都没有标准的源码,因此需要特殊途径搞到ECC算法。
根据存储芯片应用特性,可以推断出它的用途是存放Bootloader,是系统,还是临时数据。根据芯片支持的规范,可以读取其中的内容。 后续会分享一系列进阶的固件提取知识。
ReferenceNAND vs. NOR Flash Memory Technology Overview
Understanding Flash: Blocks, Pages and Program / Erases
UEFI Blog 杂谈闪存二:NOR和NAND Flash
固件提取系列 UBI文件系统提取以及重打包
去年写的,不小心把github仓库弄成私有,Readme没了,重新传了个Readme,觉得有点不好意思。先把这篇文章放出来吧
UBI(Unsorted Block Images)全称未分类块镜像。由IBM公司设计,是一个基于Raw Flash设备的卷管理系统,可以在单个物理设备上管理多个逻辑卷,并且支持耗损均衡(wear-leveling)。广泛应用于嵌入式设备。
提到Raw Flash,就要解释一下什么是MTD(Memory Technology Device)。MTD是用于访问Memory设备(尤其是Flash设备)的一个Linux子系统,作为硬件和文件系统之间的抽象层。以NAND Flash为例,MTD对NAND flash封装,为上层文件系统驱动提供抽象接口。MTD设备由擦除块(Eraseblocks)组成,MTD驱动提供了读写和擦除三种操作,但是在修改每个块之前都要先擦除。
UBI结构UBI有点像LVM(Logical Volume Management),LVM提供逻辑扇区到物理扇区的映射,而UBI提供逻辑擦除块(LEB)到物理擦除块(PEB)的映射。从上述可知,UBI是以块为单位操作的。
在每个UBI块(非坏块)的头部,有两个长度为64字节的头信息。
- EC header(erase counter header),包含了每个PEB的信息(VID的偏移,数据的偏移)。
- VID Header(volume identifier header),包含了卷ID和LEB对应PEB的编号。
在Linux源码/linux/drivers/mtd/ubi目录,ubi-media.h内,有EC header和VID header的定义。
struct ubi_ec_hdr { __be32 magic; // UBI# __u8 version; // 01 __u8 padding1[3]; __be64 ec; /* Warning: the current limit is 31-bit anyway! */ __be32 vid_hdr_offset; // VID Header 的偏移 __be32 data_offset; // 数据的偏移 __be32 image_seq; // 物理块序号 __u8 padding2[32]; __be32 hdr_crc; // CRC32 } __packed; /* * UBI volume type constants. * * @UBI_DYNAMIC_VOLUME: dynamic volume * @UBI_STATIC_VOLUME: static volume */ enum { UBI_DYNAMIC_VOLUME = 3, UBI_STATIC_VOLUME = 4, }; struct ubi_vid_hdr { __be32 magic; // UBI! __u8 version; // 1 __u8 vol_type; // 一般是UBI_DYNAMIC_VOLUME __u8 copy_flag; // 是否从另一个物理块拷贝过来的(wear-leveling) __u8 compat; // 卷兼容性 __be32 vol_id; // 卷ID __be32 lnum; // LEB编号 __u8 padding1[4]; __be32 data_size; // 数据大小 __be32 used_ebs; // 用户LEB数量 __be32 data_pad; __be32 data_crc; __u8 padding2[4]; __be64 sqnum; // 序号 __u8 padding3[12]; __be32 hdr_crc; // CRC32 } __packed;ID为UBI_INTERNAL_VOL_START的卷,专门用来存放分卷表的记录。
#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)其中包含卷名
struct ubi_vtbl_record { __be32 reserved_pebs; __be32 alignment; __be32 data_pad; __u8 vol_type; __u8 upd_marker; __be16 name_len; // 卷名长度 __u8 name[UBI_VOL_NAME_MAX+1]; // 卷名 __u8 flags; __u8 padding[23]; __be32 crc; // CRC32 } __packed;一个MTD设备前面的部分一般用于存放Bootloader,后面用于UBI。下图只是一个简单的举例,实际情况可能是多个UBI和其他分区间接排列。UBI使用fastmap将LEB到映射到乱序的PEB,为UBIFS提供抽象接口。
挂载UBIFSMTD为提供了直接操作UBI的工具:MTD-Utils
http://git.infradead.org/mtd-utils.git
- ubinfo - provides information about UBI devices and volumes found in the system;
- ubiattach - attaches MTD devices (which describe raw flash) to UBI and creates corresponding UBI devices;
- ubidetach - detaches MTD devices from UBI devices (the opposite to what ubiattach does);
- ubimkvol - creates UBI volumes on UBI devices;
- ubirmvol - removes UBI volumes from UBI devices;
- ubiblock - manages block interfaces for UBI volumes. See here for more information;
- ubiupdatevol - updates UBI volumes; this tool uses the UBI volume update feature which leaves the volume in “corrupted” state if the update was interrupted; additionally, this tool may be used to wipe out UBI volumes;
- ubicrc32 - calculates CRC-32 checksum of a file with the same initial seed as UBI would use;
- ubinize - generates UBI images;
- ubiformat - formats empty flash, erases flash and preserves erase counters, flashes UBI images to MTD devices;
- mtdinfo - reports information about MTD devices found in the system.
上面的工具只能操作UBI,而一般电脑上没有MTD设备。当从嵌入式设备提取了原始的Flash固件,想要在电脑上读取,可以使用来模拟一个MTD设备。一般情况下,会使用到NANDSim。
- mtdram which simulates NOR flash in RAM;
- nandsim which simulates NAND flash in RAM;
- block2mtd which simulates NOR flash on top of a block device;
首先看NANDSim的参数,一大堆参数该如何配置呢?
$ modinfo nandsim filename: /lib/modules/4.18.10-arch1-1-ARCH/kernel/drivers/mtd/nand/raw/nandsim.ko.xz description: The NAND flash simulator author: Artem B. Bityuckiy license: GPL srcversion: D2FD00330F9BE30A9B28365 depends: mtd,nand retpoline: Y intree: Y name: nandsim vermagic: 4.18.10-arch1-1-ARCH SMP preempt mod_unload modversions sig_id: PKCS#7 signer: sig_key: sig_hashalgo: md4 signature: parm: id_bytes:The ID bytes returned by NAND Flash 'read ID' command (array of byte) parm: first_id_byte:The first byte returned by NAND Flash 'read ID' command (manufacturer ID) (obsolete) (byte) parm: second_id_byte:The second byte returned by NAND Flash 'read ID' command (chip ID) (obsolete) (byte) parm: third_id_byte:The third byte returned by NAND Flash 'read ID' command (obsolete) (byte) parm: fourth_id_byte:The fourth byte returned by NAND Flash 'read ID' command (obsolete) (byte) parm: access_delay:Initial page access delay (microseconds) (uint) parm: programm_delay:Page programm delay (microseconds (uint) parm: erase_delay:Sector erase delay (milliseconds) (uint) parm: output_cycle:Word output (from flash) time (nanoseconds) (uint) parm: input_cycle:Word input (to flash) time (nanoseconds) (uint) parm: bus_width:Chip's bus width (8- or 16-bit) (uint) parm: do_delays:Simulate NAND delays using busy-waits if not zero (uint) parm: log:Perform logging if not zero (uint) parm: dbg:Output debug information if not zero (uint) parm: parts:Partition sizes (in erase blocks) separated by commas (array of ulong) parm: badblocks:Erase blocks that are initially marked bad, separated by commas (charp) parm: weakblocks:Weak erase blocks [: remaining erase cycles (defaults to 3)] separated by commas e.g. 113:2 means eb 113 can be erased only twice before failing (charp) parm: weakpages:Weak pages [: maximum writes (defaults to 3)] separated by commas e.g. 1401:2 means page 1401 can be written only twice before failing (charp) parm: bitflips:Maximum number of random bit flips per page (zero by default) (uint) parm: gravepages:Pages that lose data [: maximum reads (defaults to 3)] separated by commas e.g. 1401:2 means page 1401 can be read only twice before failing (charp) parm: overridesize:Specifies the NAND Flash size overriding the ID bytes. The size is specified in erase blocks and as the exponent of a power of two e.g. 5 means a size of 32 erase blocks (uint) parm: cache_file:File to use to cache nand pages instead of memory (charp) parm: bbt:0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in data area (uint) parm: bch:Enable BCH ecc and set how many bits should be correctable in 512-byte blocks (uint)可以去阅读内核驱动源码来了解NANDSim的实现,这里简单说明一下。首先由nandsim.c 调用nand_base.c中的nand_scan_ident,在nand_detect中会进行Read ID操作,nand_readid_op对NAND发送0x90,0x00。随后在nand_get_manufacturer,匹配厂商ID,最后在nand_scan_tail中初始化NAND芯片,设置各项属性。
NANDFlash的芯片手册会表明ID的具体参数
所以我们需要将ID设定正确,驱动会根据ID自动设置容量,页大小等数据。在NANDSim的参数只需要前四项。
static u_char id_bytes[8] = { [0] = CONFIG_NANDSIM_FIRST_ID_BYTE, [1] = CONFIG_NANDSIM_SECOND_ID_BYTE, [2] = CONFIG_NANDSIM_THIRD_ID_BYTE, [3] = CONFIG_NANDSIM_FOURTH_ID_BYTE, [4 ... 7] = 0xFF, };如果需要调整模拟NAND的参数,可以根据芯片手册上的数据表来选择。
一般情况下,嵌入式设备的bootloader等其他分区都会和系统分区放在同一个芯片内。因此需要对NANDSim分区,该芯片的eraseblocks以128KB为单位,也就是0x20000。
写一个脚本来寻找UBI的分布
#!/usr/bin/env python3 import sys import binascii import struct if len(sys.argv) < 1: print("Usage: find_ubi_header.py NAND.bin") sys.exit(1) raw_file_path = sys.argv[1] ubi_header = b'UBI#' out_of_ubi = True try: with open(raw_file_path, 'rb') as raw_file: rawbin = raw_file.read() for x in range(0, len(rawbin), 0x20000): magic = rawbin[x:x+4] if magic == ubi_header: if out_of_ubi: out_of_ubi = False print("\nUBI offset start:", hex(x)) else: if not out_of_ubi: print("UBI offset stop:", hex(x), "\n") out_of_ubi = True raw_file.close() except Exception as e: print(e) $ python find_ubi_header.py NAND.bin UBI offset start: 0x2e60000 UBI offset stop: 0x6900000 UBI offset start: 0x7700000 UBI offset stop: 0x81c0000 UBI offset start: 0x8200000 UBI offset stop: 0x20000000512MB = 4096 * 128 KB,该芯片有4K个块。
PN SA EA EC xxx 0x00000000 0x02E60000 371 ubi1 0x02E60000 0x06900000 469 foo 0x06900000 0x069C0000 6 recovery 0x069C0000 0x07700000 106 ubi2 0x07700000 0x081C0000 86 sec 0x081C0000 0x08200000 2 ubi3 0x08200000 0x20000000 3056加载MTD模块和NANDSim模块
sudo modprobe mtd sudo modprobe mtdblock sudo modprobe nandsim first_id_byte=0x2c second_id_byte=0xac third_id_byte=0x90 fourth_id_byte=0x15 parts=371,469,6,106,86,2,3056查看MTD设备的信息,可以看到分区已经创建成功。
$ mtdinfo -a Count of MTD devices: 8 Present MTD devices: mtd0, mtd1, mtd2, mtd3, mtd4, mtd5, mtd6, mtd7 Sysfs interface supported: yes mtd0 Name: NAND 512MiB 1,8V 8-bit Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 4096 (536870912 bytes, 512.0 MiB) Minimum input/output unit size: 2048 bytes Sub-page size: 512 bytes OOB size: 64 bytes Character device major/minor: 90:0 Bad blocks are allowed: true Device is writable: true mtd1 Name: NAND simulator partition 0 Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 371 (48627712 bytes, 46.4 MiB) Minimum input/output unit size: 2048 bytes Sub-page size: 512 bytes OOB size: 64 bytes Character device major/minor: 90:2 Bad blocks are allowed: true Device is writable: true mtd2 Name: NAND simulator partition 1 Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 469 (61472768 bytes, 58.6 MiB) Minimum input/output unit size: 2048 bytes Sub-page size: 512 bytes OOB size: 64 bytes Character device major/minor: 90:4 Bad blocks are allowed: true Device is writable: true mtd3 Name: NAND simulator partition 2 Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 6 (786432 bytes, 768.0 KiB) Minimum input/output unit size: 2048 bytes Sub-page size: 512 bytes OOB size: 64 bytes Character device major/minor: 90:6 Bad blocks are allowed: true Device is writable: true mtd4 Name: NAND simulator partition 3 Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 106 (13893632 bytes, 13.2 MiB) Minimum input/output unit size: 2048 bytes Sub-page size: 512 bytes OOB size: 64 bytes Character device major/minor: 90:8 Bad blocks are allowed: true Device is writable: true mtd5 Name: NAND simulator partition 4 Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 86 (11272192 bytes, 10.8 MiB) Minimum input/output unit size: 2048 bytes Sub-page size: 512 bytes OOB size: 64 bytes Character device major/minor: 90:10 Bad blocks are allowed: true Device is writable: true mtd6 Name: NAND simulator partition 5 Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 2 (262144 bytes, 256.0 KiB) Minimum input/output unit size: 2048 bytes Sub-page size: 512 bytes OOB size: 64 bytes Character device major/minor: 90:12 Bad blocks are allowed: true Device is writable: true mtd7 Name: NAND simulator partition 6 Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 3056 (400556032 bytes, 382.0 MiB) Minimum input/output unit size: 2048 bytes Sub-page size: 512 bytes OOB size: 64 bytes Character device major/minor: 90:14 Bad blocks are allowed: true Device is writable: true通过dmesg可以看到加载的具体信息,包括芯片信息和分区信息。
$ dmesg [13202.334289] nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xac [13202.334290] nand: Micron NAND 512MiB 1,8V 8-bit [13202.334291] nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 [13202.334299] flash size: 512 MiB [13202.334299] page size: 2048 bytes [13202.334300] OOB area size: 64 bytes [13202.334300] sector size: 128 KiB [13202.334301] pages number: 262144 [13202.334301] pages per sector: 64 [13202.334302] bus width: 8 [13202.334302] bits in sector size: 17 [13202.334302] bits in page size: 11 [13202.334303] bits in OOB size: 6 [13202.334304] flash size with OOB: 540672 KiB [13202.334304] page address bytes: 5 [13202.334304] sector address bytes: 3 [13202.334305] options: 0x8 [13202.334779] Scanning device for bad blocks [13202.358806] Creating 7 MTD partitions on "NAND 512MiB 1,8V 8-bit": [13202.358810] 0x000000000000-0x000002e60000 : "NAND simulator partition 0" [13202.360129] 0x000002e60000-0x000006900000 : "NAND simulator partition 1" [13202.360835] 0x000006900000-0x0000069c0000 : "NAND simulator partition 2" [13202.361180] 0x0000069c0000-0x000007700000 : "NAND simulator partition 3" [13202.363506] 0x000007700000-0x0000081c0000 : "NAND simulator partition 4" [13202.365146] 0x0000081c0000-0x000008200000 : "NAND simulator partition 5" [13202.366440] 0x000008200000-0x000020000000 : "NAND simulator partition 6"也可以通过下面的命令查看MTD分区表
$ sudo cat /proc/mtd dev: size erasesize name mtd0: 20000000 00020000 "NAND 512MiB 1,8V 8-bit" mtd1: 02e60000 00020000 "NAND simulator partition 0" mtd2: 03aa0000 00020000 "NAND simulator partition 1" mtd3: 000c0000 00020000 "NAND simulator partition 2" mtd4: 00d40000 00020000 "NAND simulator partition 3" mtd5: 00ac0000 00020000 "NAND simulator partition 4" mtd6: 00040000 00020000 "NAND simulator partition 5" mtd7: 17e00000 00020000 "NAND simulator partition 6"MTD0是整个MTD设备,将提取出的固件写入MTD设备,因为是在内存中模拟,所以速度很快。
sudo dd if=NAND.bin of=/dev/mtd0 bs=512M count=1查看ubi模块信息,会发现有mtd参数,实际上使用此参数会出错,因为默认的VID Header长度为512。
sudo modprobe ubi mtd=0 $ dmesg [38418.429799] ubi0: attaching mtd5 [38418.429924] ubi0 error: validate_ec_hdr [ubi]: bad VID header offset 2048, expected 512 [38418.429937] ubi0 error: validate_ec_hdr [ubi]: bad EC header [38418.429944] Erase counter header dump: [38418.429946] magic 0x55424923 [38418.429948] version 1 [38418.429950] ec 5 [38418.429952] vid_hdr_offset 2048 [38418.429953] data_offset 4096 [38418.429955] image_seq 34870392 [38418.429957] hdr_crc 0x11db9c17因此需要先挂载UBI模块,然后使用MTD-Utils的UBI Attach指定相关参数。
sudo modprobe ubi sudo ubiattach /dev/ubi_ctrl -m 2 -O 2048接下来可以看到挂载成功的信息
[43880.484837] ubi0: default fastmap pool size: 20 [43880.484841] ubi0: default fastmap WL pool size: 10 [43880.484843] ubi0: attaching mtd2 [43880.486802] ubi0: attached by fastmap [43880.486806] ubi0: fastmap pool size: 20 [43880.486808] ubi0: fastmap WL pool size: 10 [43880.491518] ubi0: attached mtd2 (name "NAND simulator partition 1", size 58 MiB) [43880.491521] ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes [43880.491523] ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 512 [43880.491525] ubi0: VID header offset: 2048 (aligned 2048), data offset: 4096 [43880.491527] ubi0: good PEBs: 469, bad PEBs: 0, corrupted PEBs: 0 [43880.491529] ubi0: user volume: 1, internal volumes: 1, max. volumes count: 128 [43880.491532] ubi0: max/mean erase counter: 14/5, WL threshold: 4096, image sequence number: 1328192 [43880.491534] ubi0: available PEBs: 0, total reserved PEBs: 469, PEBs reserved for bad PEB handling: 80 [43880.491617] ubi0: background thread "ubi_bgt0d" started, PID 25777随后指定文件系统UBIFS进行挂载,可以成功读取到文件系统里的内容。
$ mkdir /tmp/modem $ sudo mount -t ubifs ubi0_0 /tmp/modem $ ls /tmp/image bdwlan30.bin mba.b03 mba.mdt modem.b03 modem.b08 modem.b12 modem.b16 modem.b22 otp30.bin mba.b00 mba.b04 modem.b00 modem.b05 modem.b09 modem.b13 modem.b19 modem.b23 qwlan30.bin mba.b01 mba.b05 modem.b01 modem.b06 modem.b10 modem.b14 modem.b20 modem.b24 utf30.bin mba.b02 mba.mbn modem.b02 modem.b07 modem.b11 modem.b15 modem.b21 modem.mdt有时候在UBI之上会使用SquashFS,因此常规的挂载方法会失效
[ 214.800087] UBIFS error (ubi0:0 pid 3848): ubifs_read_node [ubifs]: bad node type (1 but expected 6) [ 214.800093] UBIFS error (ubi0:0 pid 3848): ubifs_read_node [ubifs]: bad node at LEB 0:0, LEB mapping status 1 [ 214.800094] Not a node, first 24 bytes: [ 214.800095] 00000000: 68 73 71 73 46 0c 00 00 5a 9c 25 5d 00 00 02 00 ac 00 00 00 01 00 11 00 hsqsF这里的hsqs是SquashFS的Magic,因此只需要将UBI用squashfs挂载即可
sudo dd if=/dev/ubi0_0 of=./ubi0_0 unsquashfs ./ubi0_0卸载操作如下
sudo umount MOUNTED_DIR sudo ubidetach /dev/ubi_ctrl -m 0 sudo modprobe -r ubi sudo modprobe -r nandsim 使用UBI Reader进行读取下载或使用PIP安装,https://github.com/jrspruitt/ubi_reader
sudo pip install ubi_reader先看是否准确识别UBI信息
ubireader_display_info [options] path/to/file完全提取文件,但是遇到其他文件系统就会失败。
ubireader_extract_files [options] path/to/file所以建议先还原PEB到LEB,然后再对其各个卷进行分析。
ubireader_extract_images [options] path/to/file UBI重打包挂载UBIFS之后,有可能需要修改文件重打包,使用dd命令不可行。
首先记住ubiattach命令后的回显,会打印出LEB信息
$ sudo ubiattach /dev/ubi_ctrl -m 7 -O 2048 UBI device number 0, total 240 LEBs (30474240 bytes, 29.1 MiB), available 0 LEBs (0 bytes), LEB size 126976 bytes (124.0 KiB)总共240个LEB,每个LEB占用12696字节,在mkfs里把ubifs的参数填入,打包成UBIFS。
# mtd5 sudo mkfs.ubifs -m 2048 -e 126976 -c 240 -F -r ./UBI_1 rootfs.img # mtd9 sudo mkfs.ubifs -m 2048 -e 126976 -c 240 -F -r ./UBI_2 rootfs.img sudo mkfs.ubifs -m 2048 -e 126976 -c 240 -R 1 -x lzo -r ./UBI_1 rootfs.img sudo mkfs.ubifs -m 2048 -e 126976 -c 240 -x lzo -r ./rootfs rootfs.img新建ubi_config.ini文件
vi ubi_config.inivol_size一定要和image的尺寸对应,最后一行为空,否则报错 ubinize: error!: cannot load the input ini file “ubi_config.ini”
[rootfs] mode=ubi image=rootfs.img vol_id=0 vol_size=9904128 vol_type=dynamic vol_name=rootfs vol_alignment=1 vol_flags=autoresize最后用ubinize生成UBI文件
sudo ubinize -o rootfs.ubi -p 131072 -m 2048 -s 512 -e 2 -Q 0 -O 2048 -x1 ubi_config.ini-e 是擦除块的数量,默认是0,可以用binwalk快速查看 -Q 是映像的顺序号,可用ubi_display_info查看 -x 是UBI的版本,默认是1 -s 是子页大小,不是所有的NAND都有子页,一般来说SLC颗粒的2048字节的NAND页是由4个512字节的子页组成,MLC没有子页 -m 是页大小 -p 是物理块大小,一个物理块一般有64页,参考NAND Flash手册
下面是给mtd7烧写rootfs.ubi
sudo ubinize -v -o rootfs.ubi -p 131072 -m 2048 -s 512 -O 2048 ubi_config.ini sudo ubiformat /dev/mtd7 -O 2048 -s 512 -f rootfs.ubi如果是SquashFS的文件系统,那么不需要构建ubifs,在修改完系统内容后,直接用mksquashfs打包SquashFS,一定要用相应的权限打包,如果目标系统是root,那么就在root下打包。后续操作就是用ubinize打包成UBI。
sudo mksquashfs ./squashfs-root/* rootfs.squashfs ReferenceGL.iNet MIFI 一款差不多的4G便携路由器
使用华为E5885L一年多了,对我而言,它不仅是一款完美的4G便携路由器,而且经过改造之后更是一款渗透利器。尽管这是一款非常美好的产品,但是在安全研究的工作中,还是发现有不少痛点。但是在使用了GL.iNet MIFI之后,完全满足了我的测试需求。尽管能够解决问题,但是某些地
浅谈4G通信模组在车联网领域的攻击场景
GL.iNet MIFI 一款差不多的4G便携路由器
使用华为E5885L一年多了,对我而言,它不仅是一款完美的4G便携路由器,而且经过改造之后更是一款渗透利器。尽管这是一款非常美好的产品,但是在安全研究的工作中,还是发现有不少痛点。但是在使用了GL.iNet MIFI之后,完全满足了我的测试需求。尽管能够解决问题,但是某些地方太粗糙了。
外壳
在侧面有很特别的出风口,跟眼睛一样o皿o,里面有风扇的形状,又丑又没用。
拆机之后,可以看到简陋的电池黏在外壳上,用一张墨绿色的纸挡住
首先E5885L使用了HiSilicon LTE Cat6的芯片集,基带的型号是hi6932,这个基带芯片实际上还用于车规级的芯片919系列,至少性能是值得肯定的。但是,车规级芯片如果作为NAD,网络负载压力也十分地小,便携路由方案的RAM要比车规级小很多。一旦负载量增大,便会出现网络不稳定的问题,这种场景主要还是容易发生在测试过程中。
某些场景需要两个RJ45接口,E5885L就不能满足了,但是GL-MIFI有两个RJ45接口,并且WAN口可以配置成LAN口。十分灵活
有时需要进行ARP欺骗,因为E5885L的配置,导致不能成功实现。
E5885L修改IMEI要重启系统才能生效,而GL-MIFI的处理器和基带芯片是分开的,因此只需要重置4G模块就能生效
GL-MIFI支持USB外接3G/4G Modem,很多时候,PC无法使用Modem拨号、有可能是驱动不支持,有可能是pppd配置不正确,此时,我们能把目标Modem放到GL-MIFI上面识别,可以免去E-SIM飞线的工作。
使用内部天线也是贴在外壳上,GL-MIFI使用的是移远EC20 4G模块,Mini PCI-E接口,国内版使用EC20-CEHCLG型号,仅支持上网,不能拨打电话。
在PCB上引出了许多AR9331的GPIO引脚,有助于开发IoT应用。
/dev/ttyUSB0 DM /dev/ttyUSB1 GPS NMEA message output /dev/ttyUSB2 AT commands /dev/ttyUSB3 PPP connection or AT commands wwan0 (QMI mode)USB network adapter在Web界面提供了快速AT命令的插件。
很方便的进行基础操作
修改IMEI非常方便
支持配置APN,非常方便
默认开放SSH服务,基于OpenWRT编译,gl.inet提供的软件源速度快。
配置opkg装到SD卡https://forum.gl-inet.com/t/mifi-install-package-on-external-storage-usb-or-sd-card/4332
其他可以查询官方提供的MIFI的通信模组使用教程
https://github.com/domino-team/docs/blob/master/docs/mini/mifi.md
Osmocom也有移远EC20的hack说明
https://osmocom.org/projects/quectel-modems/wiki/EC20
新版固件已经禁用了AT+QLINUXCMD,所以不能直接发送命令