

struct file_info{
int size;
int offset;
char filename[0x50];
}
struct MINIFS{
char magic[16];
int flag;
struct file_info[FILECOUNT];
}

对于这种格式的MINIFS,现有工具可以对其进行分析和解包,工具链接:
https://github.com/H4lo/MINIFS-Decompression
1MB至2MB之间,以及2MB以上的固件同样包含“MINIFS”字符串,但不再具有明文路径特征,样例如下,红框内不再含有文件名称等信息:

struct file_info{
int size;
int offset;
char filename[0x50];
}
struct MINIFS{
char magic[16];
int flag;
struct file_info[FILECOUNT];
}

对于这种格式的MINIFS,现有工具可以对其进行分析和解包,工具链接:
https://github.com/H4lo/MINIFS-Decompression
1MB至2MB之间,以及2MB以上的固件同样包含“MINIFS”字符串,但不再具有明文路径特征,样例如下,红框内不再含有文件名称等信息:

这里的文件看起来像是进行了加密,那么便无法再通过上面的工具进行解包了。
通过分析,在这28个固件中,ARM架构的VxWorks固件通常具有外部符号表,可以通过IDA导入signature文件对VxWorks文件做符号恢复,具体恢复方法网上有很多资料,可参考:
http://tttang.com/archive/1418/
符号恢复不在本文描述范围内,这里不再赘述。而MIPS架构固件则不存在任何符号信息。
如下图是ARM架构的VxWorks文件,可以在binwalk提取出来的文件中,使用 grep -r 找到符号信息:


在部分固件中,字符串“MyFirmware”可作为加载地址的关键指纹,但这并不通用。具体方法是:在固件中搜索字符串“MyFirmware”,然后往上查找一个段开始的位置,这很好辨认,一般段开始位置之前是上一个段使用0xFF或者0x00进行填充。找到段开始位置之后往后数0x18个字节,这两个四字节值即是VxWorks系统的加载地址。样例如下:










binwalk解包固件,得到VxWorks系统
把文件放入到IDA中,按照binwalk -Y结果设置IDA的CPU等参数,加载过程中IDA会要求输入固件加载地址,可以暂时忽略掉,直接加载即可
加载完成后,在开始位置处按c键转换为代码(这时候IDA可能会自动识别到一些其他函数),如下例:
分析上图汇编代码,得到一条指令:li $gp, 0x802DD1C0,这就是向gp指针赋值的语句,从这条指令我们得到一个结论:也就是说全局的这张函数表,它的地址大于0x80000000
然后通过对MIPS程序分析的一些经验,在整个系统中找到全局表大概的位置,找到一些类似表的数据:
然后把这些数据转换为四字节数据:
有了这些数据之后就更加确定加载地址大于0x80000000。这里给出一些MIPS架构的VxWorks常用的加载基址,这是我尝试多个样例后得出的结论,一般MIPS架构的加载地址会大于0x80000000,而ARM架构的一般会大于0x40000000。MIPS架构常用的加载地址一般有:0x80001000、0x80010000、0x80008000、0x80200000;ARM架构常用的加载地址为 0x40205000。
经过尝试过MIPS架构的一些加载地址后,当前固件的加载地址是0x80010000,然后在IDA加载时进行设置,最后再去找到全局表,依次再转换为四字节数据,这时候就可以看到IDA会自动识别函数了:
那么如何判断是否是正确的加载地址呢?可以通过字符串引用地址的方式来检查加载地址是否正确,如果设置了正确的加载地址,在字符串引用时,引用的指针所指向的字符串是完整的。如果是错误的加载地址,那么指针指向的字符串可能会指向某个字符串的中间位置,并不是完整的字符串。也可以在某些函数中查看函数逻辑是否通顺,最好的就是找到一些格式化字符串,然后查看其参数位置是否对应得上,如下例:

通过搜索“MyFirmware”、“img addr”等字符串来定位加载地址,具体分析方法可以参考之前的描述
如果无法找到关键字符串,那么就需要分析uboot文件。在整个固件中查找uboot信息,比如“u-boot image”等字符串获取uboot加载地址,然后通过逆向分析uboot文件得到VxWorks加载地址
通用的人工分析方法,通过分析VxWorks入口的gp指针定位全局函数表位置,搭配使用字符串定位的方法来分析固件加载地址

import re,sys,os
import struct
import json
def u32(data):
'''Big endian'''
return struct.unpack(">I",data)[0]
def read_file(path):
fd = open(path,"rb")
if(not fd):
print('[-] Open target firmware failed!')
exit(-1)
content = fd.read()
return content
def find_img_addr(path):
content = read_file(path)
img_addr_str_offset = content.find(b"img addr")
if img_addr_str_offset == -1:
# print('[-] Can't find "img addr" string!')
return 0
addr_str_offset = img_addr_str_offset + len('img addr: ')
count = addr_str_offset
while 1:
if content[count] == 0:
break
elif content[count] == 10:
break
else:
count+=1
addr = content[addr_str_offset: count]
if addr:
# print(hex(eval(addr)))
return eval(addr)
else:
print('[-] Find address failed!')
return 0
def find_myfirmware_addr(path):
content = read_file(path)
myfirmware_str_offset = content.find(b"MyFirmware")
if myfirmware_str_offset == -1:
# print('[-] Can't find "MyFirmware" string!')
return 0
addr_str_offset = myfirmware_str_offset - 0xc0 + 0x18
addr = u32(content[addr_str_offset: addr_str_offset + 4])
if addr:
# print(hex(addr))
return addr
else:
print('[-] Find address failed!')
return 0
def find_u_boot_image_addr(path):
content = read_file(path)
u_boot_image_addr = content.find(b"u-boot image")
if u_boot_image_addr == -1:
return 0
addr_str_offset = u_boot_image_addr - 0x10
addr = u32(content[addr_str_offset: addr_str_offset + 4])
if addr:
return addr
else:
print('[-] Find address failed!')
return 0
def main():
dirpath = "/path/to/vxworks/"
result = {
"file": "",
"myfirmware_str_addr": "",
"img_addr_addr": "",
"uboot_addr": "",
}
filelist = os.listdir(dirpath)
for i in filelist:
filename = os.path.join(dirpath,i)
result["file"] = i
result["img_addr_addr"] = hex(find_img_addr(filename))
result["myfirmware_str_addr"] = hex(find_myfirmware_addr(filename))
result["uboot_addr"] = hex(find_u_boot_image_addr(filename))
r = json.dumps(result)
print(r)
if __name__ == "__main__":
main()

还没有评论,来说两句吧...