retdec/scripts/signature-from-library.sh
2017-12-12 18:05:30 +01:00

162 lines
4.3 KiB
Bash
Executable File

#!/bin/bash
SCRIPTPATH="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"
if [ -z "$DECOMPILER_UTILS" ]; then
DECOMPILER_UTILS="$SCRIPTPATH/utils.sh"
fi
. "$DECOMPILER_UTILS"
##
## Prints help to stream $1.
##
print_help() {
echo -e "Create Yara rules file from static libraries." > "$1"
echo -e "Usage: signature-from-library.sh [OPTIONS] -o OUTPUT INPUT_1 [... INPUT_N]\n" > "$1"
echo "Options:" > "$1"
echo " -n --no-cleanup" > "$1"
echo " Temporary .pat files will be kept." > "$1"
echo "" > "$1"
echo " -o --output path" > "$1"
echo " Where result(s) will be stored." > "$1"
echo "" > "$1"
echo " -m --min-pure unsigned" > "$1"
echo " Minimum pure information needed for patterns (default 16)." > "$1"
echo "" > "$1"
echo " -i --ignore-nops opcode" > "$1"
echo " Ignore trailing NOPs when computing (pure) size." > "$1"
echo "" > "$1"
echo " -l --logfile" > "$1"
echo " Add log-file with '.log' suffix from pat2yara." > "$1"
echo "" > "$1"
echo " -b --bin2pat-only" > "$1"
echo " Stop after bin2pat." > "$1"
echo "" > "$1"
}
##
## Exit with error message $1 and clean up temporary files.
##
die_with_error_and_cleanup() {
# Cleanup.
[ ! "$NO_CLEANUP" ] && temporary_files_cleanup
print_error_and_die "$1."
}
##
## Removes temporary files.
##
temporary_files_cleanup() {
rm -r "$DIR_PATH"
}
# Parse arguments.
while [[ $# -gt 0 ]]
do
case $1 in
-h|--help)
print_help /dev/stdout
exit 0;;
-n|--no-cleanup)
NO_CLEANUP=1
shift;;
-l|--logfile)
DO_LOGFILE=1
shift;;
-b|--bin2pat-only)
BIN2PAT_ONLY=1
shift;;
-m|--min-pure)
[ "$MIN_PURE" ] && die_with_error_and_cleanup "duplicate option: --min-pure"
MIN_PURE=$2
shift 2;;
-i|--ignore-nops)
[ "$IGNORE_NOP" ] && die_with_error_and_cleanup "duplicate option: --ignore-nops"
IGNORE_NOP="--ignore-nops"
IGNORE_OPCODE=$2
shift 2;;
-o|--output)
[ "$OUT_PATH" ] && die_with_error_and_cleanup "duplicate option: --output"
OUT_PATH=$2
shift 2;;
*)
! [ -f "$1" ] && die_with_error_and_cleanup "input '$1' is not a valid file nor argument"
INPUT_LIBS+=("$1")
shift;;
esac
done
# Check inputs.
if [ "${#INPUT_LIBS[@]}" -lt 1 ]; then
die_with_error_and_cleanup "no input files"
fi
# Output directory - compulsory argument.
if [ -z "$OUT_PATH" ]; then
die_with_error_and_cleanup "option -o|--output is compulsory"
else
FILE_PATH="$OUT_PATH"
DIR="$(dirname "$(readlink -f "$FILE_PATH")")"
DIR_PATH=$(mktemp -d "$DIR/XXXXXXXXX")
fi
# Set default --min-pure information argument.
if ! [ "$MIN_PURE" ]; then
MIN_PURE="16"
fi
# Create .pat files for every library.
for LIB_PATH in "${INPUT_LIBS[@]}"; do
# Check for invalid archives.
if ! is_valid_archive "$LIB_PATH"; then
echo "ignoring file '$LIB_PATH' - not valid archive"
continue
fi
# Get library name for .pat file.
LIB_NAME_TMP="$(basename "$LIB_PATH")"
LIB_NAME="${LIB_NAME_TMP%%.*}"
# Create sub-directory for object files.
OBJECT_DIRECTORY="$DIR_PATH/$LIB_NAME-objects"
OBJECT_DIRECTORIES+=("$OBJECT_DIRECTORY")
mkdir "$OBJECT_DIRECTORY"
# Extract all files to temporary folder.
"$AR" "$LIB_PATH" --extract --output "$OBJECT_DIRECTORY"
# List all extracted objects.
IFS_OLD="$IFS"
IFS=$'\n'
OBJECTS=($(find "$OBJECT_DIRECTORY" -type f))
IFS="$IFS_OLD"
# Extract patterns from library.
PATTERN_FILE="$DIR_PATH/$LIB_NAME.pat"
PATTERN_FILES+=("$PATTERN_FILE")
"$BIN2PAT" -o "$PATTERN_FILE" "${OBJECTS[@]}"
[ "$?" -ne "0" ] && die_with_error_and_cleanup "utility bin2pat failed when processing '$LIB_PATH'"
# Remove extracted objects continuously.
[ ! "$NO_CLEANUP" ] && rm -r "$OBJECT_DIRECTORY"
done
# Skip second step - only .pat files will be created.
if [ "$BIN2PAT_ONLY" ]; then
[ ! "$NO_CLEANUP" ] && rm -f "${OBJECT_DIRECTORIES[@]}"
exit 0
fi
# Create final .yara file from .pat files.
if [ "$DO_LOGFILE" ]; then
"$PAT2YARA" "${PATTERN_FILES[@]}" --min-pure $MIN_PURE -o "$FILE_PATH" -l "$FILE_PATH.log" $IGNORE_NOP $IGNORE_OPCODE
[ "$?" -ne "0" ] && die_with_error_and_cleanup "utility pat2yara failed"
else
"$PAT2YARA" "${PATTERN_FILES[@]}" --min-pure $MIN_PURE -o "$FILE_PATH" $IGNORE_NOP $IGNORE_OPCODE
[ "$?" -ne "0" ] && die_with_error_and_cleanup "utility pat2yara failed"
fi
# Do cleanup.
[ ! "$NO_CLEANUP" ] && temporary_files_cleanup