Commit 58d1d92e by Craig Heffner

Updated unpfs extractor to create unique output directories in the event of…

Updated unpfs extractor to create unique output directories in the event of multiple PFS images inside the same file; added directory traversal check.
parent f87bcc64
import os import os
import errno import errno
import struct import struct
import binwalk.core.plugin import binwalk.core.common
import binwalk.core.compat import binwalk.core.compat
from binwalk.core.common import BlockFile as open import binwalk.core.plugin
class PFSCommon(object): class PFSCommon(object):
...@@ -23,13 +23,13 @@ class PFS(PFSCommon): ...@@ -23,13 +23,13 @@ class PFS(PFSCommon):
def __init__(self, fname, endianess='<'): def __init__(self, fname, endianess='<'):
self.endianess = endianess self.endianess = endianess
self.meta = open(fname, 'rb') self.meta = binwalk.core.common.BlockFile(fname, 'rb')
header = self.meta.read(self.HEADER_SIZE) header = self.meta.read(self.HEADER_SIZE)
self.file_list_start = self.meta.tell() self.file_list_start = self.meta.tell()
self.num_files = self._make_short(header[-2:], endianess) self.num_files = self._make_short(header[-2:], endianess)
self.node_size = self._get_fname_len() + 12 self.node_size = self._get_fname_len() + 12
def _get_fname_len(self, bufflen=128): def _get_fname_len(self, bufflen=128):
"""Returns the number of bytes designated for the filename.""" """Returns the number of bytes designated for the filename."""
buff = self.meta.peek(bufflen) buff = self.meta.peek(bufflen)
...@@ -38,7 +38,7 @@ class PFS(PFSCommon): ...@@ -38,7 +38,7 @@ class PFS(PFSCommon):
if b != '\0': if b != '\0':
return strlen+i return strlen+i
return bufflen return bufflen
def _get_node(self): def _get_node(self):
"""Reads a chunk of meta data from file and returns a PFSNode.""" """Reads a chunk of meta data from file and returns a PFSNode."""
data = self.meta.read(self.node_size) data = self.meta.read(self.node_size)
...@@ -80,7 +80,7 @@ class PFSExtractor(binwalk.core.plugin.Plugin): ...@@ -80,7 +80,7 @@ class PFSExtractor(binwalk.core.plugin.Plugin):
Extractor for known PFS/0.9 File System Formats. Extractor for known PFS/0.9 File System Formats.
""" """
MODULES = ['Signature'] MODULES = ['Signature']
def init(self): def init(self):
if self.module.extractor.enabled: if self.module.extractor.enabled:
self.module.extractor.add_rule(regex='^pfs filesystem', self.module.extractor.add_rule(regex='^pfs filesystem',
...@@ -96,16 +96,22 @@ class PFSExtractor(binwalk.core.plugin.Plugin): ...@@ -96,16 +96,22 @@ class PFSExtractor(binwalk.core.plugin.Plugin):
def extractor(self, fname): def extractor(self, fname):
fname = os.path.abspath(fname) fname = os.path.abspath(fname)
out_dir = binwalk.core.common.unique_file_name(os.path.join(os.path.dirname(fname), "pfs-root"))
try: try:
with PFS(fname) as fs: with PFS(fname) as fs:
# The end of PFS meta data is the start of the actual data # The end of PFS meta data is the start of the actual data
data = open(fname, 'rb') data = binwalk.core.common.BlockFile(fname, 'rb')
data.seek(fs.get_end_of_meta_data()) data.seek(fs.get_end_of_meta_data())
for entry in fs.entries(): for entry in fs.entries():
self._create_dir_from_fname(entry.fname) outfile_path = os.path.join(out_dir, entry.fname)
outfile = open(entry.fname, 'wb') if not outfile_path.startswith(out_dir):
outfile.write(data.read(entry.fsize)) binwalk.core.common.warning("Unpfs extractor detected directory traversal attempt for file: '%s'. Refusing to extract." % outfile_path)
outfile.close() else:
self._create_dir_from_fname(outfile_path)
outfile = binwalk.core.common.BlockFile(outfile_path, 'wb')
outfile.write(data.read(entry.fsize))
outfile.close()
data.close() data.close()
except KeyboardInterrupt as e: except KeyboardInterrupt as e:
raise e raise e
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment