施耐德NOE77101后门漏洞分析

固件下载地址:

GitHub - ameng929/NOE77101_Firmware

文件目录结构,这里只列出了一些主要的文件信息:

├── bin
├── ftp
├── fw
├── rdt
├── webloader.ini
└── wwwroot
    ├── SchneiderTFE.zip
    ├── cgi-bin
    ├── classes
    ├── conf
    │   ├── Gcnftcop.sys
    │   ├── bootp
    │   ├── dhcp
    │   ├── diag
    │   │   └── chkdsk.out
    │   ├── exec
    │   │   ├── NOE77101.bin
    │   │   └── kerVer
    │   ...
    ├── html
    │   ├── config.js
    │   	...
    ├── rdt
    │   └── rdt.zip
    └── secure

注意到 wwwroot/conf/exec 目录下有一个文件 NOE77101.bin ,这就是要分析的固件文件。使用binwalk命令查看文件内容,是一个Zlib类型的压缩文件:

➜  exec binwalk NOE77101.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
901           0x385           Zlib compressed data, default compression

binwalk提取文件内容,binwalk会自动解压文件,得到文件夹 _NOE77101.bin.extracted

➜  exec binwalk -e NOE77101.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
901           0x385           Zlib compressed data, default compression

➜  exec ls
NOE77101.bin            _NOE77101.bin.extracted kerVer

binwalk自动提取了文件到_NOE77101.bin.extracted目录下,并对其进行解压。此时文件夹下就有两个文件,一个zlib和一个被解压出来的:

➜  _NOE77101.bin.extracted ls
385      385.zlib

然后再用binwalk查看385文件:

➜  _NOE77101.bin.extracted binwalk 385

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
2054252       0x1F586C        EST flat binary
2088936       0x1FDFE8        HTML document header
2108532       0x202C74        HTML document footer
2110048       0x203260        HTML document header
2115564       0x2047EC        HTML document footer
2119528       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 table
2192580       0x2174C4        Base64 standard index table
2211604       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固件,符号表位置在0x301E74处,稍后会用到。

然后使用binwalk查看架构,得知是PowerPC big endian:

➜  _NOE77101.bin.extracted binwalk -A 385
....
2045960       0x1F3808        PowerPC big endian instructions, function epilogue
2045968       0x1F3810        PowerPC big endian instructions, function prologue
2046180       0x1F38E4        PowerPC big endian instructions, function epilogue
3150948       0x301464        PowerPC big endian instructions, function epilogue

之后用IDA打开385文件,在打开时设置架构:

Image.png

然后要求设置RAM和ROM,其实就是设置加载基地址:

Image.png

Image.png

Image.png

在IDA中无法识别出任何函数,需要在程序开头位置按一下 “c” 键,就可以显示部分函数,但没有解析出所有的函数:

Image.png

Image.png

此时可以通过三种方式获得加载基地址:

  • 通过跳转表获得基地址、通过字符串引用获得基地址

固件安全之加载地址分析 – 绿盟科技技术博客

  • 使用IDA的Vxhunter插件

vxhunter/firmware_tools at master · PAGalaxyLab/vxhunter

这里为了方便选择Vxhunter插件,选择python版本下载后复制到plugin文件夹下,然后运行插件:

Image.png

得到加载地址是0x10000:

Image.png

然后发现依然没有解析函数,此时需要恢复函数名称。使用IDA脚本:

#coding=utf-8
from idaapi import *
from idc import *

symbol_interval = 16 #符号表间隔
load_address = 0x10000 #固件内存加载基址
symbol_table_start = 0x31eec4 + load_address   #符号表起始地址
symbol_table_end = 0x348114 + load_address #符号表结束地址
ea = symbol_table_start
eaEnd = symbol_table_end

while ea < eaEnd:
   offset = 0   #4个字节为一组数据
   #将函数名指针位置的数据转换为字符串
   create_strlit(get_wide_dword(ea-offset), BADADDR)
   #将函数名赋值给变量sName
   sName = get_strlit_contents(get_wide_dword(ea))
   print(sName)
   if sName:
       #开始修复函数名
       eaFunc = get_wide_dword(ea - offset +4)
       set_name(eaFunc, sName)
       create_insn(eaFunc)
       ida_funcs.add_func(eaFunc, BADADDR)
   ea += symbol_interval

代码中的符号表起始地址和符号表结束地址需要手动修改一下,可以在16进制编辑器中查看。在binwalk分析的时候得到符号表地址为0x301E74,然后在文件中找到这个位置,0x301E74即起始位置:

Image.png

符号表每0x10为一组,一直找到结束的位置0x3293a4:

Image.png

然后执行IDA脚本:

Image.png

最后恢复完成:

Image.png

usrAppInit函数中发现多处loginUserAdd添加用户,这些字符串即后门账号和密码:

Image.png

总结

此固件分析关键点在于确定程序基地址和如何恢复符号信息,只要恢复了符号信息就和阅读源码无异了。

References

固件符号表恢复

https://bbs.pediy.com/thread-266803-1.htm

固件安全之加载地址分析 – 绿盟科技技术博客

施耐德PLC以太网模块后门账户解密 – 灯塔实验室

https://p1kk.github.io/2021/06/11/iot/施耐德 NOE771/

posted @ 2022-02-24 22:52  unr4v31  阅读(710)  评论(0编辑  收藏  举报