Skip to content

Commit 6c41f28

Browse files
author
Tim Walsh
committed
Add options to retain logical files
1 parent f700ec8 commit 6c41f28

File tree

3 files changed

+44
-27
lines changed

3 files changed

+44
-27
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Disk Image Processor
22

33
Analyze disk images and/or create ready-to-ingest SIPs from a directory of disk images and related files.
4-
Version: 0.6.0 (beta)
4+
Version: 0.6.1 (beta)
55

66
## Usage
77

@@ -28,6 +28,8 @@ The destination directory also contains a "reports" directory containing a sub-d
2828
* Text output from "disktype"
2929
* Brunnhilde reports (including logs and reports from clamAV and bulk_extractor)
3030

31+
Optionally, the destination directory may also contain a "files" directory, containing exported logical files from each recognized disk image in the source.
32+
3133
Because "Analysis" mode runs bulk_extractor against each disk, this process can take a while.
3234

3335
### Processing

diskimageanalyzer.py

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def write_to_spreadsheet(disk_result, spreadsheet_path):
250250

251251
# parse arguments
252252
parser = argparse.ArgumentParser()
253-
parser.add_argument("-f", "--forensic", help="Use fiwalk and tsk_recover", action="store_true")
253+
parser.add_argument("-k", "--keepfiles", help="Retain exported logical files from each disk", action="store_true")
254254
parser.add_argument("source", help="Path to folder containing disk images")
255255
parser.add_argument("destination", help="Output destination")
256256
args = parser.parse_args()
@@ -262,8 +262,9 @@ def write_to_spreadsheet(disk_result, spreadsheet_path):
262262
if not os.path.exists(destination):
263263
os.makedirs(destination)
264264
diskimages_dir = os.path.join(destination, 'diskimages')
265+
files_dir = os.path.join(destination, 'files')
265266
results_dir = os.path.join(destination, 'reports')
266-
for new_dir in diskimages_dir, results_dir:
267+
for new_dir in diskimages_dir, files_dir, results_dir:
267268
os.makedirs(new_dir)
268269

269270
# make list for unanalyzed disks
@@ -334,16 +335,16 @@ def write_to_spreadsheet(disk_result, spreadsheet_path):
334335
try:
335336
subprocess.check_output(['fiwalk', '-X', fiwalk_file, diskimage])
336337
except subprocess.CalledProcessError as e:
337-
logandprint('ERROR: Fiwalk could not create DFXML for disk. STDERR: %s' % (e.output))
338+
print('ERROR: Fiwalk could not create DFXML for disk. STDERR: %s' % (e.output))
338339

339340
# carve files
340-
temp_dir = os.path.join(disk_dir, 'temp')
341-
if not os.path.exists(temp_dir):
342-
os.makedirs(temp_dir)
341+
disk_files_dir = os.path.join(files_dir, file)
342+
if not os.path.exists(disk_files_dir):
343+
os.makedirs(disk_files_dir)
343344
try:
344-
subprocess.check_output(['tsk_recover', '-a', diskimage, temp_dir])
345+
subprocess.check_output(['tsk_recover', '-a', diskimage, disk_files_dir])
345346
except subprocess.CalledProcessError as e:
346-
logandprint('ERROR: tsk_recover could not carve allocated files from disk. STDERR: %s' % (e.output))
347+
print('ERROR: tsk_recover could not carve allocated files from disk. STDERR: %s' % (e.output))
347348

348349
# rewrite last modified dates of carved files based on values in DFXML
349350
for (event, obj) in Objects.iterparse(fiwalk_file):
@@ -385,15 +386,16 @@ def write_to_spreadsheet(disk_result, spreadsheet_path):
385386
continue
386387

387388
# rewrite last modified date of corresponding file in objects/files
388-
exported_filepath = os.path.join(temp_dir, dfxml_filename)
389+
exported_filepath = os.path.join(disk_files_dir, dfxml_filename)
389390
if os.path.isfile(exported_filepath):
390391
os.utime(exported_filepath, (dfxml_filedate, dfxml_filedate))
391392

392393
# run brunnhilde
393-
subprocess.call("brunnhilde.py -zwb '%s' '%s' brunnhilde" % (temp_dir, disk_dir), shell=True)
394+
subprocess.call("brunnhilde.py -zwb '%s' '%s' brunnhilde" % (disk_files_dir, disk_dir), shell=True)
394395

395-
# remove tmpdir
396-
shutil.rmtree(temp_dir)
396+
# remove disk_files_dir unless keepfiles option selected
397+
if args.keepfiles == False:
398+
shutil.rmtree(disk_files_dir)
397399

