Modules how to python

From Digital Forensics Framework
Jump to: navigation, search

Python.png

We will here explain how to develop a python module. The purpose of the module is to concatenate two files. You can use the IDE to generate a skeleton for your module.

Contents

Get started

We will first go in the modules/nodes (or wherever you want to put your module) directory of dff sources and create a directory called filescat :

cd dff_sources/modules/nodes
mkdir filescat

Bulb.png

Do not call your module 'test', it can generate some conflicts.

Then we can modify the file dff_sources/modules/nodes/CMakeList.txt and add the line :

add_subdirectory (filescat)

This cmake directives is used to indicate to make command that it must enter the filescat directory during the compilation.

In the directory filescat we will need to create an other file CMakeLists.txt containing :

set(catfiles_srcs
  __init__.py
  catfiles.py
)

install_file(catfiles ${catfiles_srcs})

and a last file called __init__.py containing :

__all__ = ['catfiles']

Python

Once theses two steps are done our environment is ready and we can start coding.

import

First we will have to create a catfiles.py file. In this file, we will add the following imports :

# version of the module
__dff_module_catfiles_version__ = "1.0.0"
 
from struct import unpack
 
from api.vfs import *
from api.module.module import *
from api.types.libtypes import Variant, VList, VMap, Argument, Parameter, typeId
from api.vfs.libvfs import *

class catfiles

In this class, inheriting the class Module, we will define which options the driver will need to run. In our case, the two file names we want to concatenate are passed in parameter to the module :

class catfiles(Module):
"""This module is designed to concatenate 2 files."""
  def __init__(self):
    Module.__init__(self, "catfiles", CatFiles)
 
    # module configuration. We are adding two mandatory arguments, which are the two nodes we will concatenate.
    self.conf.addArgument({"input": Argument.Required|Argument.List|typeId.Node,
                           "name": "files",
                           "description": "these files will be concatenated in the order they are provided",
                           "parameters": {"type": Parameter.Editable,
                                          "minimum": 2,
                                          "maximum": 2}
    self.tags = "Node"

Bulb.png

Your module musts have the same name than the file. For example, if the file is called foo.py, the module has to be named Foo otherwise it won't be loaded properly.

class CatFiles

The second step is to implement the mfso methods, and so create a class inheriting mfso :

class CatFiles(mfso):
    # Constructor. we init the name of the driver. Do not forget the self.__disown()__ or 
    # python garbage collector will delete the object
    def __init__(self):
       mfso.__init__(self, "catfiles")
       self.name = "catfiles"
       self.__disown__()
 
    # the job of the module will be done in this method
    def start(self, args):
 
       # first we get the two nodes passed in parameters to the driver (a list)
       self.files = args['files'].value()
 
       self.file1 = self.files[0]
       self.file2 = self.files[1]
 
       # we concatenate the two names and calculate the total size
       name = self.file1.name() + "-" + self.file2.name()
       size = self.file1.size() + self.file2.size()
 
       # creation of the node corresponding to the concatenated two files (see the class below)
       self.cat_node = CatfilesNode(name, size, None, self, self.file1, self.file2)
 
       # the self.cat_node.__disown__() will insure that python garbage collector wont delete the object
       self.cat_node.__disown__()
 
       # and finally the registerTree
       self.registerTree(self.file1.parent(), self.cat_node)

class CatfilesNode

in this class we will have to implement the fileMapping and extendedAttributes method

class CatfilesNode(Node):
   def __init__(self, name, size, parent, mfso, file1, file2):
      Node.__init__(self, name, size, parent, mfso)
 
      # we will need file1 and file2 in the file mapping so we save them as attributes
      self.file1 = file1
      self.file2 = file2
      self.__disown__() # to avoid python garbage collector to delete the object
 
   # the fileMapping method of the node is called when the node is opened.
   # We push the content of the two nodes (2 chuncks)
   def fileMapping(self, fm):
      fm.push(0, self.file1.size(), self.file1, 0)
      fm.push(self.file1.size(), self.file2.size(), self.file2, 0)
 
   # in the extended attributes we will store the names and sizes of the  two original files
   # so DFF users can be able to see which are the "original" 2 files
   def _attributes(self):
      f1_size = Variant(self.file1.size())
      f2_size = Variant(self.file2.size())
      f1_name = Variant(self.file1.name())
      f2_name = Variant(self.file2.name())
 
      # to avoid a deletion by the garbage collector.
      attr.thisown = False
      f1_size.thisown = False
      f2_size.thisown = False
      f1_name.thisown = False
      f2_name.thisown = False
 
      # and we push our attributes in the attr vmap
      attr = VMap()
      attr.thisown = False
 
      attr["1st file name"] = f1_name
      attr["2nd file name"] = f2_name
      attr["1st file size"] =  f1_size
      attr["2nd file size"] = f2_size
 
      return attr

Conclusion

And that's it ! Nothing complicated.

Personal tools