IOT初尝试(PLC NOE-771)
PLC NOE-771
尝试IOT的,挑个简单的来过一遍流程,大概明白了一个固件分析的流程,感觉如果挖掘CVE的话还是FUZZ可能更加合适,直接固件分析可能带来的工作量较大!
过binwalk -A指令来对固件的CPU架构进行分析,此外也可以用binwalk -Y指令来调用capstone反汇编引擎来进行辅助判断,不过我实际测试下来存在一些误报的情况会把NOE 711的固件识别成arm架构的。
r1寄存器是栈指针,而r3寄存器则是第一个参数
此时指令:
lis r1,1
addi r1,r1,0 // r1置一并左移赋零,即设置r1为0x10000
lis r3,0
addi r3,r3,0
addi r1,r1,-0x10 //栈上开辟0x10空间
b loc_1E84C //跳转
根据VxWorks官网文档对对内存布局的描述,Initial Stack是usrInit函数的初始化栈,故此时跳转为usrInit函数。此时栈地址同时为固件加载地址!
此时我们需要查看符号表是否包含符号表,如果包含即需要手动加载!
基于符号表特征也可得出符号表结尾地址!
# coding=utf-8
from idaapi import *
import time
symbol_interval = 16# 符号表间隔
load_address = 0x10000# 固件内存加载地址
symbos_table_start = 0x32d514 + load_address#符号表在内存中的起始地址
symbol_table_end = 0x356e70 + load_address# 符号表在内存中结尾地址
symbol_item_counts = 0x2996# 符号表项数
# 在IDA 中rebase 程序到加载地址
# 修改基地址
rebase_program(load_address, 0x0008)
#autoWait()#调用IDA的自动分析功能
i = symbos_table_start
while i < symbol_table_end:
offset = 4 # 每4个字节为一组数据
#MakeStr(Dword(i + offset),BADADDR)# 将函数名指针位置的数据转化为字符串
sName = GetString(Dword(i + offset), -1, ASCSTR_C)# 将函数名赋值给变量sName
print(sName)
if sName:
# 开始修复函数名
eaFunc = Dword(i + offset + 4)
MakeName(eaFunc, sName)
MakeCode(eaFunc)
MakeFunction(eaFunc,BADADDR)
i += symbol_interval
但此时IDA7.0发生TypeError: in method ‘create_strlit’, argument 2 of type 'size_t’错误!此为脚本二次传参错误bug(MakeStr 在7.0版本中使用会报错)
解决方法
IDA 7.0\python\idc_bc695.py
中,113行的
def MakeStr(ea, endea): return create_strlit(ea, 0 if (endea) == ida_idaapi.BADADDR else endea-ea)
屏蔽掉,然后修正添加如下即可
def MakeStr(ea, endea): return create_strlit(ea, endea)
最后reload下idc模块即可
经过一次又一次的尝试,因为ida版本不一,故idapython的函数具体实现不一样,故引发错误,导致无法正确恢复符号表
如下为正确脚本,(总算好了
#coding=utf-8
from idaapi import *
from idc import *
symbol_interval = 16 #符号表间隔
load_address = 0x10000 #固件内存加载基址
symbol_table_start = 0x301e64 + load_address #符号表起始地址
symbol_table_end = 0x3293a4 + 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:
#将bytes转为str
sName = str(sName,encoding="utf-8")
#开始修复函数名
eaFunc = get_wide_dword(ea - offset +4)
set_name(eaFunc, sName)
create_insn(eaFunc)
ida_funcs.add_func(eaFunc, BADADDR)
ea += symbol_interval
通过调用关系_sysInit -> usrInit -> usrKernelInit -> usrRoot -> usrAppInit