Package rekall :: Package plugins :: Package filesystems :: Module tsk
[frames] | no frames]

Source Code for Module rekall.plugins.filesystems.tsk

  1  import pytsk3 
  2   
  3  from rekall import addrspace 
  4  from rekall import plugin 
  5  from rekall import obj 
  6  from rekall_lib import utils 
  7  from rekall.plugins import guess_profile 
  8  from rekall.plugins.overlays import basic 
9 10 11 -class FSEntry(object):
12 - def __init__(self, tsk_file):
13 self.tsk_file = tsk_file
14 15 @property
16 - def type(self):
17 return str(self.tsk_file.info.meta.type)[17:]
18 19 @property
20 - def name(self):
21 return self.tsk_file.info.name.name
22 23 @property
24 - def size(self):
25 return self.tsk_file.info.meta.size
26
27 - def read(self, start, size):
28 if self.size > 0: 29 return self.tsk_file.read_random(start, size) 30 else: 31 return ""
32
33 - def __iter__(self):
34 if self.type == "DIR": 35 for directory_entry in self.tsk_file.as_directory(): 36 if directory_entry.info.meta is None: 37 continue 38 name = directory_entry.info.name.name 39 if name in [".", ".."]: 40 continue 41 yield FSEntry(directory_entry)
42
43 44 -class FS(object):
45 - def __init__(self, tsk_fs):
46 self.tsk_fs = tsk_fs
47
48 - def get_fs_entry_by_path(self, path):
49 path = path.replace('\\', '/') 50 tsk_file = self.tsk_fs.open(path) 51 return FSEntry(tsk_file)
52
53 54 -class VolumeSystem(object):
55 """Wrap a TSK_VS_INFO struct.""" 56
57 - def __init__(self, disk, tsk_vs, session=None):
58 self.session = session 59 self._disk = disk 60 self.tsk_vs = tsk_vs 61 self.type = str(self.tsk_vs.info.vstype)[12:]
62 63 @utils.safe_property
64 - def partitions(self):
65 return [Partition(self._disk, x, session=self.session, id=i) 66 for i, x in enumerate(self.tsk_vs)]
67
68 69 -class PartitionAddressSpace(addrspace.RunBasedAddressSpace):
70 """Create a mapping into the partition.""" 71
72 - def __init__(self, partition, **kwargs):
73 super(PartitionAddressSpace, self).__init__(**kwargs) 74 self.partition = partition 75 self.add_run(0, partition.start, partition.length, 76 partition.disk.address_space)
77
78 - def __repr__(self):
79 return "<Partition %s @ %#x>" % (self.partition.id, 80 self.partition.start)
81
82 83 84 -class Partition(object):
85 """Wrap a TSK_VS_PART_INFO object.""" 86
87 - def __init__(self, disk, partition=None, id=0, session=None, 88 filesystem=None):
89 self.tsk_part = partition or obj.NoneObject() 90 self.id = id 91 self.disk = disk 92 self.session = session 93 self.filesystem = filesystem or obj.NoneObject("No filesystem") 94 if (filesystem == None and 95 self.tsk_part.flags == pytsk3.TSK_VS_PART_FLAG_ALLOC): 96 try: 97 address_space = self.get_partition_address_space() 98 filesystem = pytsk3.FS_Info(AS_Img_Info(address_space)) 99 self.filesystem = FS(filesystem) 100 except IOError: 101 pass
102
104 return PartitionAddressSpace( 105 session=self.session, partition=self)
106 107 @utils.safe_property
108 - def start(self):
109 return (self.tsk_part.start * self.disk.block_size)
110 111 @utils.safe_property
112 - def length(self):
113 return (self.tsk_part.len * self.disk.block_size)
114
115 116 -class Disk(object):
117 - def __init__(self, address_space, session=None):
118 self.session = session 119 self.block_size = 512 120 121 # The address space of the entire disk. 122 self.address_space = address_space 123 self._img_info = AS_Img_Info(address_space) 124 try: 125 # open as disk image 126 tsk_vs = pytsk3.Volume_Info(self._img_info) 127 self.volume_system = VolumeSystem( 128 self, tsk_vs, session=self.session) 129 self.block_size = tsk_vs.info.block_size 130 self.partitions = self.volume_system.partitions 131 except IOError: 132 # open as partition image 133 self.volume_system = obj.NoneObject("No Volume") 134 self.partitions = [] 135 try: 136 fake_partition = Partition( 137 self, filesystem=FS(pytsk3.FS_Info(self._img_info)), 138 session=self.session) 139 self.partitions.append(fake_partition) 140 except IOError: 141 pass
142
143 - def read(self, offset, size):
144 return self._img_info.read(offset, size)
145
146 147 -class AS_Img_Info(pytsk3.Img_Info):
148 - def __init__(self, address_space):
149 self._as = address_space 150 pytsk3.Img_Info.__init__(self, "")
151
152 - def close(self):
153 self._as.close()
154
155 - def read(self, offset, size):
156 return self._as.read(offset, size)
157
158 - def get_size(self):
159 return self._as.end()
160
161 162 -class TSKProfile(obj.Profile):
163 pass
164
165 166 -class TSKDetector(guess_profile.DetectionMethod):
167 name = "tsk" 168
169 - def Offsets(self):
170 return [0]
171
172 - def DetectFromHit(self, hit, offset, address_space):
173 _ = offset 174 disk = Disk(address_space, session=self.session) 175 if len(disk.partitions) > 0: 176 # Select a partition to make the default. Users can change 177 # partitions using the cc plugin. 178 self.session.SetParameter("disk", disk) 179 profile = TSKProfile(session=self.session) 180 for partition in disk.partitions: 181 if partition.filesystem.tsk_fs.info.ftype: 182 self.session.logging.debug( 183 "Switching to first partition with filesystem.") 184 cc = SetPartitionContext(session=self.session, 185 profile=profile) 186 cc.SwitchPartition(partition) 187 break 188 189 return profile 190 return None
191
192 193 -class AbstractTSKCommandPlugin(plugin.PhysicalASMixin, 194 plugin.TypedProfileCommand, 195 plugin.ProfileCommand):
196 """Baseclass for all TSK related plugins.""" 197 __abstract = True 198 199 mode = "mode_tsk"
200
201 202 -class SetPartitionContext(AbstractTSKCommandPlugin):
203 name = "cc" 204 interactive = True 205 206 __args = [ 207 dict(name="partition_number", type="IntParser", positional=True, 208 help="The partition to switch to.") 209 ] 210 211 table_header = [ 212 dict(name="message"), 213 ] 214 215 suppress_headers = True 216
217 - def __enter__(self):
218 self.partition_context = self.session.GetParameter("partition_context") 219 return self
220
221 - def __exit__(self, unused_type, unused_value, unused_traceback):
222 self.SwitchPartition(self.partition_context)
223
224 - def SwitchPartition(self, partition=None):
225 disk = self.session.GetParameter("disk") 226 if isinstance(partition, (int, long)): 227 partition = disk.partitions[partition] 228 229 message = ("Switching to partition context: {0} " 230 "(Starts at {1:#x})").format( 231 partition.id, partition.start) 232 233 self.session.SetCache( 234 "default_address_space", 235 partition.get_partition_address_space(), 236 volatile=False) 237 238 # Reset the address resolver for the new context. 239 self.session.SetCache("partition_context", partition, 240 volatile=False) 241 self.session.logging.debug(message) 242 243 return message
244
245 - def collect(self):
246 yield dict( 247 message=self.SwitchPartition(self.plugin_args.partition_number))
248
249 250 -class TskMmls(AbstractTSKCommandPlugin):
251 name = "mmls" 252 253 table_header = [ 254 dict(name="Partition", hidden=True), 255 dict(name="PartId"), 256 dict(name="Type", width=20), 257 dict(name="Filesystem", width=20), 258 dict(name="Offset", style="address"), 259 dict(name="Size", style="address"), 260 ] 261
262 - def collect(self):
263 disk = self.session.GetParameter("disk") 264 block_size = disk.block_size 265 266 for i, partition in enumerate(disk.partitions): 267 yield dict(Partition=partition, 268 PartId=i, 269 Type=partition.tsk_part.desc, 270 Filesystem=partition.filesystem.tsk_fs.info.ftype, 271 Offset=partition.tsk_part.start * block_size, 272 Size=partition.tsk_part.len * block_size, 273 )
274
275 276 -class TSKFls(AbstractTSKCommandPlugin):
277 name = "fls" 278 279 __args = [ 280 dict(name="dir_path", default="/", positional=True, 281 help="Directory path to print content of") 282 ] 283 284 table_header = [ 285 dict(name="name", width=50), 286 dict(name="inode", width=20), 287 dict(name="type", width=10), 288 dict(name="size", width=10), 289 dict(name="mtime", hidden=True, width=20), 290 dict(name="atime", hidden=True, width=20), 291 dict(name="ctime"), 292 ] 293
294 - def collect(self):
295 dir_path = self.plugin_args.dir_path 296 partition = self.session.GetParameter("partition_context") 297 try: 298 for entry in partition.filesystem.get_fs_entry_by_path(dir_path): 299 yield dict(name=entry.name, 300 inode=entry.tsk_file.info.meta.addr, 301 type=entry.type, 302 size=entry.size, 303 ctime=basic.UnixTimeStamp( 304 session=self.session, 305 name="ctime", 306 value=entry.tsk_file.info.meta.ctime), 307 mtime=basic.UnixTimeStamp( 308 session=self.session, 309 name="mtime", 310 value=entry.tsk_file.info.meta.mtime), 311 atime=basic.UnixTimeStamp( 312 session=self.session, 313 name="atime", 314 value=entry.tsk_file.info.meta.atime), 315 ) 316 except IOError as e: 317 raise plugin.PluginError(e)
318