之前说打算写个拿华为光猫的root shell的文章来着,根据网上的资料,拿到root shell之后,发现不够玩的,想要玩的更深入点,还得实现固件的解包与打包,于是GG搜索相关资料,无意间找到一篇较冷门的但是很重要的资料:
PWN华为HG8120C光猫(三)
该文章对华为光猫固件的结构进行了粗略的猜解。但是已经具备了针对固件的解包与打包的基础功能。
不过源码是PY写的,本人对py不是很熟悉,加上原文对固件结构的解析不是很细致。
所以打算从头开始分析固件结构,一开始是瞄准了网上散播的华为ONT开telnet工具。
因为原文的upgrade.bin就是提取自该软件。
实际分析过后,发现该软件仅仅对固件文件做个校验,并不涉及解包打包的操作。
所以想从这软件里分析出固件的详细结构是不太可能的。
又开始搜索有关华为固件相关的工具,功夫不负有心人,终于在chinadsl上找到一个华为固件的重打包工具。
该工具的作用不是很清楚,实际测试时,我是用的一个老固件加一个xml来实现重打包操作的。
查了下发现没壳,还是VC++开发,IDA逆向过程也很顺利:
废话不多说,直接贴固件结构:
固件结构的C语言代码:
//基本文件头
typedef struct _HWNP_BasicFileHeader
{
//魔法字
uint32_t u32Magic;
//文件大小 (计算公式为.bin的文件大小 - 76) big-endian
uint32_t beu32FileSize;
//从HWNP_FILEHDR2开始到文件结束的CRC32值 (包含项目数据)
uint32_t u32FileCRC32;
} HWNP_BASFILEHDR, *PHWNP_BASFILEHDR;
//文件头2
typedef struct _HWNP_FileHeader2
{
//头部大小
//计算公式有2种:
//1: sizeof(HWNP_HEADER) + Header.u16ProductListSize + Header.u32ItemCount * Header.u16ItemInfoSize
//2: Header.u16ProductListSize + Header.u32ItemCount * Header.u16ItemInfoSize
//前一种多了文件头大小
//新版本固件一般是第一种公式,好像V100版本的固件是第二种计算公式
//该数值不是计算头部CRC32时的大小
uint32_t u32HeaderSize;
//从HWNP_PAKHDR开始到N个HWNP_ITEMINFO结束的CRC32值 (不包含项目数据)
uint32_t u32HeaderCRC32;
} HWNP_FILEHDR2, *PHWNP_FILEHDR2;
//包头
typedef struct _HWNP_PacketHeader
{
uint32_t u32ItemCount;
uint8_t u8PackTotal;
uint8_t u8PackNum;
uint16_t u16ProductListSize;
union {
uint16_t u16ItemInfoSize; //== sizeof(HWNP_ITEMINFO)
uint32_t _u32ItemInfoSize; //== sizeof(HWNP_ITEMINFO)
};
uint32_t u32Reserved;
} HWNP_PAKHDR, *PHWNP_PAKHDR;
typedef struct _HWNP_Header
{
HWNP_BASFILEHDR BasicFileHeader;
//file crc32 start comupte
HWNP_FILEHDR2 FileHeader2;
//header crc32 start comupte
HWNP_PAKHDR PacketHeader;
} HWNP_HEADER, *PHWNP_HEADER;
typedef struct _HWNP_ItemInfo
{
uint32_t u32Id; //原 Index
uint32_t u32ItemCRC32;
uint32_t u32Offset;
uint32_t u32Size; //原 Len
char chItemPath[256]; //原 Destination
char chItemType[16]; //原 Name
char chItemVersion[64];
uint32_t u32Policy;
uint32_t u32Reserved;
} HWNP_ITEMINFO, *PHWNP_ITEMINFO;
大致描述下固件结构,首先固件文件头是固定格式,可以被拆分为3个部分:
BasicFileHeader //基本文件头
FileHeader2 //基本文件头2
PacketHeader //包头
非要把文件头拆分成3个部分主要是为了好计算CRC32:
HeaderCRC32要从PacketHeader开始计算,包括了产品支持列表和项目信息部分。
FileCRC32则是从FileHeader2开始计算CRC32,一直到文件尾。
另外每一个项目都有自己的CRC32。
固件包也是包,类似于压缩文件包存放的是文件数据,而固件包存放的是各个
项目,这些项目可以是文件,可以是kernel,uboot,rootfs,也可以是flash的配置信息。因为不是统一的类型,所以这里管固件包存放的东西称为项目。
每一个项目都有一个项目信息的结构来记录项目的相关属性,类似于PE文件的区段头记录区段的属性以及区段的文件偏移等。
项目信息除了记录项目数据的CRC,文件偏移,长度等信息,还包括项目的路径,类型,版本,策略(我觉得叫标志比较合适)等属性。
附件是我写的一个通过GUI对华为固件进行编辑的工具,暂时只完成了对项目的导入导出以及检查CRC校验的功能。以后会考虑开源。目前先放出测试版以供收集bug。
另外先挖一个坑,根据目前掌握的信息,或许可以根据dump出来的路由器mtd块,来实现重构路由器固件。这个以后如果研究成功了再来填坑。
已开源到github:
https://github.com/csersoft/HWFW_GUI
附件已更新,修复bug(1.0.2 Alpha):
HWFW_GUI.7z
PS: 1.0.1以及1.0.0存在严重bug,不建议使用。
[课程]FART 脱壳王!加量不加价!FART作者讲授!