Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better UEFI extractor #374

Merged
merged 12 commits into from
Nov 20, 2022
5 changes: 4 additions & 1 deletion helpers/helpers_emba_dependency_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,10 @@ dependency_check()

check_dep_tool "ubireader image extractor" "ubireader_extract_images"
check_dep_tool "ubireader file extractor" "ubireader_extract_files"


# UEFI
check_dep_tool "UEFI image extractor" "$EXT_DIR""/UEFITool/UEFIExtract"
BenediktMKuehne marked this conversation as resolved.
Show resolved Hide resolved

if function_exists F20_vul_aggregator; then
# CVE-search
# TODO change to portcheck and write one for external hosts
Expand Down
2 changes: 2 additions & 0 deletions installer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ if [[ "$CVE_SEARCH" -ne 1 ]] || [[ "$DOCKER_SETUP" -ne 1 ]] || [[ "$IN_DOCKER" -

IP18_qnap_decryptor

IP35_uefi_extraction

IP61_unblob

IP99_binwalk_default
Expand Down
50 changes: 50 additions & 0 deletions installer/IP35_uefi_extraction.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/bash

# EMBA - EMBEDDED LINUX ANALYZER
#
# Copyright 2020-2022 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
#
# Author(s): Benedikt Kuehne

# Description: Installs UEFIExtract from https://github.com/LongSoft/UEFITool/releases
BenediktMKuehne marked this conversation as resolved.
Show resolved Hide resolved
# into external/UEFITool/UEFIExtract

IP35_uefi_extraction() {
module_title "${FUNCNAME[0]}"


INSTALL_APP_LIST=()

print_file_info "UEFIExtract_NE_A62_linux_x86_64.zip" "Release-version A62" "https://github.com/LongSoft/UEFITool/releases/download/A62/UEFIExtract_NE_A62_linux_x86_64.zip" "external/UEFITool/UEFIExtract_NE_A62_linux_x86_64.zip"
print_tool_info "unzip" 1

if [[ "$LIST_DEP" -eq 1 ]] || [[ $DOCKER_SETUP -eq 1 ]]; then
ANSWER=("n")
else
echo -e "\\n""$MAGENTA""$BOLD""UEFI Extraction Tool"" will be downloaded (if not already on the system) installed!""$NC"
ANSWER=("y")
fi

case ${ANSWER:0:1} in
y|Y )
apt-get install "${INSTALL_APP_LIST[@]}" -y --no-install-recommends
if ! [[ -d external/UEFITool ]]; then
mkdir external/UEFITool
fi
download_file "UEFIExtract_NE_A62_linux_x86_64.zip" "https://github.com/LongSoft/UEFITool/releases/download/A62/UEFIExtract_NE_A62_linux_x86_64.zip" "external/UEFITool/UEFIExtract_NE_A62_linux_x86_64.zip"
if [[ -f "external/UEFITool/UEFIExtract_NE_A62_linux_x86_64.zip" ]]; then
if ! [[ -f external/UEFITool/UEFIExtract ]]; then
unzip external/UEFITool/UEFIExtract_NE_A62_linux_x86_64.zip -d external/UEFITool
fi
else
echo -e "$ORANGE""UEFITool installation failed - check it manually""$NC"
fi
;;
esac
}
12 changes: 10 additions & 2 deletions installer/helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,20 @@ print_pip_info() {

print_file_info()
{
local CONTENT_LENGTH=""
local FILE_SIZE=0
echo -e "\\n""$ORANGE""$BOLD""${1:-}""$NC"
if [[ -n "${2:-}" ]] ; then
echo -e "Description: ""${2:-}"
fi
# echo "$(wget "${3}" --spider --server-response -O -)"
FILE_SIZE=$(("$(wget "${3:-}" --no-check-certificate --spider --server-response 2>&1 | sed -ne '/.ontent-.ength/{s/.*: //;p}' | sed '$!d' || true)"))
CONTENT_LENGTH=$(wget "${3:-}" --no-check-certificate --spider --server-response --output-file=./.wget.log 2>&1 | sed -ne '/.ontent-.ength/{s/.*: //;p}' | sed '$!d')
if [[ -n "$CONTENT_LENGTH" ]]; then
FILE_SIZE=$(("$CONTENT_LENGTH"))
else
# try grep from .wget.log
FILE_SIZE=$(("$(sed -ne '/.ontent-.ength/{s/.*: //;p}' ./.wget.log | sed '$!d')"))
fi

if (( FILE_SIZE > 1048576 )) ; then
echo -e "Download-Size: ""$(( FILE_SIZE / 1048576 ))"" MB"
Expand Down Expand Up @@ -213,7 +221,7 @@ download_file()
if [[ "$D_FILE" == "${1:-}" ]] ; then
echo -e "\\n""$ORANGE""$BOLD""Downloading ""${1:-}""$NC"
if ! [[ -f "${3:-}" ]] ; then
wget --no-check-certificate "${2:-}" -O "${3:-}"
wget --no-check-certificate --output-file=./.wget.log "${2:-}" -O "${3:-}"
else
echo -e "$GREEN""${1}"" is already downloaded - no further action performed.""$NC"
fi
Expand Down
12 changes: 12 additions & 0 deletions modules/F50_base_aggregator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ F50_base_aggregator() {
CVE_AGGREGATOR_LOG="f20_vul_aggregator.txt"
F20_EXPLOITS_LOG="$LOG_DIR"/f20_vul_aggregator/exploits-overview.txt
P02_LOG="p02_firmware_bin_file_check.csv"
P35_LOG="p35_uefi_extractor.txt"
S03_LOG="s03_firmware_bin_base_analyzer.txt"
S05_LOG="s05_firmware_details.txt"
S06_LOG="s06_distribution_identification.txt"
Expand Down Expand Up @@ -119,6 +120,11 @@ output_overview() {
write_csv_log "architecture_verified" "unknown" "NA"
write_csv_log "architecture_unverified" "$PRE_ARCH" "NA"
fi
if [[ -n "$EFI_ARCH" ]]; then
print_output "[+] Detected architecture:""$ORANGE"" ""$EFI_ARCH""$NC"
write_link "p99"
write_csv_log "architecture_verified" "$EFI_ARCH" "NA"
fi
else
write_csv_log "architecture_verified" "unknown" "NA"
fi
Expand Down Expand Up @@ -684,6 +690,7 @@ get_data() {
export KNOWN_EXPLOITED_COUNTER=0
export ENTROPY=""
export PRE_ARCH=""
export EFI_ARCH=""
export FILE_ARR_COUNT=0
export DETECTED_DIR=0
export LINUX_DISTRIS=()
Expand Down Expand Up @@ -731,6 +738,11 @@ get_data() {
if [[ -f "$LOG_DIR"/"$P02_LOG" ]]; then
ENTROPY=$(grep -a "Entropy" "$LOG_DIR"/"$P02_LOG" | cut -d\; -f2 | cut -d= -f2 | sed 's/^\ //' || true)
fi
if [[ -f "$LOG_DIR"/"$P35_LOG" ]]; then
EFI_ARCH=$(grep -a "Possible architecture details found" "$LOG_DIR"/"$P35_LOG" | cut -d: -f2 | sed 's/\ //g' | tr '\n' '/' || true)
EFI_ARCH="${EFI_ARCH%\/}"
EFI_ARCH=$(strip_color_codes "$EFI_ARCH")
fi
if [[ -f "$LOG_DIR"/"$S02_LOG" ]]; then
FWHUNTER_CNT=$(grep -a "\[\*\]\ Statistics:" "$LOG_DIR"/"$S02_LOG" | cut -d: -f2 || true)
fi
Expand Down
95 changes: 81 additions & 14 deletions modules/P35_UEFI_extractor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ P35_UEFI_extractor() {

EXTRACTION_DIR="$LOG_DIR"/firmware/uefi_extraction/

if [[ "$UEFI_AMI_CAPSULE" -gt 0 ]]; then
ami_extractor "$FIRMWARE_PATH" "$EXTRACTION_DIR"
fi
# if [[ "$UEFI_AMI_CAPSULE" -gt 0 ]]; then
# ami_extractor "$FIRMWARE_PATH" "$EXTRACTION_DIR"
# else
uefi_extractor "$FIRMWARE_PATH" "$EXTRACTION_DIR"
# fi

if [[ "$FILES_UEFI" -gt 0 ]]; then
MD5_DONE_DEEP+=( "$(md5sum "$FIRMWARE_PATH" | awk '{print $1}')" )
Expand All @@ -42,36 +44,101 @@ P35_UEFI_extractor() {
fi
}

ami_extractor() {
sub_module_title "AMI capsule extractor"
# TODO marked for deletion
# ami_extractor() {
# sub_module_title "AMI capsule extractor"
#
# local FIRMWARE_PATH_="${1:-}"
# local EXTRACTION_DIR_="${2:-}"
# local DIRS_UEFI=0
# local FIRMWARE_NAME_=""
#
# if ! [[ -f "$FIRMWARE_PATH_" ]]; then
# print_output "[-] No file for extraction provided"
# return
# fi
#
# FIRMWARE_NAME_="$(basename "$FIRMWARE_PATH_")"
#
# echo -ne '\n' | python3 "$EXT_DIR"/BIOSUtilities/AMI_PFAT_Extract.py -o "$EXTRACTION_DIR_" "$FIRMWARE_PATH_" &> "$LOG_PATH_MODULE"/uefi_ami_"$FIRMWARE_NAME_".log
#
# if [[ -f "$LOG_PATH_MODULE"/uefi_ami_"$FIRMWARE_NAME_".log ]]; then
# tee -a "$LOG_FILE" < "$LOG_PATH_MODULE"/uefi_ami_"$FIRMWARE_NAME_".log
# fi
#
# print_ln
# print_output "[*] Using the following firmware directory ($ORANGE$EXTRACTION_DIR_$NC) as base directory:"
# find "$EXTRACTION_DIR_" -xdev -maxdepth 1 -ls | tee -a "$LOG_FILE"
# print_ln
#
# FILES_UEFI=$(find "$EXTRACTION_DIR_" -type f | wc -l)
# DIRS_UEFI=$(find "$EXTRACTION_DIR_" -type d | wc -l)
# print_output "[*] Extracted $ORANGE$FILES_UEFI$NC files and $ORANGE$DIRS_UEFI$NC directories from the firmware image."
# write_csv_log "Extractor module" "Original file" "extracted file/dir" "file counter" "directory counter" "further details"
# write_csv_log "UEFI AMI extractor" "$FIRMWARE_PATH_" "$EXTRACTION_DIR_" "$FILES_UEFI" "$DIRS_UEFI" "NA"
# print_ln
# }

uefi_extractor(){
sub_module_title "UEFI Extractor"

local FIRMWARE_PATH_="${1:-}"
local EXTRACTION_DIR_="${2:-}"
local DIRS_UEFI=0

local FIRMWARE_NAME_=""
local UEFI_EXTRACT_REPORT_FILE=""

local UEFI_EXTRACT_BIN="$EXT_DIR""/UEFITool/UEFIExtract"
local FILES_UEFI=0
local DIRS_UEFI=0
local NVARS=0
local PE32_IMAGE=0
local EFI_ARCH=""

if ! [[ -f "$FIRMWARE_PATH_" ]]; then
print_output "[-] No file for extraction provided"
return
fi

FIRMWARE_NAME_="$(basename "$FIRMWARE_PATH_")"
if ! [[ -d "$EXTRACTION_DIR_" ]]; then
mkdir -p "$EXTRACTION_DIR_"
fi
cp "$FIRMWARE_PATH_" "$EXTRACTION_DIR_"
$UEFI_EXTRACT_BIN "$EXTRACTION_DIR_"firmware all &> "$LOG_PATH_MODULE"/uefi_extractor_"$FIRMWARE_NAME_".log
UEFI_EXTRACT_REPORT_FILE="$EXTRACTION_DIR_"firmware.report.txt
mv "$UEFI_EXTRACT_REPORT_FILE" "$LOG_PATH_MODULE"
UEFI_EXTRACT_REPORT_FILE="$LOG_PATH_MODULE"/firmware.report.txt
if [[ -f "$EXTRACTION_DIR_"/firmware ]]; then
rm "$EXTRACTION_DIR_"/firmware
fi

echo -ne '\n' | python3 "$EXT_DIR"/BIOSUtilities/AMI_PFAT_Extract.py -o "$EXTRACTION_DIR_" "$FIRMWARE_PATH_" &> "$LOG_PATH_MODULE"/uefi_ami_"$FIRMWARE_NAME_".log

if [[ -f "$LOG_PATH_MODULE"/uefi_ami_"$FIRMWARE_NAME_".log ]]; then
tee -a "$LOG_FILE" < "$LOG_PATH_MODULE"/uefi_ami_"$FIRMWARE_NAME_".log
if [[ -f "$LOG_PATH_MODULE"/uefi_extractor_"$FIRMWARE_NAME_".log ]]; then
tee -a "$LOG_FILE" < "$LOG_PATH_MODULE"/uefi_extractor_"$FIRMWARE_NAME_".log
fi

print_ln
print_output "[*] Using the following firmware directory ($ORANGE$EXTRACTION_DIR_$NC) as base directory:"
find "$EXTRACTION_DIR_" -xdev -maxdepth 1 -ls | tee -a "$LOG_FILE"
print_output "[*] Using the following firmware directory ($ORANGE${EXTRACTION_DIR_}firmware.dump$NC) as base directory:"
find "$EXTRACTION_DIR_"firmware.dump -xdev -maxdepth 1 -ls | tee -a "$LOG_FILE"
print_ln

FILES_UEFI=$(find "$EXTRACTION_DIR_" -type f | wc -l)
NVARS=$(grep -c "NVAR entry" "$UEFI_EXTRACT_REPORT_FILE")
PE32_IMAGE=$(grep -c "PE32 image" "$UEFI_EXTRACT_REPORT_FILE")
DRIVER_COUNT=$(grep -c "DXE driver" "$UEFI_EXTRACT_REPORT_FILE")
EFI_ARCH=$(find "$EXTRACTION_DIR_" -name 'info.txt' -exec grep 'Machine type:' {} \; | sed -E 's/Machine\ type\:\ //g' | uniq | head -n 1)

if [[ -n "$EFI_ARCH" ]]; then
print_output "[*] Found $ORANGE$PE32_IMAGE$NC PE32 images for architecture $ORANGE$EFI_ARCH$NC drivers."
print_output "[+] Possible architecture details found ($ORANGE UEFI Extractor $NC): $ORANGE$EFI_ARCH$NC"
export EFI_ARCH
BenediktMKuehne marked this conversation as resolved.
Show resolved Hide resolved
backup_var "EFI_ARCH" "$EFI_ARCH"
fi

FILES_UEFI=$(grep -c "File" "$UEFI_EXTRACT_REPORT_FILE")
DIRS_UEFI=$(find "$EXTRACTION_DIR_" -type d | wc -l)
print_output "[*] Extracted $ORANGE$FILES_UEFI$NC files and $ORANGE$DIRS_UEFI$NC directories from the firmware image."
print_output "[*] Found $ORANGE$NVARS$NC NVARS and $ORANGE$DRIVER_COUNT$NC drivers."
write_csv_log "Extractor module" "Original file" "extracted file/dir" "file counter" "directory counter" "further details"
write_csv_log "UEFI AMI extractor" "$FIRMWARE_PATH_" "$EXTRACTION_DIR_" "$FILES_UEFI" "$DIRS_UEFI" "NA"
write_csv_log "UEFI extractor" "$FIRMWARE_PATH_" "$EXTRACTION_DIR_" "$FILES_UEFI" "$DIRS_UEFI" "NA"
print_ln
}