博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vxworks固件分析
阅读量:4647 次
发布时间:2019-06-09

本文共 6550 字,大约阅读时间需要 21 分钟。

前言

vxworks 的固件分析流程

1.用binwalk查看固件基本信息并解压固件2.获取固件相关信息, cpu架构,大小端3.确定固件的加载地址4.用IDA加载固件,并修复符号表5. 分析固件

实战分析

一道CTF题

分析固件

用到的例子

http://www.icsmaster.org/wp-content/uploads/2018/01/2018013004153995.zip

首先用 binwalk 扫描下固件的信息

$ binwalk ctf_vxworks.bin DECIMAL       HEXADECIMAL     DESCRIPTION--------------------------------------------------------------------------------901           0x385           Zlib compressed data, default compression

发现就是 zlib 压缩的数据, 用 binwalk 直接解开, 然后用 binwalk 对解开后的文件扫描,发现 vxworks 关键信息, 于是拿到 vxworks 的固件。

$ binwalk 385DECIMAL       HEXADECIMAL     DESCRIPTION--------------------------------------------------------------------------------2054252       0x1F586C        EST flat binary2088936       0x1FDFE8        HTML document header2108532       0x202C74        HTML document footer2110048       0x203260        HTML document header2115564       0x2047EC        HTML document footer2119528       0x205768        XML document, version: "1.0"2119796       0x205874        XML document, version: "1.0"2119912       0x2058E8        XML document, version: "1.0"2192512       0x217480        Base64 standard index table2192580       0x2174C4        Base64 standard index table2211604       0x21BF14        VxWorks WIND kernel version "2.5"2225264       0x21F470        Copyright string: "Copyright Wind River Systems, Inc., 1984-2000"2321952       0x236E20        Copyright string: "copyright_wind_river"3118988       0x2F978C        Copyright string: "Copyright, Real-Time Innovations, Inc., 1991.  All rights reserved."3126628       0x2FB564        Copyright string: "Copyright 1984-1996 Wind River Systems, Inc."3153524       0x301E74        VxWorks symbol table, big endian, first entry: [type: function, code address: 0x1FF058, symbol address: 0x27655C]

同时还扫到了符号表的位置

计算固件加载地址

固件加载地址的计算可以通过vxworks固件中的符号表计算得出的。

固件的符号表一般在固件的最后,有明显的规律。

16个字节 为一组数据:

  • 4个字节 符号对应字符串的内存地址

  • 4个字节 符号的内存地址

  • 4个字节 特征数据

  • 4个字节 0x00, 标识一组数据的结尾

iMnxnU.png

计算加载地址的方法就是

加载地址 = 符号表中字符串的地址 - 相应字符串在固件中的偏移

这里还有一个小 tips

字符串表里面的最后一个字符串 在 符号表的第一项被引用

首先根据特征找到符号表, 根据 binwalk -A 可知固件为大端,所以 第一个符号表项对应字符串在内存中的地址为 0x27656c

iMMO1I.png

然后找到字符串表中最后一个字符串所在偏移为 0x26656c

iMMHtH.png

所以加载地址为

$ python -c "print hex(0x27656c - 0x26656c)"0x10000

恢复符号表

拿到加载地址后,把固件用 IDA 加载起来,然后用 idapython 的脚本恢复即可、

from idaapi import *from idc import *loadaddress = 0x10000eaStart = 0x301e64 + loadaddresseaEnd = 0x3293a4 + loadaddressea = eaStarteaEnd = eaEndwhile ea < eaEnd:    create_strlit(Dword(ea), BADADDR)    sName = get_strlit_contents(Dword(ea))    print sName    if sName:        eaFunc = Dword(ea + 4)        MakeName(eaFunc, sName)        MakeCode(eaFunc)        MakeFunction(eaFunc, BADADDR)    ea = ea + 16

就是遍历符号表项,在指定位置命名 + 设置函数。

参考

http://www.icsmaster.org/archives/ics/784http://www.freebuf.com/vuls/177036.html

下载固件

网上可以搜到

http://www.drvsky.com/TP-Link/TL-WR886N.htm

分析固件

首先 binwalk 看看信息

iMQJu6.png

这里 binwalk 只识别到了 u-boot 镜像,和一大堆 lzma 压缩的数据。通过 u-boot 的信息可以知道固件的加载地址为 0x80010000

发现其中有个 lzma 压缩的数据大小和其他的不在一个数量级, 把它拿出来解析。

41472         0xA200          LZMA compressed data, properties: 0x6E, dictionary size: 8388608 bytes, uncompressed size: 2365616 bytes

然后用 dd 把它 拿出来

dd if=wr886v6.bin of=large.lzma bs=1 skip=41472 count=749632

然后用 binwalk 解出来