398400
elif ('hfs' in disk_fs.lower()) and ('hfs+' not in disk_fs.lower()):
399401
# mount disk image
@@ -404,14 +406,25 @@ def write_to_spreadsheet(disk_result, spreadsheet_path):
404406
try:
405407
subprocess.call("cd /mnt/diskid/ && python3 /usr/share/ccatools/diskimageprocessor/walk_to_dfxml.py > '%s'" % (dfxml_file), shell=True)
406408
except:
407-
logandprint('ERROR: walk_to_dfxml.py unable to generate DFXML for disk %s' % (diskimage))
409+
print('ERROR: walk_to_dfxml.py unable to generate DFXML for disk %s' % (diskimage))
408410

409411
# run brunnhilde
410412
subprocess.call("brunnhilde.py -zwb /mnt/diskid/ '%s' brunnhilde" % (disk_dir), shell=True)
411413

412414
# unmount disk image
413415
subprocess.call('sudo umount /mnt/diskid', shell=True)
414416

417+
# export files to disk_files_dir if keepfiles selected
418+
if args.keepfiles == True:
419+
disk_files_dir = os.path.join(files_dir, file)
420+
if not os.path.exists(disk_files_dir):
421+
os.makedirs(disk_files_dir)
422+
try:
423+
subprocess.check_output(['bash', '/usr/share/hfsexplorer/bin/unhfs', '-v', '-o', disk_files_dir, diskimage])
424+
except subprocess.CalledProcessError as e:
425+
print('ERROR: HFS Explorer could not carve the following files from image: %s' % (e.output))
426+
427+
415428
elif 'udf' in disk_fs.lower():
416429
# mount image
417430
subprocess.call("sudo mount -t udf -o loop '%s' /mnt/diskid/" % (diskimage), shell=True)
@@ -421,32 +434,34 @@ def write_to_spreadsheet(disk_result, spreadsheet_path):
421434
try:
422435
subprocess.call("cd /mnt/diskid/ && python3 /usr/share/ccatools/diskimageprocessor/walk_to_dfxml.py > '%s'" % (dfxml_file), shell=True)
423436
except:
424-
logandprint('ERROR: walk_to_dfxml.py unable to generate DFXML for disk %s' % (diskimage))
437+
print('ERROR: walk_to_dfxml.py unable to generate DFXML for disk %s' % (diskimage))
425438

426439
# write files to tempdir
427-
temp_dir = os.path.join(disk_dir, 'temp')
428-
shutil.copytree('/mnt/diskid/', temp_dir, symlinks=False, ignore=None)
440+
disk_files_dir = os.path.join(disk_dir, 'temp')
441+
shutil.copytree('/mnt/diskid/', disk_files_dir, symlinks=False, ignore=None)
429442

430-
# change file permissions in temp_dir
431-
subprocess.call("find '%s' -type d -exec chmod 755 {} \;" % (temp_dir), shell=True)
432-
subprocess.call("find '%s' -type f -exec chmod 644 {} \;" % (temp_dir), shell=True)
443+
# change file permissions in disk_files_dir
444+
subprocess.call("find '%s' -type d -exec chmod 755 {} \;" % (disk_files_dir), shell=True)
445+
subprocess.call("find '%s' -type f -exec chmod 644 {} \;" % (disk_files_dir), shell=True)
433446

434447
# unmount disk image
435448
subprocess.call('sudo umount /mnt/diskid', shell=True)
436449

437450
# run brunnhilde
438-
subprocess.call("brunnhilde.py -zwb '%s' '%s' brunnhilde" % (temp_dir, disk_dir), shell=True)
451+
subprocess.call("brunnhilde.py -zwb '%s' '%s' brunnhilde" % (disk_files_dir, disk_dir), shell=True)
439452

440-
# delete tempdir
441-
shutil.rmtree(temp_dir)
453+
# remove disk_files_dir unless keepfiles option selected
454+
if args.keepfiles == False:
455+
shutil.rmtree(disk_files_dir)
442456

443457
else:
444458
# add disk to unanalyzed list
445-
unanalyzed.append(diskimage)
446-
459+
unanalyzed.append(diskimage)
447460

448-
# delete disk images
461+
# delete temp directories
449462
shutil.rmtree(diskimages_dir)
463+
if args.keepfiles == False:
464+
shutil.rmtree(files_dir)
450465

451466
# create analysis spreadsheet
452467
spreadsheet_path = os.path.join(destination, 'analysis.csv')

main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def __init__(self, parent=None):
2424

2525
def about_dialog(self):
2626
QMessageBox.information(self, "About",
27-
"Disk Image Processor v0.6.0\nTim Walsh, 2017\nMIT License\nhttps://github.com/timothyryanwalsh/cca-diskimageprocessor")
27+
"Disk Image Processor v0.6.1\nTim Walsh, 2017\nMIT License\nhttps://github.com/timothyryanwalsh/cca-diskimageprocessor")
2828

2929
@pyqtSlot()
3030
def readStdOutput(self):

0 commit comments

Comments
 (0)