#!/usr/bin/env bash # Usage: ./extract-and-index-evolution-mail-storage # or # bash extract-and-index-evolution-mail-storage # Description: (see scriptname!) # Author: Patrick Neumann (patrick@neumannsland.de) # Version: 0.9 # Date: 07.04.2019 # License: GPL3 # Warranty: This program is distributed WITHOUT ANY WARRANTY # Todo: - # Tests: Forensik Workstation(s): # - macOS 10.13.6 + TSK 4.6.5 (Homebrew) + mu 1.0 (Homebrew) # - ArchLinux + TSK 4.6.5 + mu 1.0 (AUR) # Image(s): # - VirtualBox VM with Linux Mint 19.1 + Evolution 3.28.5 #------------------------------------------------------------------------------- # Simple checks for dependencies: #------------------------------------------------------------------------------- which ifind > /dev/null || ( echo "Please install sleuthkit!" ; exit 1 ) which mu > /dev/null || ( echo "Please install mu!" ; exit 1 ) #=== FUNCTION ================================================================== # NAME: usage # DESCRIPTION: Display help. # PARAMETERS: - #=============================================================================== usage () { printf "Usage:\n" printf " $0 \n" } #------------------------------------------------------------------------------- # Check for one param: #------------------------------------------------------------------------------- if [ "${#}" -ne 1 ]; then echo "Please provide exactly one parameter!" echo usage exit 2 fi #=== CONFIGURATION (params) ==================================================== #------------------------------------------------------------------------------- # Check and set image: #------------------------------------------------------------------------------- if ! file "${1}" | grep -F "EWF" > /dev/null ; then echo "Please provide EWF image!" echo usage exit 3 fi readonly IMG="${1}" #=== CONFIGURATION (dynamic) =================================================== #------------------------------------------------------------------------------- # Find and set home directory: #------------------------------------------------------------------------------- offsets="$( mmls -aM "${IMG}" \ | awk '/^[[:digit:]]{3}:/ { print $3; }' \ | sed 's/0*//' )" for offset in ${offsets} ; do if fsstat -o "${offset}" "${IMG}" \ | grep -E "^Last mounted on: /home$" > /dev/null then home="" readonly S_PRE="" readonly T_PRE="./recovered/home" readonly OFS="${offset}" elif fsstat -o "${offset}" "${IMG}" \ | grep -E "^Last mounted on: /$" > /dev/null then home="$( ifind -o "${offset}" -n "/home" "${IMG}" )" if [ "${home}" != "File not found" ] ; then readonly S_PRE="/home" readonly T_PRE="./recovered" readonly OFS="${offset}" fi else echo "/home not found!" echo echo "Hint:" echo " 1.: assemble RAID and/or LVM" echo " 2.: ewfacquire the file system of /home" echo " 3.: use that image with ${0}" exit 4 fi done #=== CONFIGURATION (user) ====================================================== #------------------------------------------------------------------------------- # Select user: #------------------------------------------------------------------------------- printf "Please select a user:\n" users="$( fls -o "${OFS}" "${IMG}" "${home}" | awk '{ print $NF; }' )" select user in ${users} ; do if [ -n "${user}" ] ; then break fi done #=== CONFIGURATION (static) ==================================================== readonly LOCAL=".local/share/evolution/mail" readonly CACHE=".cache/evolution/mail" DIRS="${S_PRE}/${user}/${LOCAL}/" readonly DIRS="${DIRS} ${S_PRE}/${user}/${CACHE}/" #------------------------------------------------------------------------------- # ... magic ... #------------------------------------------------------------------------------- for DIR in ${DIRS} ; do #----------------------------------------------------------------------------- # Store inode of DIR as start: #----------------------------------------------------------------------------- start="$( ifind -o "${OFS}" -n "${DIR}" "${IMG}" )" if [ "${start}" = "File not found" ] ; then echo "${DIR} not found!" continue fi #----------------------------------------------------------------------------- # Store directory paths recursively under start pipe separated as dirs: #----------------------------------------------------------------------------- dirs="$( fls -o "${OFS}" -u -D -r -m "${DIR}" "${IMG}" "${start}" )" #----------------------------------------------------------------------------- # Create target folder structure recursively: #----------------------------------------------------------------------------- for dir in ${dirs} ; do path="$( echo "${dir}" | cut -d "|" -f 2 )" # the subfolder between "cur" and the mail kill the RFC if ! echo ${path} \ | grep -E ".*/\.cache/evolution/mail/.*/folders/.*/cur/.*" > /dev/null then if ! [ -d "${path}" ] ; then mkdir -p "${T_PRE}${path}" fi fi done #----------------------------------------------------------------------------- # Store file names recursively under start pipe separated as files: #----------------------------------------------------------------------------- files="$( fls -o "${OFS}" -u -F -r -m "${DIR}" "${IMG}" "${start}" )" #----------------------------------------------------------------------------- # Extract files recursively into target folder(s): #----------------------------------------------------------------------------- for file in ${files} ; do inode="$( echo "${file}" | cut -d "|" -f 3 )" name="$( echo "${file}" | cut -d "|" -f 2 )" if ! echo ${name} \ | grep -E ".*/\.cache/evolution/mail/.*/folders/.*/cur/.*/.*" > /dev/null then icat -o "${OFS}" "${IMG}" "${inode}" > "${T_PRE}${name}" else # replace the last slash with a hyphen icat -o "${OFS}" "${IMG}" "${inode}" > "${T_PRE}${name%/*}-${name##*/}" fi done done #------------------------------------------------------------------------------- # Index the local mail storage: #------------------------------------------------------------------------------- if [ -d "${T_PRE}${S_PRE}/${user}/${LOCAL}" ] ; then mu index --quiet --muhome=./mu --maildir="${T_PRE}${S_PRE}/${user}/${LOCAL}" fi #------------------------------------------------------------------------------- # Index the external mail storage(s): #------------------------------------------------------------------------------- accounts="$( find -E "${T_PRE}${S_PRE}/${user}/${CACHE}" -type d -depth 1 \ -iregex ".*/[[:xdigit:]]{40}" -exec basename '{}' \; )" for account in ${accounts} ; do folders="$( find -E "${T_PRE}${S_PRE}/${user}/${CACHE}/${account}/folders" \ -type d -depth 1 -exec basename '{}' \; )" for folder in ${folders} ; do mu index --quiet --muhome=./mu \ --maildir="${T_PRE}${S_PRE}/${user}/${CACHE}/${account}/folders/${folder}" done done exit 0