• VxWorks固件分析方法总结


    VxWorks固件分析方法总结

    最近研究基于VxWorks系统的iot设备的固件分析方法,将学习心得记录于此,以备将来的查询需要。

    1.VxWorks是什么?

    VxWorks是美国WindRiverSystem公司(风河公司)推出的一个RTOS(实时操作系统),凭借良好的持续发展能力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据一席之地。自从1987年首次问世以来,VxWorks系统版本经历了5.x,6.x到如今的7版本。VxWorks系统凭借其优秀的实时性占据着不小的市场份额,包括NASA的火星探测器、波音787客机、网络路由器等,市场范围跨越各种安全领域。
    VxWorks版本更替

    按照所运行的操作系统区分,嵌入式iot设备可以大致上分为基于linux和基于VxWorks的两类。VxWorks支持几乎所有现代市场上的嵌入式CPU架构,包括x86系列、MIPS、PowerPC、Freescale ColdFire、Intel i960、SPARC、SH-4、ARM、StrongARM以及xScale CPU。

    2.如何定位VxWorks固件的加载地址

    使用ida pro、ghidra等反汇编工具进行分析时,需要了解固件的加载地址,否则无法正确的分析固件。下图所示为填写固件加载地址前后的函数识别情况的对比,可以看出确定了固件加载地址之后函数的识别度更高。
    before
    after

    2.1通过ELF文件头读取

    通常固件文件会使用ELF格式进行封装,因此可以使用readelf等工具对头部文件进行分析,进而得到固件的加载地址。IDA pro已经集成了这个功能,可以直接分析出常见的固件的加载地址。
    elf

    2.2通过分析内存中的相邻位置

    mips
    如图所示为VxWorks固件在mips架构中的内存分布图,可知固件加载地址与栈初始化地址相邻,可以通过定位栈初始化地址确定固件的加载地址。

    initialstack
    那么如何定位栈初始化地址呢?那就是寻找栈指针寄存器sp的位置。根据VxWorks官网给出的Initial Stack的说明,可知Initial Stack是usrInit()函数的初始化栈。

    usrinit
    又因为UsrInit()是VxWorks系统引导后的运行的第一个函数,因此可以通过在ida中寻找sp寄存器首次出现的位置(此时的ida并没有指定固件加载地址),通过sp的值确定栈初始化的值,从而确定固件的加载地址。

    sp
    如果所示,sp寄存器中保存0x80000FF0,因此固件的加载地址应该是0x80001000。

    2.3通过定位bss在内存中的地址

    usrinit2
    这个方法在原理上同2.2的方法一样,但是需要一定的计算。根据UsrInit()的描述,第一个跳转的函数就是负责初始化BBS区的函数,因此可以寻找第一个跳转的指令的位置;还有另外一个方法确定初始化BBS区的位置,由于在系统启动过程中VxWorks会使用bzero函数对bss区的数据进行清零,所以可以在固件中用命令grep -r bzero查找bzero字符串出现的位置,此方法可以作为验证。

    2.4其他方法

    通过焊接UART接口查看系统引导过程的串口输出;通过查阅开发者手册等。

    3.使用符号表修复函数名

    3.1寻找符号表的位置

    如果固件本身已经编入了符号表,那么可以使用binwalk确定符号表的位置。
    binwalk-fuhaobiao

    VxWorks系统的符号表按照每16个字节一组,前四个字节用0x00进行填充,第二个四字节表示符号名字符串在内存中的位置,第三个四字节表示符号在内存中的位置,最后四个字节代表符号的类型,如0x0500表示函数名。
    fuhaobiao

    但是如果分析固件没有得到符号表,可能存在两种可能:一种是固件本身就没有编入符号表,这种情况使得函数分析变得比较困难;另一种是符号表被开发者隐藏了起来,防止固件被顺利逆向。

    如何寻找隐藏了的符号表还在学习中,之后会另开一篇专门介绍。

    3.2修复函数名

    在ida pro中,函数名的修复需要编写脚本,用符号表中的函数名替换当前无意义的函数名。在ghidra中,加载完固件之后可以运行vxhunter脚本,将函数名替换为符号表中的函数名。

    ghidra修复完函数名之后的效果,可以很明显的看出施耐德PLC以太网模块固件NOE77101.bin固件中所存在的后门账户漏洞CVE-2011-4859
    ghidra

  • 相关阅读:
    1001. 害死人不偿命的(3n+1)猜想 (15)
    单链表排序
    简单插入排序
    简单选择排序
    C语言-随机数
    二分查找(折半查找)
    顺序查找-顺序查找-带哨兵查找
    队列-链表实现
    循环队列_数组实现
    队列-顺序存储-简单实现
  • 原文地址:https://www.cnblogs.com/yangmzh3/p/11214451.html
Copyright © 2020-2023  润新知