VxWorks固件解包
发表于:2023-07-17 |
字数统计: 1.6k | 阅读时长: 7分钟 | 阅读量:

1.前言

闲来无聊,便想着玩玩家里的两个闲置的路由器,第一个是烽火的SR1041H,奈何网上无法免费获得该固件,便拆开看看能不能提取,但家里没有设备,也不会焊接,因此放弃了。另一个是TP-link的TL-WDR5620,官网上有固件的[下载]( TL-WDR5620珍珠白 V6.0升级软件20190830_1.0.10 - TP-LINK 服务支持 )。

2.固件提取

使用binwalk跑一下固件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
binwalk TL-WDR5620珍珠白\ V6.0_1.0.10\ Build\ 190830\ Rel.56944n.bin 

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
43984 0xABD0 U-Boot version string, "U-Boot 1.1.3 (Aug 30 2019 - 10:09:42)"
62464 0xF400 LZMA compressed data, properties: 0x6E, dictionary size: 8388608 bytes, uncompressed size: 3885424 bytes
1287232 0x13A440 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 95491 bytes
1310631 0x13FFA7 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 94952 bytes
1337998 0x146A8E LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 94669 bytes
1360409 0x14C219 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 94659 bytes
1380297 0x150FC9 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 94148 bytes
1399946 0x155C8A LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 91853 bytes
1420189 0x15AB9D LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 89711 bytes
1442119 0x160147 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 85890 bytes
1461740 0x164DEC LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 42500 bytes
1472706 0x1678C2 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 7170 bytes
1474229 0x167EB5 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 200 bytes
1474456 0x167F98 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 253 bytes
1474721 0x1680A1 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 14751 bytes
1476674 0x168842 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 493 bytes
1477125 0x168A05 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 2823 bytes
1478639 0x168FEF LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 221476 bytes
1550818 0x17A9E2 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 1111 bytes
1551723 0x17AD6B LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 1356 bytes
1552122 0x17AEFA LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 384 bytes
1552357 0x17AFE5 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 1535 bytes
1552729 0x17B159 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 607 bytes
1553032 0x17B288 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 438 bytes
1553275 0x17B37B LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 949 bytes
1553612 0x17B4CC LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 566 bytes
1553908 0x17B5F4 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 2536 bytes
1554359 0x17B7B7 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 731 bytes
1554680 0x17B8F8 LZMA compressed data, properties: 0x5A, dictionary size: 8388608 bytes, uncompressed size: 217 bytes
…………

可以看到是由u-boot(引导操作系统启动)和一堆LZMA格式压缩的数据所得,我们把重点放在最大的那块LZMA也就是第二块上,它包含了我们需要的主程序,可以看见偏移为0xF400。

binwalk -e提取整个固件,得到一堆以数字(偏移)命名的文件和压缩包。binwalk跑一下F400

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ binwalk F400                                                           

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
1043412 0xFEBD4 MySQL MISAM index file Version 8
3295696 0x3249D0 VxWorks operating system version "5.5.1" , compiled: "Aug 30 2019, 15:49:04"
3369842 0x336B72 Neighborly text, "NeighborReq)ble; 1:reload with bs enable)"
3370320 0x336D50 Neighborly text, "NeighborReq ignore. dbglvl to Default."
3376794 0x33869A Neighborly text, "neighbor[%d]: %d"
3376923 0x33871B Neighborly text, "neighbor info of %02X:%02X:%02X:%02X:%02X:%02X"
3415248 0x341CD0 Neighborly text, "Neighbor Response Frame/common/wss.c:%d assert binfo->apchanrpt_opclass_num <= IEEE80211_RRM_NUM_CHANRPT_MAXfailed"
3529296 0x35DA50 Neighborly text, "neighbor report framel check failed "
3529425 0x35DAD1 Neighborly text, "neighbor report frame failed:%02x) not support rrm"
3531312 0x35E230 Neighborly text, "Neighbor RSP"
3574248 0x3689E8 Unix path: /etc/Wireless/RT2860AP/RT2860AP.dat
3580496 0x36A250 Copyright string: "Copyright(C) 2001-2011 by TP-LINK TECHNOLOGIES CO., LTD."
3607395 0x370B63 Neighborly text, "neighbor(%s)fault router list contains a non-linklocal address(%s)"
3625056 0x375060 VxWorks WIND kernel version "2.6"
3651625 0x37B829 StuffIt Deluxe Segment (data): fDomain
3651641 0x37B839 StuffIt Deluxe Segment (data): fPort
3668168 0x37F8C8 HTML document header
3668233 0x37F909 HTML document footer
3691320 0x385338 PEM certificate
3691376 0x385370 PEM RSA private key
3697077 0x3869B5 StuffIt Deluxe Segment (data): f
3698768 0x387050 Base64 standard index table
3710203 0x389CFB Neighborly text, "NeighborReq"
3736104 0x390228 AES Inverse S-Box
3736360 0x390328 AES Inverse S-Box
3738680 0x390C38 AES S-Box
3738936 0x390D38 AES S-Box
3741040 0x391570 SHA256 hash constants, little endian
3741296 0x391670 SHA256 hash constants, little endian
3774436 0x3997E4 XML document, version: "1.0"
3794196 0x39E514 SHA256 hash constants, little endian
3805349 0x3A10A5 StuffIt Deluxe Segment (data): f
3805380 0x3A10C4 StuffIt Deluxe Segment (data): fError
3820948 0x3A4D94 XML document, version: "1.0"
3832816 0x3A7BF0 CRC32 polynomial table, little endian
3855272 0x3AD3A8 CRC32 polynomial table, little endian

