基于VxWorks的固件分析-修复篇
VxWorks的固件分析 由于binwalk无法直接解包出 需要手动提取 并且包括符号表修复过程
版本信息
TP-link/TL-WDR7660千兆版 V1.0升级软件20190830_2.0.30
附件地址
https://smb.tp-link.com.cn/service/detail_download_7989.html
--------------------------------------------------------------------------------------------------------
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------------------------------
512 0x200 uImage firmware image, header
size: 64 bytes, data size: 48928
bytes, compression: lzma, CPU:
ARM, OS: Firmware, image type:
Standalone Program, load address:
0x41C00000, entry point:
0x41C00000, creation time:
2018-09-05 07:32:57, image name:
"U-Boot
2014.04-rc1-gdbb6e75-dirt]"
66560 0x10400 LZMA compressed data, properties:
0x6E, dictionary size: 8388608
bytes, compressed size: 1351799
bytes, uncompressed size: 3869672
bytes
--------------------------------------------------------------------------------------------------------uImage header size是64字节 ARM架构 载入uboot的地址0x41C00000
数据是lzma压缩的
我们依次进行提取
提取uboot
dd if=wdr7660gv1-cn-up_2019-08-30_10.37.02.bin of=uboot bs=1 skip=512 count=66048(66560-512)放入010editor中分析 header data
27051956
0DEFB3DA
A5B8F86A
90000BF2
041C0000
41C00000
2A36A3AD
11020103
552D426F
6F742032
3031342E
30342D72
63312D67
64626236
6537352D
64697274- 术字 (
ih_magic):0x27051956,表明这是一个uImage镜像。 - 头部 CRC 校验 (
ih_hcrc):0x0DEFB3DA,头部校验值。 - 时间戳 (
ih_time):0xA5B8F86A,镜像生成的时间(需进一步转换为实际时间)。 - 镜像数据大小 (
ih_size):0x90000BF2,即 2415916690 字节。 - 加载地址 (
ih_load):0x041C0000,解压后的加载地址。 - 入口地址 (
ih_ep):0x41C00000,解压后的执行入口地址。 - 数据 CRC 校验 (
ih_dcrc):0x2A36A3AD,镜像数据的校验值。 - 操作系统类型 (
ih_os):0x11,表示操作系统是U-Boot。 - 架构类型 (
ih_arch):0x02,表示镜像适用于 ARM 架构。 - 镜像类型 (
ih_type):0x01,表示镜像类型是Standalone Program。 - 压缩类型 (
ih_comp):0x03,表示镜像使用LZMA压缩。 - 镜像名称 (
ih_name):"u-Boot 2014.04-rc1-gdb26e75-dir",这是镜像的名称。
提取主程序
dd if=wdr7660gv1-cn-up_2019-08-30_10.37.02.bin of=10400.lzma bs=1 skip=66560 count=1351799解压后 没有问题成功解压
再进一步分析
binwalk 10400 --------------------------------------------------------------------------------------------------------
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------------------------------
3174925 0x30720D Copyright text: "Copyright (c)
1983, 1988, 1993 Regents of the
University of California. All
rights reserved. "
3178484 0x307FF4 Copyright text: "Copyright
1984-2002 Wind River Systems,
Inc. This program contains
confidential information of Wind
"
3566196 0x366A74 Copyright text: "Copyright(C)
2001-2011 by TP-LINK TECHNOLOGIES
CO., LTD."
3610436 0x371744 VxWorks WIND kernel version 2.6
3725480 0x38D8A8 AES S-Box
3726796 0x38DDCC AES S-Box
3728344 0x38E3D8 SHA256 hash constants, little
endian
3784928 0x39C0E0 SHA256 hash constants, little
endian
3847576 0x3AB598 CRC32 polynomial table, little
endian
--------------------------------------------------------------------------------------------------------解释一下上面的信息
- 版权文本:这些文本代表固件中不同软件的版权信息。这些内存地址上的文本可能用于显示有关固件或作系统中使用的相应软件组件的法律信息。
- VxWorks WIND 内核版本 2.6:这是指系统中嵌入的 VxWorks作系统内核的版本。VxWorks 是嵌入式系统中经常使用的实时作系统。
- AES S-Box:这些是 AES 加密算法中使用的查找表,特别是在密钥扩展和加密/解密过程中。
- SHA256 哈希常量:这些常量是 SHA256 加密哈希算法的一部分,用于各种安全应用程序,如数字签名、消息完整性检查等。
- CRC32 多项式表:此表包含用于计算 CRC32 校验和的值,CRC32 校验和通常用于网络通信、文件存储等中的错误检查。
这里已经知道主程序的架构 arm 小端序 接下来要找到程序的入口点
可以通过直接ida设置正确架构默认打开 反编译最开始的几段可以看到
赋给r0 0x40205000 猜测这就是基地址 关掉重新设置发现
是基本没啥问题的 但是这里是没有符号表的 我们binwalk固件的时候也是无法直接解析出来的因此我们手动去查询
查看VxWorks手册 发现常用bzero这些函数 因此我们用grep -r bzero ./去查看 发现15CBBA可能存在符号表
放入010 editor后 发现格式确实很像符号表 最前面四字节是总size长度 后面四字节是总条目数
因此我们直接跟着 0x34E4*8+8找到符号表的位置 也就是0x1a728
我们可以通过自动化工具vxhunter或者ida脚本进行加载
由于我用的是最新版的ida 9.x 而vxhunter 又已经有5年左右没有维护了 所以这里在网上找了个脚本 手动改了改 脚本如下
# encoding:utf-8
#symfile_path: 刚刚搜索到的符号文件的路径
#symbols_table_start : 符号表起始偏移,从16进制编辑器看出来是8(前8字节作用不清楚,也不重要)
#strings_table_start : 字符串起始偏移,也是从16进制编辑器看出来
import binascii
import idautils
import idc
import idaapi
import ida_funcs
symfile_path = r"K:\winshare\iot\luyouqi\TL-WR940N/15CBBA"
symbols_table_start = 8
strings_table_start = 0x1a728
with open(symfile_path, 'rb') as f:
symfile_contents = f.read()
symbols_table = symfile_contents[symbols_table_start:strings_table_start]
strings_table = symfile_contents[strings_table_start:]
def get_string_by_offset(offset):
index = 0
while True:
if strings_table[offset+index] != 0:
index += 1
else:
break
return strings_table[offset:offset+index]
def get_symbols_metadata():
symbols = []
for offset in range(0, len(symbols_table), 8):
symbol_item = symbols_table[offset:offset + 8]
flag = symbol_item[0]
string_offset = int(binascii.b2a_hex((symbol_item[1:4])).decode("ascii"), 16)
string_name = get_string_by_offset(string_offset)
target_address = int(binascii.b2a_hex((symbol_item[-4:])).decode("ascii"), 16)
# 添加调试输出
print(f"Symbol: {flag}, {string_name}, {target_address}")
symbols.append((flag, string_name, target_address))
return symbols
def add_symbols(symbols_meta_data):
for flag, string_name, target_address in symbols_meta_data:
print(f"Adding symbol: {string_name.decode('utf8')} at {hex(target_address)}")
idc.set_name(target_address, string_name.decode("utf8")) #命令目标地址的数据,数据类型由flag而定
if flag == 0x54: # 类型T,表示是text段的符号,text段的符号一般是函数符号
idc.create_insn(target_address) # 确保target_address有指令
ida_funcs.add_func(target_address) # 将target_address定义为函数并自动寻找边界
if __name__ == "__main__":
symbols_metadata = get_symbols_metadata()
if symbols_metadata:
print(f"Found {len(symbols_metadata)} symbols.")
add_symbols(symbols_metadata)
else:
print("No symbols found.")可以看到我们这里基本修复完成