Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
obsidianforensics committed Apr 24, 2019
2 parents 1896b0c + f5ae1ea commit aaf0a3e
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 46 deletions.
63 changes: 30 additions & 33 deletions hindsight.py
Expand Up @@ -6,19 +6,20 @@
against the data, and then outputs the results in a spreadsheet.
"""

import os
import sys
import time
import datetime
import argparse
import logging
import json
import shutil
import datetime
import importlib
import json
import logging
import os
import pyhindsight
import pyhindsight.plugins
from pyhindsight.analysis import AnalysisSession
from pyhindsight.utils import banner, MyEncoder, format_meta_output, format_plugin_output
import re
import shutil
import sys
import time

# Try to import module for timezone support
try:
Expand Down Expand Up @@ -127,31 +128,27 @@ def write_excel(analysis_session):
def write_sqlite(analysis_session):
output_file = analysis_session.output_name + '.sqlite'

if not os.path.exists(output_file):
analysis_session.generate_sqlite(output_file)
else:
print("\n Database file \"{}\" already exists. Please choose a different output location.\n".format(output_file))

def find_browser_profiles(base_path):
"""Search a path for browser profiles (only Chromium-based at the moment)."""
found_profile_paths = []
base_dir_listing = os.listdir(base_path)

# The 'History' and 'Cookies' SQLite files are kind of the minimum required for most
# Chrome analysis. This approach (checking the file names) is naive but should work.
if {'History', 'Cookies'}.issubset(base_dir_listing):
found_profile_paths.append(base_path)

# Only search sub dirs if the current dir is not a Profile (Profiles are not nested).
else:
for item in base_dir_listing:
item_path = os.path.join(base_path, item)
if os.path.isdir(item_path):
profile_found_in_subdir = find_browser_profiles(item_path)
if profile_found_in_subdir:
found_profile_paths.extend(profile_found_in_subdir)

return found_profile_paths
if os.path.exists(output_file):
if os.path.getsize(output_file) > 0:
print('\nDatabase file "{}" already exists.\n'.format(output_file))
user_input = raw_input('Would you like to (O)verwrite it, (R)ename output file, or (E)xit? ')
over_re = re.compile(r'(^o$|overwrite)', re.IGNORECASE)
rename_re = re.compile(r'(^r$|rename)', re.IGNORECASE)
exit_re = re.compile(r'(^e$|exit)', re.IGNORECASE)
if re.search(exit_re, user_input):
print("Exiting... ")
sys.exit()
elif re.search(over_re, user_input):
os.remove(output_file)
print("Deleted old \"%s\"" % output_file)
elif re.search(rename_re, user_input):
output_file = "{}_1.sqlite".format(output_file[:-7])
print("Renaming new output to {}".format(output_file))
else:
print("Did not understand response. Exiting... ")
sys.exit()

analysis_session.generate_sqlite(output_file)

print(banner)

Expand Down Expand Up @@ -200,7 +197,7 @@ def find_browser_profiles(base_path):
log.debug("Input directory contents: " + str(input_listing))

# Search input directory for browser profiles to analyze
input_profiles = find_browser_profiles(args.input)
input_profiles = analysis_session.find_browser_profiles(args.input)
log.info(" - Found {} browser profile(s): {}".format(len(input_profiles), input_profiles))
analysis_session.profile_paths = input_profiles

Expand Down
56 changes: 43 additions & 13 deletions pyhindsight/analysis.py
Expand Up @@ -139,25 +139,55 @@ def promote_object_to_analysis_session(self, item_name, item_value):
else:
setattr(self, item_name, item_value)

@staticmethod
def is_profile(base_path, existing_files, warn=False):
"""
Log a warning message if any file in `required_files` is missing from
`existing_files`. Return True if all required files are present.
"""
is_profile = True
for required_file in ['History', 'Cookies']:
# This approach (checking the file names) is naive but should work.
if required_file not in existing_files:
if warn:
log.warning("The profile directory {} does not contain the "
"file {}. Analysis may not be very useful."
.format(base_path, required_file))
is_profile = False
return is_profile

def search_subdirs(self, base_path):
"""Recursively search a path for browser profiles"""
found_profile_paths = []
base_dir_listing = os.listdir(base_path)
if self.is_profile(base_path, base_dir_listing):
found_profile_paths.append(base_path)
for item in base_dir_listing:
item_path = os.path.join(base_path, item)
if os.path.isdir(item_path):
profile_found_in_subdir = self.search_subdirs(item_path)
if profile_found_in_subdir:
found_profile_paths.extend(profile_found_in_subdir)
return found_profile_paths

def find_browser_profiles(self, base_path):
"""Search a path for browser profiles (only Chromium-based at the moment)."""
found_profile_paths = []
base_dir_listing = os.listdir(base_path)

# The 'History' and 'Cookies' SQLite files are kind of the minimum required for most
# Chrome analysis. This approach (checking the file names) is naive but should work.
if {'History', 'Cookies'}.issubset(base_dir_listing):
found_profile_paths.append(base_path)

# Only search sub dirs if the current dir is not a Profile (Profiles are not nested).
else:
for item in base_dir_listing:
item_path = os.path.join(base_path, item)
if os.path.isdir(item_path):
profile_found_in_subdir = self.find_browser_profiles(item_path)
if profile_found_in_subdir:
found_profile_paths.extend(profile_found_in_subdir)

# Chrome analysis. Warn if they are not present.
if not self.is_profile(base_path, base_dir_listing, warn=True):
# Only search sub dirs if the current dir is not a Profile (Profiles are not nested).
found_profile_paths.extend(self.search_subdirs(base_path))

# If we did not find any valid Profiles, attempt to process the input
# path as a Profile
if not found_profile_paths:
log.warning("No Profile paths found; processing input path as a Profile")
found_profile_paths = [base_path]

log.debug("Profile paths: " + str(found_profile_paths))
return found_profile_paths

def generate_display_version(self):
Expand Down

0 comments on commit aaf0a3e

Please sign in to comment.