4、固件识别:从文件类型到基地址的全链路分析
拿到一个思科路由器固件,第一件事是什么?
不是急着解包,也不是直接扔进反汇编器。我个人的习惯是——先做固件识别。这一步就像医生看病前的望闻问切,看似基础,但能帮你避开后面80%的坑。
4.1 file命令:第一眼判断文件类型
在Linux终端里,我最常用的命令就是 file。它通过读取文件头部的Magic Number来判断文件类型,准确率相当高。
$ file c2960s-universalk9-mz.152-4.E7.bin
c2960s-universalk9-mz.152-4.E7.bin: data
嗯,这里显示的是 data,说明file命令没识别出来。别慌,这很正常。思科的固件往往经过特殊封装,不是标准的ELF或PE格式。
换个思路,我们看看是不是压缩过的:
$ file c2960s-universalk9-mz.152-4.E7.bin
c2960s-universalk9-mz.152-4.E7.bin: gzip compressed data, from Unix
看到了吧?有时候固件本身就是gzip压缩包。我在分析Cisco 2960系列时,遇到过好几次这种情况。直接解压就能拿到真正的固件镜像。
hexdump -C | head 看看文件头。思科固件常见的Magic Number包括0x2000、0x4000、0x6000等,这些往往对应不同的平台架构。
4.2 binwalk熵分析:发现隐藏的宝藏
file命令只能看表面,但固件内部可能藏着多个文件系统、压缩块、甚至加密分区。这时候就要请出我们的老朋友——binwalk。
binwalk的熵分析功能,说白了就是检测数据块的随机性。高熵区域通常代表加密或压缩数据,低熵区域则可能是明文代码或文件系统。
$ binwalk -E c2960s-universalk9-mz.152-4.E7.bin
这条命令会生成一张熵图。我一般会重点关注那些熵值突然跳变的位置——那里往往是不同文件系统的分界线。
举个例子,我在分析Cisco 3800系列时,熵图显示在0x200000处有一个明显的熵值下降。后来验证,那里正是Squashfs文件系统的起始位置。
-B参数),能帮你快速定位固件中的文件系统、内核镜像、Bootloader等关键组件。
4.3 Magic Number:固件头的身份证
每个固件都有自己独特的头部标识,也就是Magic Number。思科不同系列的固件,Magic Number差异很大。
| 固件系列 | Magic Number | 说明 |
|---|---|---|
| Cisco IOS (传统) | 0x2000 或 0x4000 | 常见于老款路由器,如2500、2600系列 |
| Cisco IOS (新) | 0x6000 | 用于7200、7500等高端平台 |
| Cisco IOS-XE | 0x7F454C46 (ELF头) | 基于Linux内核,本质是ELF文件 |
| Cisco NX-OS | 0x1F8B (gzip头) | 通常先解压再分析 |
怎么找Magic Number?用hexdump看一眼文件开头:
$ hexdump -C c2960s-universalk9-mz.152-4.E7.bin | head -5
00000000 1f 8b 08 00 00 00 00 00 00 03 ec bd 07 60 1c 47 |.............`.G.|
00000010 96 27 8a aa ea ee 9e 99 9e 99 99 99 99 99 99 99 |.'..............|
...
看到开头的 1f 8b 了吗?这就是gzip的Magic Number。所以这个固件其实是压缩包,解压后才能看到真正的IOS镜像。
4.4 基地址分析:找到代码的落脚点
基地址,说白了就是固件在内存中的加载地址。没有它,反汇编出来的地址全是错的,根本没法看。
怎么找基地址?我一般用两种方法:
- 查看Bootloader输出: 如果固件是从Flash启动的,Bootloader通常会打印加载地址。比如Cisco 2600系列的Bootloader会显示
Loading at 0x80001000... - 分析固件头: 有些固件头里直接包含了基地址信息。比如IOS的固件头,在偏移0x10处通常存放着加载地址。
举个例子,用binwalk扫描后,我们找到了一个疑似内核的镜像块:
$ binwalk -Me c2960s-universalk9-mz.152-4.E7.bin
...
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 gzip compressed data
...
0x200000 0x200000 Squashfs filesystem, little endian, version 4.0
...
对于Squashfs文件系统,基地址通常是0x200000。但如果是内核镜像,基地址就需要根据架构来推断。MIPS架构的基地址一般是0x80000000,ARM架构则可能是0xC0000000或0x00008000。
strings 命令搜索内核符号表。比如搜索 start_kernel 或 init_task,然后根据符号地址反推基地址。这个方法我在分析Cisco 3800时用过,效果不错。
知识体系总览
下面这张图,是我自己总结的固件识别流程。每次拿到新固件,我都会按这个步骤走一遍:
这张图把整个流程串起来了。从拿到固件开始,先用file命令看表面,再用binwalk做熵分析挖内部结构,接着通过Magic Number确认固件系列,最后确定基地址。每一步都有它的价值,缺一不可。
好了,这一章的内容就到这里。记住,固件识别是逆向分析的地基,地基打不牢,后面全是空中楼阁。