Files
emba/modules/P10_vmdk_extractor.sh

121 lines
4.4 KiB
Bash
Executable File

#!/bin/bash -p
# EMBA - EMBEDDED LINUX ANALYZER
#
# Copyright 2020-2026 Siemens Energy AG
#
# EMBA comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
# welcome to redistribute it under the terms of the GNU General Public License.
# See LICENSE file for usage of this software.
#
# EMBA is licensed under GPLv3
# SPDX-License-Identifier: GPL-3.0-only
#
# Author(s): Michael Messner
# Description: Extracts vmdk images
# Pre-checker threading mode - if set to 1, these modules will run in threaded mode
export PRE_THREAD_ENA=0
P10_vmdk_extractor() {
local lNEG_LOG=0
if [[ "${VMDK_DETECTED:-0}" -eq 1 ]]; then
module_log_init "${FUNCNAME[0]}"
module_title "VMDK (Virtual Machine Disk) extractor"
pre_module_reporter "${FUNCNAME[0]}"
EXTRACTION_DIR="${LOG_DIR}"/firmware/vmdk_extractor
vmdk_extractor "${FIRMWARE_PATH}" "${EXTRACTION_DIR}"
if [[ -s "${P99_CSV_LOG}" ]] && grep -q "^${FUNCNAME[0]};" "${P99_CSV_LOG}"; then
export FIRMWARE_PATH="${LOG_DIR}"/firmware/
backup_var "FIRMWARE_PATH" "${FIRMWARE_PATH}"
lNEG_LOG=1
fi
module_end_log "${FUNCNAME[0]}" "${lNEG_LOG}"
fi
}
vmdk_extractor() {
local lVMDK_PATH_="${1:-}"
local lEXTRACTION_DIR_="${2:-}"
local lMOUNT_DEV=""
local lDEV_NAME=""
local lRET=0
export VMDK_FILES=0
local lVMDK_VIRT_FS_ARR=()
if ! [[ -f "${lVMDK_PATH_}" ]]; then
print_output "[-] No file for extraction provided"
return
fi
sub_module_title "VMDK (Virtual Machine Disk) extractor"
print_output "[*] Enumeration of devices in VMDK images ${ORANGE}${lVMDK_PATH_}${NC}"
disable_strict_mode "${STRICT_MODE}" 0
virt-filesystems -a "${lVMDK_PATH_}" >"${TMP_DIR}"/vmdk.log
lRET="$?"
if [[ "${lRET}" -ne 0 ]]; then
# backup with 7z
7z x -o"${lEXTRACTION_DIR_}" "${lVMDK_PATH_}"
lRET="$?"
if [[ "${lRET}" -ne 0 ]]; then
print_output "[-] WARNING: VMDK filesystem not enumerated"
enable_strict_mode "${STRICT_MODE}" 0
return
fi
else
mapfile -t lVMDK_VIRT_FS_ARR <"${TMP_DIR}"/vmdk.log
for lMOUNT_DEV in "${lVMDK_VIRT_FS_ARR[@]}"; do
print_output "[*] Found device ${ORANGE}${lMOUNT_DEV}${NC}"
done
fi
enable_strict_mode "${STRICT_MODE}" 0
for lMOUNT_DEV in "${lVMDK_VIRT_FS_ARR[@]}"; do
lDEV_NAME=$(basename "${lMOUNT_DEV}")
local lTMP_VMDK_MNT="${LOG_PATH_MODULE}/vmdk_mount_${lDEV_NAME}_${RANDOM}.tgz"
print_output "[*] Mounting and extracting ${ORANGE}${lMOUNT_DEV}${NC} to ${ORANGE}${lTMP_VMDK_MNT}${NC} file"
# if troubles ahead with vmdk mount, remove the error redirection
# guestmount -a "${lVMDK_PATH_}" -m "${lMOUNT_DEV}" --ro "${lTMP_VMDK_MNT}" 2>/dev/null || { print_error "[-] Mounting VMDK ${lVMDK_PATH_} failed ..."; continue; }
guestfish --ro -a "${lVMDK_PATH_}" -m "${lMOUNT_DEV}" tgz-out / "${lTMP_VMDK_MNT}" || {
print_error "[-] Extracting VMDK ${lVMDK_PATH_} failed ..."
continue
}
if [[ -f "${lTMP_VMDK_MNT}" ]]; then
print_output "[*] Extracting ${ORANGE}${lMOUNT_DEV}${NC} to firmware directory ${ORANGE}${lEXTRACTION_DIR_}/${lDEV_NAME}${NC}"
mkdir -p "${lEXTRACTION_DIR_}/${lDEV_NAME}" || true
tar -xvf "${lTMP_VMDK_MNT}" -C "${lEXTRACTION_DIR_}/${lDEV_NAME}" || {
print_error "[-] Extracting VMDK ${lTMP_VMDK_MNT} to ${lEXTRACTION_DIR_}/${lDEV_NAME} failed ..."
continue
}
rm "${lTMP_VMDK_MNT}" || true
fi
done
if [[ -d "${lEXTRACTION_DIR_}" ]]; then
local lVMDK_FILES_ARR=()
local lBINARY=""
local lWAIT_PIDS_P99_ARR=()
mapfile -t lVMDK_FILES_ARR < <(find "${lEXTRACTION_DIR_}" -type f)
print_output "[*] Extracted ${ORANGE}${#lVMDK_FILES_ARR[@]}${NC} files from the firmware image."
print_output "[*] Populating backend data for ${ORANGE}${#lVMDK_FILES_ARR[@]}${NC} files ... could take some time" "no_log"
for lBINARY in "${lVMDK_FILES_ARR[@]}"; do
binary_architecture_threader "${lBINARY}" "P10_vmdk_extractor" &
local lTMP_PID="$!"
lWAIT_PIDS_P99_ARR+=("${lTMP_PID}")
done
wait_for_pid "${lWAIT_PIDS_P99_ARR[@]}"
write_csv_log "Extractor module" "Original file" "extracted file/dir" "file counter" "further details"
write_csv_log "VMDK extractor" "${lVMDK_PATH_}" "${lEXTRACTION_DIR_}" "${#lVMDK_FILES_ARR[@]}" "NA"
# currently unblob has issues with VMDKs. We need to disable it for this extraction process
safe_echo 0 >"${TMP_DIR}"/unblob_disable.cfg
fi
}