evolution-mail-forensics/extract-and-index-evolution-mail-storage

184 lines
6.8 KiB
Bash

#!/usr/bin/env bash
# Usage: ./extract-and-index-evolution-mail-storage <EWF image>
# or
# bash extract-and-index-evolution-mail-storage <EWF image>
# 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: 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 <EWF image>\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