$ binwalk _large.lzma.extracted/00     0.7z  $ binwalk _large.lzma.extracted/0DECIMAL       HEXADECIMAL     DESCRIPTION--------------------------------------------------------------------------------1846464       0x1C2CC0        Certificate in DER format (x509 v3), header length: 4, sequence length: 41853752       0x1C4938        Certificate in DER format (x509 v3), header length: 4, sequence length: 41899120       0x1CFA70        VxWorks operating system version "5.5.1" , compiled: "Oct 20 2017, 16:17:22"1968188       0x1E083C        Copyright string: "Copyright(C) 2001-2011 by TP-LINK TECHNOLOGIES CO., LTD."1997876       0x1E7C34        VxWorks WIND kernel version "2.6"2042936       0x1F2C38        HTML document header2043001       0x1F2C79        HTML document footer2062828       0x1F79EC        PEM certificate2062884       0x1F7A24        PEM RSA private key2072188       0x1F9E7C        Base64 standard index table2107248       0x202770        CRC32 polynomial table, big endian2108272       0x202B70        CRC32 polynomial table, big endian2109296       0x202F70        CRC32 polynomial table, big endian2110320       0x203370        CRC32 polynomial table, big endian2130920       0x2083E8        XML document, version: "1.0"2150332       0x20CFBC        SHA256 hash constants, big endian2248421       0x224EE5        StuffIt Deluxe Segment (data): f2248452       0x224F04        StuffIt Deluxe Segment (data): fError2248533       0x224F55        StuffIt Deluxe Segment (data): f

可以看到有 vxworks 的字符串,前面已经拿到了固件的基地址,用 ida 加载。

恢复符号表

使用 grep 来找符号表

$ binwalk  -Me wr886v6.bin........$ cd _wr886v6.bin.extracted/$ grep -r bzeroBinary file C2E3A matches

然后打开 C2E3A 看看

iMl2sx.png

开头 8 字节表示文件大小和符号表大小, 然后就是符号表了, 0x9d00 为字符串表的位置。

然后用脚本恢复

# coding=utf-8import idcimport idaapiimport idautilssym_file = open("PATH OF SYM FILE", 'rb').read()table_data = sym_file[0x08:0x9f80]print(table_data[-8:].encode('hex'))string_table = sym_file[0x9f80:]def get_string(offset):    string = ""    while True:        if string_table[offset] != '\x00':            string += string_table[offset]            offset += 1        else:            break    return stringdef get_sym_data():    sym_data = []    for offset in range(0, len(table_data), 8):        table = table_data[offset: offset + 8]        flag = table[0]        # print('flag: %s' % flag)        string_offset = int(table[1:4].encode('hex'), 16)        # print('string_offset: %s' % string_offset)        string = get_string(string_offset)        # print('string: %s' % string)        target_address = int(table[-4:].encode('hex'), 16)        # print('target_address: %s' % hex(target_address))        sym_data.append([flag, string, target_address])    return sym_datadef fix_idb(sym_data):    for sym in sym_data:        flag, string, target_address = sym        idc.MakeName(target_address, string)        if flag == '\x54':            print("Start fix Function %s at %s" % (string, hex(target_address)))            idc.MakeCode(target_address)            idc.MakeFunction(target_address, idc.BADADDR)            # print('flag: %s' % flag)            # print('string: %s' % string)            # print('target_address: %s' % hex(target_address))if __name__ == '__main__':    sym_data = get_sym_data()    fix_idb(sym_data)

参考

https://www.secpulse.com/archives/75635.html

转载于:https://www.cnblogs.com/hac425/p/9706815.html

你可能感兴趣的文章
pyQt 每日一练习 -- 登录框
查看>>
wp 删除独立存储空间文件(多级非空文件夹删除)
查看>>
Loadrunner安装使用入门
查看>>
smartupload 上传文件时 把页面编码改成gbk 解决乱码
查看>>
EPS是什么格式
查看>>
Python的数据库操作(Sqlalchemy)
查看>>
2.抽取代码(BaseActivity)
查看>>
My simplified pickit2 clone
查看>>
Redis 入门知识
查看>>
夏天过去了, 姥爷推荐几套来自smashingmagzine的超棒秋天主题壁纸
查看>>
转--Android如何在java代码中设置margin
查看>>
反射的所有api
查看>>
css 定位及遮罩层小技巧
查看>>
项目中非常有用并且常见的ES6语法
查看>>
[2017.02.23] Java8 函数式编程
查看>>
Knowledge Point 20180305 数据在计算机中的表示
查看>>
谈谈对web标准的理解
查看>>
58前端内推笔试2017(含答案)
查看>>
sprintf 和strcpy 的差别
查看>>
MPEG4与.mp4
查看>>