可以看见它是Vxworks操作系统,binwalk -A F400 | grep head发现是mipsel架构。

3.确定主程序入口

使用16进制编辑器打开之前的.bin文件,搜索字符串MyFirmware(从[大佬]( 分类 RTOS 下的文章 - 赤道企鹅的博客 | Eqqie’s Blog )那获得的经验),往上找到两个相同的地址就是主程序的入口,因此这里的入口是0x80001000。(还有其他几种确定主程序入口地址的方法,等遇见了再补充)

image-20230717202425154

使用ida打开F400文件,选择mipsel,开始和加载地址填入刚刚找到的程序入口地址

image-20230717202802019

image-20230717202829633

4.恢复符号表

Bzero是VxWorks中的一个函数,系统在启动过程中会使用bzero函数对bss段的数据进行清0,因此一定会使用该函数,利用该函数名搜索提取的文件中是否存在该函数名字符串。

image-20230717203718843

使用16进制编辑器查看该文件

image-20230717204208404

从第8个字节开始是符号表,也就是说8+0x21ad*8=0x10d70为函数对应的函数名位置。

image-20230717204511468

每个函数名以\x00结尾,利用如下脚本恢复符号表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import idautils
import idc
import ida_ua
import ida_funcs
import idaapi

symfile_path = './168FEF' #symbols_file path
symbols_table_start = 8 #symbols_table_satrt
strings_table_start = 0x10d70#strings_table_start

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(symbol_item[1:4].hex(), 16)
string_name = str(get_string_by_offset(string_offset))[2:-1]
target_address = int(symbol_item[-4:].hex(), 16)
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:
idc.set_name(target_address, string_name)
if flag == 84:
ida_ua.create_insn(target_address)
ida_funcs.add_func(target_address)


if __name__ == "__main__":
symbols_metadata = get_symbols_metadata()
add_symbols(symbols_metadata)

不能完全恢复。

image-20230717204747970

在修改恢复脚本时,参考了如下api

image-20230717205007893

参考

TP-LINK WDR 7660 固件浅析 - 『软件调试区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

Vxworks固件分析 - FreeBuf网络安全行业门户

(18条消息) 基于VxWorks的嵌入式设备固件分析——PLC NOE-771_vxworks 固件分析_Mira1127的博客-CSDN博客

vxworks固件分析 - hac425 - 博客园 (cnblogs.com)

分类 RTOS 下的文章 - 赤道企鹅的博客 | Eqqie’s Blog

VxWorks固件分析方法总结 - 燕麦粥 - 博客园 (cnblogs.com)

(18条消息) 基于VxWorks的嵌入式设备固件分析——PLC NOE-771_vxworks 固件分析_Mira1127的博客-CSDN博客

上一篇:
cgi调试
下一篇:
vivotek摄像头溢出漏洞复现