施耐德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文件,在打開時設置架構:
然後要求設置RAM和ROM,其實就是設置載入基地址:
在IDA中無法識別出任何函數,需要在程式開頭位置按一下 「c」 鍵,就可以顯示部分函數,但沒有解析出所有的函數:
此時可以通過三種方式獲得載入基地址:
- 通過跳轉表獲得基地址、通過字元串引用獲得基地址
- 使用IDA的Vxhunter插件
vxhunter/firmware_tools at master · PAGalaxyLab/vxhunter
這裡為了方便選擇Vxhunter插件,選擇python版本下載後複製到plugin文件夾下,然後運行插件:
得到載入地址是0x10000:
然後發現依然沒有解析函數,此時需要恢複函數名稱。使用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即起始位置:
符號表每0x10為一組,一直找到結束的位置0x3293a4:
然後執行IDA腳本:
最後恢復完成:
在usrAppInit
函數中發現多處loginUserAdd
添加用戶,這些字元串即後門帳號和密碼:
總結
此韌體分析關鍵點在於確定程式基地址和如何恢復符號資訊,只要恢復了符號資訊就和閱讀源碼無異了。
References
//bbs.pediy.com/thread-266803-1.htm
//p1kk.github.io/2021/06/11/iot/施耐德 NOE771/