2. 固件字符串提取与分析
任务说明
本案例面向嵌入式固件安全分析场景:拿到一个未知的固件二进制文件后,第一步通常是提取其中的可打印字符串,快速定位版本号、文件系统路径、调试命令、协议关键字等敏感信息,为后续逆向定位关键函数提供线索。你将使用 strings 工具完成一次完整的固件字符串提取与分析。
环境准备
本案例需要一台 Linux 机器(或 WSL),并安装 binutils(提供 strings 命令)。大多数发行版默认已安装,若缺失可用以下命令安装:
sudo apt-get install binutils # Debian/Ubuntu
sudo yum install binutils # RHEL/CentOS
准备测试固件
为便于复现,我们先用一段 C 代码编译出一个模拟固件,其中故意包含版本号、路径、命令等特征字符串。将以下代码保存为 demo_fw.c:
#include <stdio.h>
#include <string.h>
const char version[] = "FW_VERSION: 2.1.7-rc3";
const char build_path[] = "/home/builder/firmware/src/main.c";
const char debug_cmd[] = "AT+DEBUG=1";
const char wifi_ssid[] = "IoT_Home_2.4G";
void process_cmd(char *buf) {
if (strstr(buf, "AT+REBOOT")) {
printf("System rebooting...\n");
} else if (strstr(buf, "AT+UART_BAUD=115200")) {
printf("UART baud set to 115200\n");
}
}
int main() {
char input[64];
printf("Firmware demo, version: %s\n", version);
printf("Build path: %s\n", build_path);
printf("Default SSID: %s\n", wifi_ssid);
while (1) {
printf("cmd> ");
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = 0;
process_cmd(input);
}
return 0;
}
编译生成固件镜像(静态链接以模拟真实固件中字符串较多的情况):
gcc -static -o demo_fw demo_fw.c
字符串提取与过滤
使用 strings 提取所有可打印字符串,并过滤掉长度过短的噪声(默认最小长度为 4):
strings -n 4 demo_fw > strings_all.txt
wc -l strings_all.txt
查看与目标信息相关的字符串:
grep -i "version\|FW_\|AT+\|\.c\|\.h\|/home\|/usr\|/etc" strings_all.txt
预期输出(与代码逻辑严格一致):
FW_VERSION: 2.1.7-rc3
/home/builder/firmware/src/main.c
AT+DEBUG=1
AT+REBOOT
AT+UART_BAUD=115200
IoT_Home_2.4G
分析要点
对提取结果按类别进行人工分析:
- 版本信息:
FW_VERSION: 2.1.7-rc3表明固件版本为 2.1.7 的候选版本,可用于漏洞库匹配。 - 路径泄漏:
/home/builder/firmware/src/main.c暴露了开发者的构建目录结构,可用于推测源码组织方式。 - 调试/AT命令:
AT+DEBUG=1、AT+REBOOT等表明设备支持串口 AT 指令,可尝试通过 UART 接口交互。 - 默认配置:
IoT_Home_2.4G可能是默认 Wi-Fi SSID,可用于识别设备型号或搜索同类设备。
验证方法
运行以下命令确认提取结果与固件内容一致:
./demo_fw < /dev/null | strings | grep "FW_VERSION"
若输出 FW_VERSION: 2.1.7-rc3,则说明 strings 提取结果准确。判定标准:strings_all.txt 中能检索到上述 6 条关键字符串,且与源码中定义的常量完全匹配。
常见问题
- 字符串被压缩或加密:若固件经过压缩(如 LZMA)或加密,
strings无法直接提取,需先进行解压或解密处理。 - UTF-16 编码字符串:部分嵌入式系统使用宽字符,可用
strings -e l指定 16 位 little-endian 编码提取。 - 误报过滤:二进制中大量短字符串(如寄存器名)会干扰分析,建议先用
-n 8或更长阈值过滤,再逐步降低。