Skip to content

Development

Joachim Metz edited this page May 10, 2015 · 14 revisions

Obtaining the version

pytsk3 (as of February 17, 2014) comes with 2 different version numbers:

  • the SleuthKit version it was built against;
  • the version of the pytsk3 code.

To obtain the SleuthKit version:

import pytsk3

print pytsk3.TSK_VERSION_STR

To obtain the pytsk3 version:

import pytsk3

print pytsk3.get_version()

Iterating volumes

This is an example of how to replicate the mmls functionality.

import pytsk3

img = pytsk3.Img_Info(url="/path/to/image/file")
volume = pytsk3.Volume_Info(img)

for part in volume:
    print part.addr, part.desc.decode('utf-8'), part.start, part.len

Note: at the moment the volume object is an iterator object that will change state if accessed

To retain the state e.g. in a nested construction use:

list(volume)

Note: that part.desc contains an UTF-8 encoded byte stream.

Accessing a file system

To access a file system via pytsk3 run:

import pytsk3

img = pytsk3.Img_Info(url="/path/to/image/file")
fs = pytsk3.FS_Info(img)

When you try to access a file system make sure that the image object (img) contains a file system. If not you can pass pytsk3.FS_Info a byte offset of where the volume containing the file system starts, e.g.

fs_offset = 2048 * 512
fs = pytsk3.FS_Info(img, offset=fs_offset)

Getting a file entry

The term "file entry" is used to indicates any "entry" the file system can define e.g. a file, a directory, a symbolic link, etc.

To access a specific file entry within a file system by path:

file_entry = fs.open("/Windows/MyFile.txt")

A file entry can also be accessed based on its "inode":

file_entry = fs.open_meta(inode=15)

Note: that the term inode applied to the abstraction the SleuthKit provides, which can also apply to file systems that do not define inodes e.g. NTFS.

Note that there is a difference between open and open_meta, from: http://www.sleuthkit.org/sleuthkit/docs/api-docs/fspage.html

The tsk_fs_file_open_meta() function takes a metadata address as an argument and returns a TSK_FS_FILE structure. The TSK_FS_FILE::name pointer will be NULL because the file name was not used to open the file and, for efficiency, TSK does not search the directory tree to locate the file name that points to the metadata address.

Determining the file entry type

The file entry type is stored in the attribute:

file_entry.info.meta.type

Note that not every file entry necessarily has the .info or .info.meta property.

This attribute contains a value of pytsk3.TSK_FS_META_TYPE_ENUM, e.g. to determine if a file entry is a "regular" file.

if file_entry.info.meta.type == pytsk3.TSK_FS_META_TYPE_REG:
    print "A file :)"
else:
    print "Not a file :("

Determining the file entry address

The file entry address is stored in the attribute:

file_entry.info.meta.addr

Note that not every file entry necessarily has the .info or .info.meta property.

The address is also referred to as the inode by the SleuthKit.

Determining the file entry timestamps

The timestamp values contain the number of seconds since January 1, 1970 00:00:00, which often are normalized to UTC but not guaranteed. TODO check if the SleuthKit has an option to pass a timezone.

The file entry access time is stored in the attribute:

file_entry.info.meta.atime

The file entry change time (or entry modification time) is stored in the attribute:

file_entry.info.meta.ctime

The file entry modification time is stored in the attribute:

file_entry.info.meta.mtime

The file entry creation time (or birth time) is stored in the attribute:

file_entry.info.meta.crtime

For file systems that provide a larger granularity there is a nano-attribute available e.g. for the atime:

file_entry.info.meta.atime_nano

Note that the SleuthKit can has conversions issues with timestamps outside the range 1970 - 2038 for NTFS.

Also see: https://github.com/sleuthkit/sleuthkit/pull/323

Accessing a directory

for directory_entry in fs.open_dir(path="/Windows"):
    directory_entry = directory_entry.info.name.name
    try:
      print directory_entry.decode("utf8")
    except UnicodeError:
      pass

Note that not every directory entry necessarily has the .info or .info.name property.

Note that (at the moment January 19, 2014) directory_entry.info.name.name contains a UTF-8 formatted binary string.

Note that this will include the directory entries "." (self), ".." (parent) and entries recovered by the SleuthKit.

Note that the SleuthKit will also expose virtual directories like "/$OrphanFiles"

Accessing a alternate data stream (NTFS)

ads_attribute = None
for attribute in file_entry:
  if attribute.info.name == name_ads:
    ads_attribute = attribute
    break

if ads_attribute:
  file_entry.read_random(
      offset, size, ads_attribute.info.type, ads_attribute.info.id)

The underlying behavior of the SleuthKit for file_entry.read_random() seems to be to read the first available $DATA NTFS attribute in case no default (nameless) $DATA NTFS attribute is available e.g. $Extend$UsnJrnl.

Also see

import pytsk3

help(pytsk3)
help(pytsk3.Img_Info)
help(pytsk3.Volume_Info)
help(pytsk3.FS_Info)

Code samples

Clone this wiki locally