一、固件基本信息
设备简介:5500NAC 是一个自动化的逻辑控制器,主要应用在楼宇控制系统,配备WEB界面以及cubs/MODBUS/Bacnet通信协议
固件压缩包文件名:5500NAC_Firmware_V1.6.0.zip
SHA256: 81D2B46A6505B28D94DB9C7C9CF16EB38CC316747A1CCB93A3FBCE2C4487245E
固件文件分析:解压后可获得 .img 系统镜像 binwalk 可直接解压出文件系统
二、固件分析
1.固件文件系统分析
2.敏感信息发现
查看 /etc 文件夹中各类配置文件,发现了多个服务的默认账户信息
3.业务代码解密&审计
经分析,该固件业务功能采用Lua编写,查看/lib/ 文件夹发现大量.lua 文件
打开某些文件,却发现是各种乱码,编辑器提示是编码问题,换了各种编码后发现并不能改变乱码现象
随后想到,lua 存在各种加密和编译方式(但编译后后缀大都会发生改变如 luac),审计发现开头标志位 LJ 到网上各种搜资料,最终在看雪一篇文章中发现了蛛丝马迹
在确定为 luajit 编译后从安全客一篇文章中获悉了 luajit 的反编译方法{传送门},在这里我重点演示一下,使用 ljd 直接反编译 luajit 伪码的流程。
使用ghidra反汇编 luajit 查找关键字符串 lua 确定了 luajit 以及 lua 的版本
从 luajit 官网下载相对应版本的demo 查看/src/lj_bc.h头文件中的opcode
在 ljd 工具目录下 有两处代码引用了 Opcode 分别是 ljd/ljd/bytecode/instructions.py 和 ljd/ljd/rawdump/code/py
对比 lj_bc.h 中的 Opcode 定义一个一个改就可以了,ljd 默认是 2.1.0版本的,多的注释,少的加上。
由于我要反编译许多源码,所以临时改了一下 /ljd/main.py 使其可以支持多文件,并且将反编译出来的demo 写入新的文件demo如下(这里我反编译的目录是固件里的/lib目录):
import os
import re
import ljdmain
import sys def get_filelist(dir): ##获取包含绝对路径的文件列表 Filelist = []
for home, dirs, files in os.walk(path): for filename in files: #文件名列表, 包含完整路径 Filelist.append(os.path.join(home, filename)) return Filelist def mkdir(path): ##创建文件夹# 引入模块
import os# 去除首位空格 path = path.strip()# 去除尾部\ 符号path = path.rstrip("\\")# 判断路径是否存在# 存在 True# 不存在 False isExists = os.path.exists(path)# 判断结果
if not isExists: os.makedirs(path) print path + ' 创建成功'
return True
else :#如果目录存在则不创建, 并提示目录已存在 print path + ' 目录已存在'
return False# 调用函数if __name__ == "__main__": path = '/home/murkfox/ljd/lib'##
把固件中lib目录复制到了ljd工具目录下Filelist = get_filelist(path)## 获取被反编译的源码目录结构
for file in Filelist: ##创建空文件, 如果目录不存在就创建目录( 将输出重定向至创建的空文件中) fil = file.split("/") fil[4] = "libdec"
ffi = ""
mkpath = ""
for i in range(len(fil)): if i > 0: ffi = ffi + "/" + fil[i]
if i < len(fil) - 1: mkpath = mkpath + "/" + fil[i]# mkpath = mkpath + "/"#
print(mkpath)# mkdir(mkpath) if re.search(r "\.lua", file): ##遍历要反编译的目录, 找到需要被反编译的文件 mkdir(mkpath) with open(ffi, "w") as fl: ##反编译文件, 并将反编译demo输出至对应文件
try: fl.write("## Dec file \n") sys.stdout = fl ljdmain.main(file) fl.close() except: pass
很多从代码审计来看,程序多处操作都是直接通过系统命令完成操作测试文件上传处的命令执行成功
发表评论
您还未登录,请先登录。
登录