1
0
mirror of https://github.com/hashcat/hashcat.git synced 2024-11-01 21:19:04 +00:00
hashcat/tools/test.sh

3293 lines
83 KiB
Bash
Executable File

#!/usr/bin/env bash
##
## Author......: See docs/credits.txt
## License.....: MIT
##
OPTS="--quiet --potfile-disable --runtime 400 --hwmon-disable"
TDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# List of TrueCrypt modes which have test containers
TC_MODES="6211 6212 6213 6221 6222 6223 6231 6232 6233 6241 6242 6243"
# List of VeraCrypt modes which have test containers
VC_MODES="13711 13712 13713 13721 13722 13723 13731 13732 13733 13741 13742 13743 13751 13752 13753 13761 13762 13763 13771 13772 13773"
# List of modes which either are OPTS_TYPE_PT_NEVERCRACK or produce collisions
NEVER_CRACK="9720 9820 14900 18100"
# List of modes which return a different output hash format than the input hash format
NOCHECK_ENCODING="16800 22000"
# LUKS mode has test containers
LUKS_MODE="14600"
# missing hash types: 5200
HASH_TYPES=$(ls "${TDIR}"/test_modules/*.pm | sed -E 's/.*m0*([0-9]+).pm/\1/')
HASH_TYPES="${HASH_TYPES} ${TC_MODES} ${VC_MODES} ${LUKS_MODE}"
HASH_TYPES=$(echo -n "${HASH_TYPES}" | tr ' ' '\n' | sort -u -n | tr '\n' ' ')
VECTOR_WIDTHS="1 2 4 8 16"
HASHFILE_ONLY=$(grep -l OPTS_TYPE_BINARY_HASHFILE "${TDIR}"/../src/modules/module_*.c | sed -E 's/.*module_0*([0-9]+).c/\1/' | tr '\n' ' ')
SLOW_ALGOS=$(grep -l ATTACK_EXEC_OUTSIDE_KERNEL "${TDIR}"/../src/modules/module_*.c | sed -E 's/.*module_0*([0-9]+).c/\1/' | tr '\n' ' ')
OUTD="test_$(date +%s)"
PACKAGE_CMD="7z a"
PACKAGE_FOLDER=""
EXTRACT_CMD="7z x"
mask_3[0]=""
mask_3[1]="?d"
mask_3[2]="?d?d"
mask_3[3]="?d?d?d"
mask_3[4]="?d?d?d?d"
mask_3[5]="?d?d?d?d?d"
mask_3[6]="?d?d?d?d?d?d"
mask_3[7]="?d?d?d?d?d?d?d"
mask_3[8]="?d?d?d?d?d?d?d?d"
mask_3[9]="?d?d?d?d?d?d?d?d?d"
mask_3[10]="?d?d?d?d?d?d?d?d?d?d"
mask_3[11]="?d?d?d?d?d?d?d?d?d?d?d"
mask_3[12]="?d?d?d?d?d?d?d?d?d?d?d?d"
mask_3[13]="?d?d?d?d?d?d?d?d?d?d?d?d?d"
mask_3[14]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d"
mask_3[15]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d"
mask_3[16]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0"
mask_3[17]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00"
mask_3[18]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000"
mask_3[19]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000"
mask_3[20]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00000"
mask_3[21]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000000"
mask_3[22]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000000"
mask_3[23]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00000000"
mask_3[24]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000000000"
mask_3[25]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000000000"
mask_3[26]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00000000000"
mask_3[27]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000000000000"
mask_3[28]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000000000000"
mask_3[29]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00000000000000"
mask_3[30]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000000000000000"
mask_3[31]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000000000000000"
mask_6[0]=""
mask_6[1]=""
mask_6[2]="?d"
mask_6[3]="?d?d"
mask_6[4]="?d?d"
mask_6[5]="?d?d?d"
mask_6[6]="?d?d?d"
mask_6[7]="?d?d?d?d"
mask_6[8]="?d?d?d?d"
mask_6[9]="?d?d?d?d?d"
mask_6[10]="?d?d?d?d?d"
mask_6[11]="?d?d?d?d?d?d"
mask_6[12]="?d?d?d?d?d?d"
mask_6[13]="?d?d?d?d?d?d?d"
mask_6[14]="?d?d?d?d?d?d?d"
mask_6[15]="?d?d?d?d?d?d?d?d"
mask_6[16]="?d?d?d?d?d?d?d?d"
mask_6[17]="?d?d?d?d?d?d?d?d0"
mask_6[18]="?d?d?d?d?d?d?d?d0"
mask_6[19]="?d?d?d?d?d?d?d?d00"
mask_6[20]="?d?d?d?d?d?d?d?d00"
mask_6[21]="?d?d?d?d?d?d?d?d000"
mask_6[22]="?d?d?d?d?d?d?d?d000"
mask_6[23]="?d?d?d?d?d?d?d?d0000"
mask_6[24]="?d?d?d?d?d?d?d?d0000"
mask_6[25]="?d?d?d?d?d?d?d?d00000"
mask_6[26]="?d?d?d?d?d?d?d?d00000"
mask_6[27]="?d?d?d?d?d?d?d?d000000"
mask_6[28]="?d?d?d?d?d?d?d?d000000"
mask_6[29]="?d?d?d?d?d?d?d?d0000000"
mask_6[30]="?d?d?d?d?d?d?d?d0000000"
mask_6[31]="?d?d?d?d?d?d?d?d00000000"
mask_7[0]=""
mask_7[1]=""
mask_7[2]="?d"
mask_7[3]="?d"
mask_7[4]="?d?d"
mask_7[5]="?d?d"
mask_7[6]="?d?d?d"
mask_7[7]="?d?d?d"
mask_7[8]="?d?d?d?d"
mask_7[9]="?d?d?d?d"
mask_7[10]="?d?d?d?d?d"
mask_7[11]="?d?d?d?d?d"
mask_7[12]="?d?d?d?d?d?d"
mask_7[13]="?d?d?d?d?d?d"
mask_7[14]="?d?d?d?d?d?d?d"
mask_7[15]="?d?d?d?d?d?d?d"
mask_7[16]="?d?d?d?d?d?d?d?d"
mask_7[17]="?d?d?d?d?d?d?d?d"
mask_7[18]="?d?d?d?d?d?d?d?d0"
mask_7[19]="?d?d?d?d?d?d?d?d0"
mask_7[20]="?d?d?d?d?d?d?d?d00"
mask_7[21]="?d?d?d?d?d?d?d?d00"
mask_7[22]="?d?d?d?d?d?d?d?d000"
mask_7[23]="?d?d?d?d?d?d?d?d000"
mask_7[24]="?d?d?d?d?d?d?d?d0000"
mask_7[25]="?d?d?d?d?d?d?d?d0000"
mask_7[26]="?d?d?d?d?d?d?d?d00000"
mask_7[27]="?d?d?d?d?d?d?d?d00000"
mask_7[28]="?d?d?d?d?d?d?d?d000000"
mask_7[29]="?d?d?d?d?d?d?d?d000000"
mask_7[30]="?d?d?d?d?d?d?d?d0000000"
mask_7[31]="?d?d?d?d?d?d?d?d0000000"
# Array lookup
# $1: value
# $2: array
# Returns 0 (SUCCESS) if the value is found, 1 otherwise
function is_in_array()
{
for e in "${@:2}"; do
[ "$e" = "$1" ] && return 0
done
return 1
}
function init()
{
if [ "${PACKAGE}" -eq 1 ]; then
echo "[ ${OUTD} ] > Generate tests for hash type $hash_type."
else
echo "[ ${OUTD} ] > Init test for hash type $hash_type."
fi
rm -rf "${OUTD}/${hash_type}.sh" "${OUTD}/${hash_type}_passwords.txt" "${OUTD}/${hash_type}_hashes.txt"
# Exclude TrueCrypt and VeraCrypt testing modes
if is_in_array "${hash_type}" ${TC_MODES}; then
return 0
fi
if is_in_array "${hash_type}" ${VC_MODES}; then
return 0
fi
if [ "${hash_type}" -eq ${LUKS_MODE} ]; then
luks_tests_folder="${TDIR}/luks_tests/"
if [ ! -d "${luks_tests_folder}" ]; then
mkdir -p "${luks_tests_folder}"
fi
luks_first_test_file="${luks_tests_folder}/hashcat_ripemd160_aes_cbc-essiv_128.luks"
if [ ! -f "${luks_first_test_file}" ]; then
luks_tests="hashcat_luks_testfiles.7z"
luks_tests_url="https://hashcat.net/misc/example_hashes/${luks_tests}"
cd "${TDIR}" || exit
# if the file already exists, but was not successfully extracted, we assume it's a broken
# downloaded file and therefore it should be deleted
if [ -f "${luks_tests}" ]; then
rm -f "${luks_tests}"
fi
echo ""
echo "ATTENTION: the luks test files (for -m ${hash_type}) are currently missing on your system."
echo "They will be fetched from ${luks_tests_url}"
echo "Note: this needs to be done only once and could take a little bit to download/extract."
echo "These luks test files are not shipped directly with hashcat because the file sizes are"
echo "particularily large and therefore a bandwidth burner for users who do not run these tests."
echo ""
# download:
if ! wget -q "${luks_tests_url}" >/dev/null 2>/dev/null; then
cd - >/dev/null
echo "ERROR: Could not fetch the luks test files from this url: ${luks_tests_url}"
exit 1
fi
# extract:
${EXTRACT_CMD} "${luks_tests}" >/dev/null 2>/dev/null
# cleanup:
rm -f "${luks_tests}"
cd - >/dev/null || exit
# just to be very sure, check again that (one of) the files now exist:
if [ ! -f "${luks_first_test_file}" ]; then
echo "ERROR: downloading and extracting ${luks_tests} into ${luks_tests_folder} did not complete successfully"
exit 1
fi
fi
return 0
fi
# create list of password and hashes of same type
cmd_file=${OUTD}/${hash_type}.sh
grep " ${hash_type} '" "${OUTD}/all.sh" > "${cmd_file}" 2>/dev/null
# create separate list of password and hashes
sed 's/^echo *|.*$//' "${cmd_file}" | awk '{print $2}' > "${OUTD}/${hash_type}_passwords.txt"
sed 's/^echo *|/echo "" |/' "${cmd_file}" | awk '{print $10}' | cut -d"'" -f2 > "${OUTD}/${hash_type}_hashes.txt"
if [ "${hash_type}" -eq 10300 ]; then
#cat ${OUTD}/${hash_type}.sh | cut -d' ' -f11- | cut -d"'" -f2 > ${OUTD}/${hash_type}_hashes.txt
cut -d"'" -f2 "${OUTD}/${hash_type}.sh" > "${OUTD}/${hash_type}_hashes.txt"
fi
# truncate dicts
rm -rf "${OUTD}/${hash_type}_dict1" "${OUTD}/${hash_type}_dict2"
touch "${OUTD}/${hash_type}_dict1" "${OUTD}/${hash_type}_dict2"
# minimum password length
min=1 # minimum line number from start of the file
min_offset=0 # minimum offset starting from ${min} lines
if [ "${hash_type}" -eq 2500 ]; then
min_offset=7 # means length 8, since we start with 0
elif [ "${hash_type}" -eq 14000 ]; then
min=0
min_offset=4
elif [ "${hash_type}" -eq 14100 ]; then
min=0
min_offset=3
elif [ "${hash_type}" -eq 14900 ]; then
min=0
min_offset=5
elif [ "${hash_type}" -eq 15400 ]; then
min=0
min_offset=3
elif [ "${hash_type}" -eq 16800 ]; then
min_offset=7 # means length 8, since we start with 0
elif [ "${hash_type}" -eq 22000 ]; then
min_offset=7 # means length 8, since we start with 0
fi
# foreach password entry split password in 2 (skip first entry, is len 1)
i=1
while read -r -u 9 pass; do
if [ ${i} -gt ${min} ]; then
# split password, 'i' is the len
p0=$((i / 2))
p1=$((p0 + 1))
# special case (passwords longer than expected)
pass_len=${#pass}
if [ "${pass_len}" -gt 1 ]
then
p1=$((p1 + min_offset))
p0=$((p0 + min_offset))
if [ "${p1}" -gt "${pass_len}" ]; then
p1=${pass_len}
p0=$((p1 - 1))
fi
# add splitted password to dicts
echo "${pass}" | cut -c -${p0} >> "${OUTD}/${hash_type}_dict1"
echo "${pass}" | cut -c ${p1}- >> "${OUTD}/${hash_type}_dict2"
elif [ "${pass_len}" -eq 1 ]; then
echo "${pass}" >> "${OUTD}/${hash_type}_dict1"
echo >> "${OUTD}/${hash_type}_dict2"
else
echo >> "${OUTD}/${hash_type}_dict1"
echo >> "${OUTD}/${hash_type}_dict2"
fi
fi
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_passwords.txt"
min_len=0
if [ "${hash_type}" -eq 2500 ]; then
min_len=7 # means length 8, since we start with 0
elif [ "${hash_type}" -eq 14000 ]; then
min_len=7
elif [ "${hash_type}" -eq 14100 ]; then
min_len=23
elif [ "${hash_type}" -eq 14900 ]; then
min_len=9
elif [ "${hash_type}" -eq 15400 ]; then
min_len=31
elif [ "${hash_type}" -eq 16800 ]; then
min_len=7 # means length 8, since we start with 0
elif [ "${hash_type}" -eq 22000 ]; then
min_len=7 # means length 8, since we start with 0
fi
# generate multiple pass/hash foreach len (2 to 8)
if [ "${MODE}" -ge 1 ]; then
i=2
while [ "$i" -lt 9 ]; do
cmd_file=${OUTD}/${hash_type}_multi_${i}.txt
rm -rf "${cmd_file}" "${OUTD}/${hash_type}_passwords_multi_${i}.txt" "${OUTD}/${hash_type}_hashes_multi_${i}.txt"
rm -rf "${OUTD}/${hash_type}_dict1_multi_${i}" "${OUTD}/${hash_type}_dict2_multi_${i}"
touch "${OUTD}/${hash_type}_dict1_multi_${i}" "${OUTD}/${hash_type}_dict2_multi_${i}"
perl tools/test.pl single "${hash_type}" ${i} > "${cmd_file}"
sed 's/^echo *|.*$//' "${cmd_file}" | awk '{print $2}' > "${OUTD}/${hash_type}_passwords_multi_${i}.txt"
sed 's/^echo *|/echo "" |/' "${cmd_file}" | awk '{print $10}' | cut -d"'" -f2 > "${OUTD}/${hash_type}_hashes_multi_${i}.txt"
if [ "${hash_type}" -eq 10300 ]; then
#cat ${OUTD}/${hash_type}_multi_${i}.txt | cut -d' ' -f11- | cut -d"'" -f2 > ${OUTD}/${hash_type}_hashes_multi_${i}.txt
cut -d"'" -f2 "${OUTD}/${hash_type}_multi_${i}.txt" > "${OUTD}/${hash_type}_hashes_multi_${i}.txt"
fi
# split password, 'i' is the len
p0=$((i / 2))
p1=$((p0 + 1))
p0=$((p0 + min_len))
p1=$((p1 + min_len))
while read -r -u 9 pass; do
# add splitted password to dicts
echo "${pass}" | cut -c -${p0} >> "${OUTD}/${hash_type}_dict1_multi_${i}"
echo "${pass}" | cut -c ${p1}- >> "${OUTD}/${hash_type}_dict2_multi_${i}"
done 9< "${OUTD}/${hash_type}_passwords_multi_${i}.txt"
i=$((i + 1))
done
fi
}
function status()
{
RET=$1
cnt=$((cnt + 1))
if [ "${RET}" -ne 0 ]; then
case ${RET} in
1)
if ! is_in_array "${hash_type}" ${NEVER_CRACK_ALGOS}; then
echo "password not found, cmdline : ${CMD}" >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
e_nf=$((e_nf + 1))
fi
;;
4)
echo "timeout reached, cmdline : ${CMD}" >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
e_to=$((e_to + 1))
;;
10)
if [ "${pass_only}" -eq 1 ]; then
echo "plains not found in output, cmdline : ${CMD}" >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
else
echo "hash:plains not matched in output, cmdline : ${CMD}" >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.tx"t
fi
e_nm=$((e_nm + 1))
;;
*)
echo "! unhandled return code ${RET}, cmdline : ${CMD}" >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
echo "! unhandled return code, see ${OUTD}/logfull.txt for details."
e_nf=$((e_nf + 1))
;;
esac
fi
}
function attack_0()
{
file_only=0
if is_in_array "${hash_type}" ${FILE_BASED_ALGOS}; then
file_only=1
fi
# single hash
if [ "${MODE}" -ne 1 ]; then
e_to=0
e_nf=0
e_nm=0
cnt=0
echo "> Testing hash type $hash_type with attack mode 0, markov ${MARKOV}, single hash, device-type ${TYPE}, vector-width ${VECTOR}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
max=32
if is_in_array "${hash_type}" ${TIMEOUT_ALGOS}; then
max=12
fi
i=0
while read -r -u 9 line; do
if [ "${i}" -ge ${max} ]; then
break
fi
hash="$(echo "${line}" | cut -d\' -f2)"
pass="$(echo "${line}" | cut -d' ' -f2)"
if [ -z "${hash}" ]; then
break
fi
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
echo "${hash}" | base64 -d > "${temp_file}"
hash="${temp_file}"
fi
pass_old=${pass}
if [ "${hash_type}" -eq 20510 ]; then # special case for PKZIP Master Key
pass=$(echo "${pass}" | cut -b 7-) # skip the first 6 chars
fi
CMD="echo ${pass} | ./${BIN} ${OPTS} -a 0 -m ${hash_type} '${hash}'"
echo -n "[ len $((i + 1)) ] " >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(echo "${pass}" | ./${BIN} ${OPTS} -a 0 -m ${hash_type} "${hash}" 2>&1)
pass=${pass_old}
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
if [ "${pass_only}" -eq 1 ]; then
search=":${pass}"
else
search="${hash}:${pass}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
fi
fi
status ${ret}
i=$((i + 1))
done 9< "${OUTD}/${hash_type}.sh"
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 0, Mode single, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
fi
# multihash
if [ "${MODE}" -ne 0 ]; then
e_to=0
e_nf=0
e_nm=0
cnt=0
echo "> Testing hash type $hash_type with attack mode 0, markov ${MARKOV}, multi hash, Device-Type ${TYPE}, vector-width ${VECTOR}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
hash_file=${OUTD}/${hash_type}_hashes.txt
# if file_only -> decode all base64 "hashes" and put them in the temporary file
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
rm -f "${temp_file}"
hash_file=${temp_file}
while read -r base64_hash; do
echo -n "${base64_hash}" | base64 -d >> "${temp_file}"
done < "${OUTD}/${hash_type}_hashes.txt"
fi
CMD="cat ${OUTD}/${hash_type}_passwords.txt | ./${BIN} ${OPTS} -a 0 -m ${hash_type} ${hash_file}"
output=$(./${BIN} ${OPTS} -a 0 -m ${hash_type} ${hash_file} < ${OUTD}/${hash_type}_passwords.txt 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
i=1
while read -r -u 9 hash; do
pass=$(sed -n ${i}p "${OUTD}/${hash_type}_passwords.txt")
if [ "${pass_only}" -eq 1 ]; then
search=":${pass}"
else
search="${hash}:${pass}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
break
fi
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_hashes.txt"
fi
status ${ret}
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 0, Mode multi, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
fi
}
function attack_1()
{
file_only=0
if is_in_array "${hash_type}" ${FILE_BASED_ALGOS}; then
file_only=1
fi
# single hash
if [ "${MODE}" -ne 1 ]; then
e_to=0
e_nf=0
e_nm=0
cnt=0
min=1
if [ "${hash_type}" -eq 14000 ]; then
min=0
elif [ "${hash_type}" -eq 14100 ]; then
min=0
elif [ "${hash_type}" -eq 14900 ]; then
min=0
elif [ "${hash_type}" -eq 15400 ]; then
min=0
fi
echo "> Testing hash type $hash_type with attack mode 1, markov ${MARKOV}, single hash, Device-Type ${TYPE}, vector-width ${VECTOR}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
i=1
while read -r -u 9 hash; do
if [ $i -gt ${min} ]; then
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
echo "${hash}" | base64 -d > "${temp_file}"
hash="${temp_file}"
fi
line_nr=1
if [ "${i}" -gt 1 ]; then
line_nr=$((i - 1))
fi
dict1="${OUTD}/${hash_type}_dict1"
dict2="${OUTD}/${hash_type}_dict2"
if [ "${hash_type}" -eq 20510 ]; then # special case for PKZIP Master Key
line_dict1=$(sed -n ${line_nr}p "${dict1}")
line_dict2=$(sed -n ${line_nr}p "${dict2}")
line_num=$(wc -l "${dict1}" | sed -E 's/ *([0-9]+) .*$/\1/')
line_dict1_orig=${line_dict1}
line_dict2_orig=${line_dict2}
if [ "${#line_dict1}" -ge 6 ]; then
line_dict1=$(echo "${line_dict1}" | cut -b 7-) # skip the first 6 chars
else
# we need to also "steal" some chars from the second dict
num_to_steal=$((6 - ${#line_dict1}))
num_steal_start=$((num_to_steal + 1))
if [ "${#line_dict2}" -ge 6 ]; then
num_to_steal_new=$(((${#line_dict2} - num_to_steal) / 2))
if [ "${num_to_steal_new}" -gt ${num_to_steal} ]; then
num_to_steal=${num_to_steal_new}
fi
fi
line_chars_stolen=$(echo "${line_dict2}" | cut -b -${num_to_steal} | cut -b ${num_steal_start}-)
line_dict1="${line_chars_stolen}"
line_dict2=$(echo "${line_dict2}" | cut -b $((num_to_steal + 1))-)
fi
# finally, modify the dicts accordingly:
tmp_file="${dict1}_mod"
head -n $((line_nr - 1)) "${dict1}" > "${tmp_file}"
echo "${line_dict1}" >> "${tmp_file}"
tail -n $((line_num - line_nr - 1)) "${dict1}" >> "${tmp_file}"
dict1=${tmp_file}
tmp_file="${dict2}_mod"
head -n $((line_nr - 1)) "${dict2}" > "${tmp_file}"
echo "${line_dict2}" >> "${tmp_file}"
tail -n $((line_num - line_nr - 1)) "${dict2}" >> "${tmp_file}"
dict2=${tmp_file}
fi
CMD="./${BIN} ${OPTS} -a 1 -m ${hash_type} '${hash}' ${dict1} ${dict2}"
echo -n "[ len $i ] " >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(./${BIN} ${OPTS} -a 1 -m ${hash_type} "${hash}" ${dict1} ${dict2} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
line_dict1=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict1")
line_dict2=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict2")
if [ "${pass_only}" -eq 1 ]; then
search=":${line_dict1}${line_dict2}"
else
search="${hash}:${line_dict1}${line_dict2}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
fi
fi
status ${ret}
fi
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_hashes.txt"
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 1, Mode single, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
fi
# multihash
if [ "${MODE}" -ne 0 ]; then
# no multi hash checks for these modes (because we only have 1 hash for each of them)
if [ "${hash_type}" -eq 14000 ]; then
return
elif [ "${hash_type}" -eq 14100 ]; then
return
elif [ "${hash_type}" -eq 14900 ]; then
return
elif [ "${hash_type}" -eq 15400 ]; then
return
fi
e_to=0
e_nf=0
e_nm=0
cnt=0
offset=7
if [ "${hash_type}" -eq 5800 ]; then
offset=6
elif [ "${hash_type}" -eq 3000 ]; then
offset=6
fi
hash_file=${OUTD}/${hash_type}_multihash_combi.txt
tail -n ${offset} "${OUTD}/${hash_type}_hashes.txt" > "${hash_file}"
# if file_only -> decode all base64 "hashes" and put them in the temporary file
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
rm -f "${temp_file}"
hash_file=${temp_file}
while read -r base64_hash; do
echo -n "${base64_hash}" | base64 -d >> "${temp_file}"
done < "${OUTD}/${hash_type}_multihash_combi.txt"
fi
CMD="./${BIN} ${OPTS} -a 1 -m ${hash_type} ${hash_file} ${OUTD}/${hash_type}_dict1 ${OUTD}/${hash_type}_dict2"
echo "> Testing hash type $hash_type with attack mode 1, markov ${MARKOV}, multi hash, Device-Type ${TYPE}, vector-width ${VECTOR}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(./${BIN} ${OPTS} -a 1 -m ${hash_type} ${hash_file} ${OUTD}/${hash_type}_dict1 ${OUTD}/${hash_type}_dict2 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
i=0
while read -r -u 9 hash; do
line_nr=1
if [ "${offset}" -gt ${i} ]; then
line_nr=$((offset - i))
fi
line_dict1=$(tail -n ${line_nr} "${OUTD}/${hash_type}_dict1" | head -1)
line_dict2=$(tail -n ${line_nr} "${OUTD}/${hash_type}_dict2" | head -1)
if [ "${pass_only}" -eq 1 ]; then
search=":${line_dict1}${line_dict2}"
else
search="${hash}:${line_dict1}${line_dict2}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
break
fi
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_multihash_combi.txt"
fi
status ${ret}
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 1, Mode multi, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
fi
}
function attack_3()
{
file_only=0
if is_in_array "${hash_type}" ${FILE_BASED_ALGOS}; then
file_only=1
fi
# single hash
if [ "${MODE}" -ne 1 ]; then
e_to=0
e_nf=0
e_nm=0
cnt=0
echo "> Testing hash type $hash_type with attack mode 3, markov ${MARKOV}, single hash, Device-Type ${TYPE}, vector-width ${VECTOR}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
max=8
# some algos have a minimum password length
if [ "${hash_type}" -eq 2500 ]; then
max=7
elif [ "${hash_type}" -eq 14000 ]; then
max=1
elif [ "${hash_type}" -eq 14100 ]; then
max=1
elif [ "${hash_type}" -eq 14900 ]; then
max=1
elif [ "${hash_type}" -eq 15400 ]; then
max=1
elif [ "${hash_type}" -eq 16800 ]; then
max=7
elif [ "${hash_type}" -eq 22000 ]; then
max=7
fi
i=1
while read -r -u 9 hash; do
if [ "${i}" -gt 6 ]; then
if is_in_array "${hash_type}" ${TIMEOUT_ALGOS}; then
break
fi
fi
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
echo "${hash}" | base64 -d > "${temp_file}"
hash="${temp_file}"
fi
# construct a meaningful mask from the password itself:
dict="${OUTD}/${hash_type}_passwords.txt"
pass=$(sed -n ${i}p "${dict}")
# passwords can't be smaller than mask in -a 3 = mask attack
if [ "${#pass}" -lt ${i} ]; then
i=$((i + 1))
continue
fi
pass_part_2=$(echo -n "${pass}" | cut -b $((i + 1))-)
mask=""
if [ "${hash_type}" -eq 14000 ]; then
mask="${pass}"
elif [ "${hash_type}" -eq 14100 ]; then
mask="${pass}"
else
for i in $(seq 1 ${i}); do
mask="${mask}?d"
done
mask="${mask}${pass_part_2}"
fi
if [ "${hash_type}" -eq 20510 ]; then # special case for PKZIP Master Key
if [ "${i}" -le 1 ]; then
i=$((i + 1))
continue
fi
cut_pos=$((i * 2 + 6 - i + 1)) # skip it in groups of 2 ("?d"), at least 6, offset +1 for cut to work
if [ "${i}" -gt 6 ]; then
cut_pos=13 # 6 * ?d + 1 (6 * 2 + 1)
fi
mask=$(echo "${mask}" | cut -b ${cut_pos}-)
fi
CMD="./${BIN} ${OPTS} -a 3 -m ${hash_type} '${hash}' ${mask}"
echo -n "[ len $i ] " >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(./${BIN} ${OPTS} -a 3 -m ${hash_type} "${hash}" ${mask} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
line_dict=$(sed -n ${i}p "${dict}")
if [ "${pass_only}" -eq 1 ]; then
search=":${line_dict}"
else
search="${hash}:${line_dict}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
fi
fi
status ${ret}
if [ $i -eq ${max} ]; then break; fi
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_hashes.txt"
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 3, Mode single, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
fi
# multihash
if [ "${MODE}" -ne 0 ]; then
# no multi hash checks for these modes (because we only have 1 hash for each of them)
if [ "${hash_type}" -eq 14000 ]; then
return
elif [ "${hash_type}" -eq 14100 ]; then
return
elif [ "${hash_type}" -eq 14900 ]; then
return
elif [ "${hash_type}" -eq 15400 ]; then
return
fi
e_to=0
e_nf=0
e_nm=0
cnt=0
increment_max=8
if is_in_array "${hash_type}" ${TIMEOUT_ALGOS}; then
increment_max=5
fi
increment_min=1
if [ "${hash_type}" -eq 2500 ]; then
increment_min=8
increment_max=9
fi
if [ "${hash_type}" -eq 16800 ]; then
increment_min=8
increment_max=9
fi
if [ "${hash_type}" -eq 22000 ]; then
increment_min=8
increment_max=9
fi
# if file_only -> decode all base64 "hashes" and put them in the temporary file
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
rm -f "${temp_file}"
hash_file=${temp_file}
while read -r base64_hash; do
echo -n "${base64_hash}" | base64 -d >> "${temp_file}"
done < "${OUTD}/${hash_type}_multihash_bruteforce.txt"
fi
hash_file=${OUTD}/${hash_type}_multihash_bruteforce.txt
tail_hashes=$(awk "length >= ${increment_min} && length <= ${increment_max}" "${OUTD}/${hash_type}_passwords.txt" | wc -l)
head_hashes=$(awk "length <= ${increment_max}" "${OUTD}/${hash_type}_passwords.txt" | wc -l)
# in very rare cases (e.g. without -O and long passwords) we need to use .hcmask files with the passwords in it
# otherwise there are no good masks we can test for such long passwords
need_hcmask=0
if [ "${tail_hashes}" -gt "${head_hashes}" ]; then
need_hcmask=1
fi
if [ "${tail_hashes}" -lt 1 ]; then
need_hcmask=1
fi
if [ ${need_hcmask} -eq 0 ]; then
head -n "${head_hashes}" "${OUTD}/${hash_type}_hashes.txt" | tail -n "${tail_hashes}" > "${hash_file}"
else
tail_hashes=$(awk "length >= ${increment_min}" "${OUTD}/${hash_type}_passwords.txt" | wc -l)
if [ "${tail_hashes}" -lt 1 ]; then
return
fi
tail -n "${tail_hashes}" "${OUTD}/${hash_type}_hashes.txt" > "${hash_file}"
fi
mask_pos=8
if [ "${increment_min}" -gt ${mask_pos} ]; then
mask_pos=${increment_min}
fi
mask=""
cracks_offset=0
if [ ${need_hcmask} -eq 0 ]; then
cracks_offset=$((head_hashes - tail_hashes))
mask=${mask_3[${mask_pos}]}
else
num_hashes=$(wc -l < "${OUTD}/${hash_type}_hashes.txt")
cracks_offset=$((num_hashes - tail_hashes))
mask=${OUTD}/${hash_type}_passwords.txt # fake hcmask file (i.e. the original dict)
fi
custom_charsets=""
# modify "default" mask if needed (and set custom charset to reduce keyspace)
if [ "${hash_type}" -eq 2500 ]; then
mask="?d?d?d?d?d?1?2?3?4"
charset_1=""
charset_2=""
charset_3=""
charset_4=""
# check positions (here we assume that mask is always composed of non literal chars
# i.e. something like ?d?l?u?s?1 is possible, but ?d?dsuffix not
charset_1_pos=$(expr index "${mask}" 1)
charset_2_pos=$(expr index "${mask}" 2)
charset_3_pos=$(expr index "${mask}" 3)
charset_4_pos=$(expr index "${mask}" 4)
# divide each charset position by 2 since each of them occupies 2 positions in the mask
charset_1_pos=$((charset_1_pos / 2))
charset_2_pos=$((charset_2_pos / 2))
charset_3_pos=$((charset_3_pos / 2))
charset_4_pos=$((charset_4_pos / 2))
i=1
while read -r -u 9 hash; do
pass=$(sed -n ${i}p "${OUTD}/${hash_type}_passwords.txt")
# charset 1
char=$(echo "${pass}" | cut -b ${charset_1_pos})
charset_1=$(printf "%s\n%s\n" "${charset_1}" "${char}")
# charset 2
char=$(echo "${pass}" | cut -b ${charset_2_pos})
charset_2=$(printf "%s\n%s\n" "${charset_2}" "${char}")
# charset 3
char=$(echo "${pass}" | cut -b ${charset_3_pos})
charset_3=$(printf "%s\n%s\n" "${charset_3}" "${char}")
# charset 4
char=$(echo "${pass}" | cut -b ${charset_4_pos})
charset_4=$(printf "%s\n%s\n" "${charset_4}" "${char}")
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_multihash_bruteforce.txt"
# just make sure that all custom charset fields are initialized
if [ -z "${charset_1}" ]; then
charset_1="1"
fi
if [ -z "${charset_2}" ]; then
charset_2="2"
fi
if [ -z "${charset_3}" ]; then
charset_3="3"
fi
if [ -z "${charset_4}" ]; then
charset_4="4"
fi
# unique and remove new lines
charset_1=$(echo "${charset_1}" | sort -u | tr -d '\n')
charset_2=$(echo "${charset_2}" | sort -u | tr -d '\n')
charset_3=$(echo "${charset_3}" | sort -u | tr -d '\n')
charset_4=$(echo "${charset_4}" | sort -u | tr -d '\n')
custom_charsets="-1 ${charset_1} -2 ${charset_2} -3 ${charset_3} -4 ${charset_4}"
fi
if [ "${hash_type}" -eq 16800 ]; then
mask="?d?d?d?d?d?1?2?3?4"
charset_1=""
charset_2=""
charset_3=""
charset_4=""
# check positions (here we assume that mask is always composed of non literal chars
# i.e. something like ?d?l?u?s?1 is possible, but ?d?dsuffix not
charset_1_pos=$(expr index "${mask}" 1)
charset_2_pos=$(expr index "${mask}" 2)
charset_3_pos=$(expr index "${mask}" 3)
charset_4_pos=$(expr index "${mask}" 4)
# divide each charset position by 2 since each of them occupies 2 positions in the mask
charset_1_pos=$((charset_1_pos / 2))
charset_2_pos=$((charset_2_pos / 2))
charset_3_pos=$((charset_3_pos / 2))
charset_4_pos=$((charset_4_pos / 2))
i=1
while read -r -u 9 hash; do
pass=$(sed -n ${i}p "${OUTD}/${hash_type}_passwords.txt")
# charset 1
char=$(echo "${pass}" | cut -b ${charset_1_pos})
charset_1=$(printf "%s\n%s\n" "${charset_1}" "${char}")
# charset 2
char=$(echo "${pass}" | cut -b ${charset_2_pos})
charset_2=$(printf "%s\n%s\n" "${charset_2}" "${char}")
# charset 3
char=$(echo "${pass}" | cut -b ${charset_3_pos})
charset_3=$(printf "%s\n%s\n" "${charset_3}" "${char}")
# charset 4
char=$(echo "${pass}" | cut -b ${charset_4_pos})
charset_4=$(printf "%s\n%s\n" "${charset_4}" "${char}")
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_multihash_bruteforce.txt"
# just make sure that all custom charset fields are initialized
if [ -z "${charset_1}" ]; then
charset_1="1"
fi
if [ -z "${charset_2}" ]; then
charset_2="2"
fi
if [ -z "${charset_3}" ]; then
charset_3="3"
fi
if [ -z "${charset_4}" ]; then
charset_4="4"
fi
# unique and remove new lines
charset_1=$(echo "${charset_1}" | sort -u | tr -d '\n')
charset_2=$(echo "${charset_2}" | sort -u | tr -d '\n')
charset_3=$(echo "${charset_3}" | sort -u | tr -d '\n')
charset_4=$(echo "${charset_4}" | sort -u | tr -d '\n')
custom_charsets="-1 ${charset_1} -2 ${charset_2} -3 ${charset_3} -4 ${charset_4}"
fi
if [ "${hash_type}" -eq 22000 ]; then
mask="?d?d?d?d?d?1?2?3?4"
charset_1=""
charset_2=""
charset_3=""
charset_4=""
# check positions (here we assume that mask is always composed of non literal chars
# i.e. something like ?d?l?u?s?1 is possible, but ?d?dsuffix not
charset_1_pos=$(expr index "${mask}" 1)
charset_2_pos=$(expr index "${mask}" 2)
charset_3_pos=$(expr index "${mask}" 3)
charset_4_pos=$(expr index "${mask}" 4)
# divide each charset position by 2 since each of them occupies 2 positions in the mask
charset_1_pos=$((charset_1_pos / 2))
charset_2_pos=$((charset_2_pos / 2))
charset_3_pos=$((charset_3_pos / 2))
charset_4_pos=$((charset_4_pos / 2))
i=1
while read -r -u 9 hash; do
pass=$(sed -n ${i}p "${OUTD}/${hash_type}_passwords.txt")
# charset 1
char=$(echo "${pass}" | cut -b ${charset_1_pos})
charset_1=$(printf "%s\n%s\n" "${charset_1}" "${char}")
# charset 2
char=$(echo "${pass}" | cut -b ${charset_2_pos})
charset_2=$(printf "%s\n%s\n" "${charset_2}" "${char}")
# charset 3
char=$(echo "${pass}" | cut -b ${charset_3_pos})
charset_3=$(printf "%s\n%s\n" "${charset_3}" "${char}")
# charset 4
char=$(echo "${pass}" | cut -b ${charset_4_pos})
charset_4=$(printf "%s\n%s\n" "${charset_4}" "${char}")
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_multihash_bruteforce.txt"
# just make sure that all custom charset fields are initialized
if [ -z "${charset_1}" ]; then
charset_1="1"
fi
if [ -z "${charset_2}" ]; then
charset_2="2"
fi
if [ -z "${charset_3}" ]; then
charset_3="3"
fi
if [ -z "${charset_4}" ]; then
charset_4="4"
fi
# unique and remove new lines
charset_1=$(echo "${charset_1}" | sort -u | tr -d '\n')
charset_2=$(echo "${charset_2}" | sort -u | tr -d '\n')
charset_3=$(echo "${charset_3}" | sort -u | tr -d '\n')
charset_4=$(echo "${charset_4}" | sort -u | tr -d '\n')
custom_charsets="-1 ${charset_1} -2 ${charset_2} -3 ${charset_3} -4 ${charset_4}"
fi
increment_charset_opts=""
if [ ${need_hcmask} -eq 0 ]; then # the "normal" case without .hcmask file
increment_charset_opts="--increment --increment-min ${increment_min} --increment-max ${increment_max}"
if [ -n "${custom_charsets}" ]; then
increment_charset_opts="${increment_charset_opts} ${custom_charsets}"
fi
fi
CMD="./${BIN} ${OPTS} -a 3 -m ${hash_type} ${increment_charset_opts} ${hash_file} ${mask} "
echo "> Testing hash type $hash_type with attack mode 3, markov ${MARKOV}, multi hash, Device-Type ${TYPE}, vector-width ${VECTOR}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(./${BIN} ${OPTS} -a 3 -m ${hash_type} ${increment_charset_opts} ${hash_file} ${mask} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
i=1
while read -r -u 9 hash; do
line_nr=$((i + cracks_offset))
pass=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_passwords.txt")
if [ "${pass_only}" -eq 1 ]; then
search=":${pass}"
else
search="${hash}:${pass}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
break
fi
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_multihash_bruteforce.txt"
fi
status ${ret}
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 3, Mode multi, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
fi
}
function attack_6()
{
file_only=0
if is_in_array "${hash_type}" ${FILE_BASED_ALGOS}; then
file_only=1
fi
# single hash
if [ "${MODE}" -ne 1 ]; then
e_to=0
e_nf=0
e_nm=0
cnt=0
echo "> Testing hash type $hash_type with attack mode 6, markov ${MARKOV}, single hash, Device-Type ${TYPE}, vector-width ${VECTOR}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
min=1
max=8
mask_offset=0
if [ "${hash_type}" -eq 2500 ]; then
max=6
elif [ "${hash_type}" -eq 14000 ]; then
min=0
max=1
mask_offset=4
elif [ "${hash_type}" -eq 14100 ]; then
min=0
max=1
mask_offset=21
elif [ "${hash_type}" -eq 14900 ]; then
min=0
max=1
mask_offset=5
elif [ "${hash_type}" -eq 15400 ]; then
min=0
max=1
mask_offset=29
elif [ "${hash_type}" -eq 16800 ]; then
max=6
elif [ "${hash_type}" -eq 22000 ]; then
max=6
fi
# special case: we need to split the first line
if [ "${min}" -eq 0 ]; then
pass_part_1=$(sed -n 1p "${OUTD}/${hash_type}_dict1")
pass_part_2=$(sed -n 1p "${OUTD}/${hash_type}_dict2")
pass="${pass_part_1}${pass_part_2}"
echo -n "${pass}" | cut -b -$((mask_offset + 0)) > "${OUTD}/${hash_type}_dict1_custom"
echo -n "${pass}" | cut -b $((mask_offset + 1))- > "${OUTD}/${hash_type}_dict2_custom"
mask_custom=""
for i in $(seq 1 $((${#pass} - mask_offset))); do
if [ "${hash_type}" -eq 14000 ]; then
char=$(echo -n "${pass}" | cut -b $((i + mask_offset)))
mask_custom="${mask_custom}${char}"
elif [ "${hash_type}" -eq 14100 ]; then
char=$(echo -n "${pass}" | cut -b $((i + mask_offset)))
mask_custom="${mask_custom}${char}"
else
mask_custom="${mask_custom}?d"
fi
done
fi
i=1
while read -r -u 9 hash; do
if [ "${i}" -gt 6 ]; then
if is_in_array "${hash_type}" ${TIMEOUT_ALGOS}; then
break
fi
fi
if [ ${i} -gt ${min} ]; then
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
echo "${hash}" | base64 -d > "${temp_file}"
hash="${temp_file}"
fi
dict1=${OUTD}/${hash_type}_dict1
dict2=${OUTD}/${hash_type}_dict2
dict1_a6=${OUTD}/${hash_type}_dict1_a6
cp "${dict1}" "${dict1_a6}"
pass=$(sed -n ${i}p "${OUTD}/${hash_type}_passwords.txt")
if [ "${hash_type}" -eq 20510 ]; then # special case for PKZIP Master Key
pass=$(echo "${pass}" | cut -b 7-) # skip the first 6 chars
fi
if [ ${#pass} -le ${i} ]; then
i=$((i + 1))
continue
fi
echo "${pass}" | cut -b -$((${#pass} - i)) >> "${dict1_a6}"
# the block below is just a fancy way to do a "shuf" (or sort -R) because macOS doesn't really support it natively
# we do not really need a shuf, but it's actually better for testing purposes
rm -f "${dict1_a6}.txt" # temporary file
line_num=$(wc -l "${dict1_a6}" | sed -E 's/ *([0-9]+) .*$/\1/')
sorted_lines=$(seq 1 "${line_num}")
for lines in $(seq 1 "${line_num}"); do
random_num=$((RANDOM % line_num))
random_num=$((random_num + 1)) # sed -n [n]p starts counting with 1 (not 0)
random_line=$(echo -n "${sorted_lines}" | sed -n ${random_num}p)
sed -n ${random_line}p "${dict1_a6}" >> "${dict1_a6}.txt"
# update the temp list of lines
sorted_lines=$(echo -n "${sorted_lines}" | grep -v "^${random_line}$")
line_num=$((line_num - 1))
done
mv "${dict1_a6}.txt" "${dict1_a6}"
# end of shuf/sort -R
mask=""
for j in $(seq 1 ${i}); do
mask="${mask}?d"
done
CMD="./${BIN} ${OPTS} -a 6 -m ${hash_type} '${hash}' ${dict1_a6} ${mask}"
echo -n "[ len $i ] " >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(./${BIN} ${OPTS} -a 6 -m ${hash_type} "${hash}" ${dict1_a6} ${mask} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
line_nr=1
if [ "${i}" -gt 1 ]; then
line_nr=$((i - 1))
fi
line_dict1=$(sed -n ${line_nr}p "${dict1}")
line_dict2=$(sed -n ${line_nr}p "${dict2}")
if [ "${pass_only}" -eq 1 ]; then
search=":${line_dict1}${line_dict2}"
else
search="${hash}:${line_dict1}${line_dict2}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
fi
fi
status ${ret}
fi
if [ "${i}" -eq ${max} ]; then break; fi
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_hashes.txt"
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 6, Mode single, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
rm -f "${OUTD}/${hash_type}_dict1_custom"
rm -f "${OUTD}/${hash_type}_dict2_custom"
fi
# multihash
if [ "${MODE}" -ne 0 ]; then
# no multi hash checks for these modes (because we only have 1 hash for each of them)
if [ "${hash_type}" -eq 14000 ]; then
return
elif [ "${hash_type}" -eq 14100 ]; then
return
elif [ "${hash_type}" -eq 14900 ]; then
return
elif [ "${hash_type}" -eq 15400 ]; then
return
fi
e_to=0
e_nf=0
e_nm=0
cnt=0
max=9
if [ "${hash_type}" -eq 2500 ]; then
max=5
elif [ "${hash_type}" -eq 3000 ]; then
max=8
elif [ "${hash_type}" -eq 7700 ] || [ "${hash_type}" -eq 7701 ]; then
max=8
elif [ "${hash_type}" -eq 8500 ]; then
max=8
elif [ "${hash_type}" -eq 16800 ]; then
max=5
elif [ "${hash_type}" -eq 22000 ]; then
max=5
fi
if is_in_array "${hash_type}" ${TIMEOUT_ALGOS}; then
max=5
if [ "${hash_type}" -eq 3200 ]; then
max=3
fi
fi
i=2
while [ "$i" -lt "$max" ]; do
hash_file=${OUTD}/${hash_type}_hashes_multi_${i}.txt
# if file_only -> decode all base64 "hashes" and put them in the temporary file
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
rm -f "${temp_file}"
hash_file=${temp_file}
while read -r base64_hash; do
echo -n "${base64_hash}" | base64 -d >> "${temp_file}"
done < "${OUTD}/${hash_type}_hashes_multi_${i}.txt"
fi
mask=${mask_6[$i]}
CMD="./${BIN} ${OPTS} -a 6 -m ${hash_type} ${hash_file} ${OUTD}/${hash_type}_dict1_multi_${i} ${mask}"
echo "> Testing hash type $hash_type with attack mode 6, markov ${MARKOV}, multi hash with word len ${i}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(./${BIN} ${OPTS} -a 6 -m ${hash_type} ${hash_file} ${OUTD}/${hash_type}_dict1_multi_${i} ${mask} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
j=1
while read -r -u 9 hash; do
line_dict1=$(sed -n ${j}p "${OUTD}/${hash_type}_dict1_multi_${i}")
line_dict2=$(sed -n ${j}p "${OUTD}/${hash_type}_dict2_multi_${i}")
if [ "${pass_only}" -eq 1 ]; then
search=":${line_dict1}${line_dict2}"
else
search="${hash}:${line_dict1}${line_dict2}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
break
fi
j=$((j + 1))
done 9< "${OUTD}/${hash_type}_hashes_multi_${i}.txt"
fi
status ${ret}
i=$((i + 1))
done
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 6, Mode multi, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
fi
}
function attack_7()
{
file_only=0
if is_in_array "${hash_type}" ${FILE_BASED_ALGOS}; then
file_only=1
fi
# single hash
if [ "${MODE}" -ne 1 ]; then
e_to=0
e_nf=0
e_nm=0
cnt=0
echo "> Testing hash type $hash_type with attack mode 7, markov ${MARKOV}, single hash, Device-Type ${TYPE}, vector-width ${VECTOR}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
min=1
max=8
mask_offset=0
if [ "${hash_type}" -eq 2500 ]; then
max=5
elif [ "${hash_type}" -eq 14000 ]; then
mask_offset=4
min=0
max=1
elif [ "${hash_type}" -eq 14100 ]; then
mask_offset=3
min=0
max=1
elif [ "${hash_type}" -eq 14900 ]; then
mask_offset=5
min=0
max=1
elif [ "${hash_type}" -eq 15400 ]; then
mask_offset=3
min=0
max=1
elif [ "${hash_type}" -eq 16800 ]; then
max=5
elif [ "${hash_type}" -eq 22000 ]; then
max=5
fi
# special case: we need to split the first line
if [ "${min}" -eq 0 ]; then
pass_part_1=$(sed -n 1p "${OUTD}/${hash_type}_dict1")
pass_part_2=$(sed -n 1p "${OUTD}/${hash_type}_dict2")
pass="${pass_part_1}${pass_part_2}"
echo -n "${pass}" | cut -b -$((mask_offset + 0)) > "${OUTD}/${hash_type}_dict1_custom"
echo -n "${pass}" | cut -b $((mask_offset + 1))- > "${OUTD}/${hash_type}_dict2_custom"
mask_custom=""
for i in $(seq 1 ${mask_offset}); do
if [ "${hash_type}" -eq 14000 ]; then
char=$(echo -n "${pass}" | cut -b ${i})
mask_custom="${mask_custom}${char}"
elif [ "${hash_type}" -eq 14100 ]; then
char=$(echo -n "${pass}" | cut -b ${i})
mask_custom="${mask_custom}${char}"
else
mask_custom="${mask_custom}?d"
fi
done
fi
i=1
while read -r -u 9 hash; do
if [ ${i} -gt ${min} ]; then
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
echo "${hash}" | base64 -d > "${temp_file}"
hash="${temp_file}"
fi
mask=${mask_7[$i]}
# adjust mask if needed
line_nr=1
if [ "${i}" -gt 1 ]; then
line_nr=$((i - 1))
fi
if [ "${hash_type}" -eq 2500 ]; then
pass_part_1=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict1")
pass_part_2=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict2")
pass_part_2_len=${#pass_part_2}
pass=${pass_part_1}${pass_part_2}
pass_len=${#pass}
# add first x chars of password to mask and append the (old) mask
mask_len=${#mask}
mask_len=$((mask_len / 2))
mask_prefix=$(echo ${pass} | cut -b -$((pass_len - mask_len - pass_part_2_len)))
mask=${mask_prefix}${mask}
fi
if [ "${hash_type}" -eq 16800 ]; then
pass_part_1=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict1")
pass_part_2=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict2")
pass_part_2_len=${#pass_part_2}
pass=${pass_part_1}${pass_part_2}
pass_len=${#pass}
# add first x chars of password to mask and append the (old) mask
mask_len=${#mask}
mask_len=$((mask_len / 2))
mask_prefix=$(echo "${pass}" | cut -b -$((pass_len - mask_len - pass_part_2_len)))
mask=${mask_prefix}${mask}
fi
if [ "${hash_type}" -eq 22000 ]; then
pass_part_1=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict1")
pass_part_2=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict2")
pass_part_2_len=${#pass_part_2}
pass=${pass_part_1}${pass_part_2}
pass_len=${#pass}
# add first x chars of password to mask and append the (old) mask
mask_len=${#mask}
mask_len=$((mask_len / 2))
mask_prefix=$(echo "${pass}" | cut -b -$((pass_len - mask_len - pass_part_2_len)))
mask=${mask_prefix}${mask}
fi
if [ "${hash_type}" -eq 20510 ]; then
pass_part_1=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict1")
pass_part_2=$(sed -n ${line_nr}p "${OUTD}/${hash_type}_dict2")
pass=${pass_part_1}${pass_part_2}
pass_len=${#pass}
if [ "${pass_len}" -le 6 ]; then
i=$((i + 1))
continue
fi
pass_old=${pass}
pass=$(echo "${pass}" | cut -b 7-) # skip the first 6 chars
mask_len=$((${#mask} / 2))
echo "${pass_old}" | cut -b -$((6 + mask_len)) > "${OUTD}/${hash_type}_dict1_custom"
echo "${pass}" | cut -b $((mask_len + 1))- > "${OUTD}/${hash_type}_dict2_custom"
min=0 # hack to use the custom dict
mask_custom=${mask}
fi
dict1=${OUTD}/${hash_type}_dict1
dict2=${OUTD}/${hash_type}_dict2
if [ "${min}" -eq 0 ]; then
mask=${mask_custom}
dict1=${OUTD}/${hash_type}_dict1_custom
dict2=${OUTD}/${hash_type}_dict2_custom
fi
CMD="./${BIN} ${OPTS} -a 7 -m ${hash_type} '${hash}' ${mask} ${dict2}"
echo -n "[ len $i ] " >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(./${BIN} ${OPTS} -a 7 -m ${hash_type} "${hash}" ${mask} ${dict2} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
line_nr=1
if [ "${i}" -gt 1 ]; then
line_nr=$((i - 1))
fi
line_dict1=$(sed -n ${line_nr}p "${dict1}")
line_dict2=$(sed -n ${line_nr}p "${dict2}")
if [ "${pass_only}" -eq 1 ]; then
search=":${line_dict1}${line_dict2}"
else
search="${hash}:${line_dict1}${line_dict2}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
fi
fi
status ${ret}
fi
if [ $i -eq ${max} ]; then break; fi
i=$((i + 1))
done 9< "${OUTD}/${hash_type}_hashes.txt"
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 7, Mode single, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
rm -f "${OUTD}/${hash_type}_dict1_custom"
rm -f "${OUTD}/${hash_type}_dict2_custom"
fi
# multihash
if [ "${MODE}" -ne 0 ]; then
# no multi hash checks for these modes (because we only have 1 hash for each of them)
if [ "${hash_type}" -eq 14000 ]; then
return
elif [ "${hash_type}" -eq 14100 ]; then
return
elif [ "${hash_type}" -eq 14900 ]; then
return
elif [ "${hash_type}" -eq 15400 ]; then
return
fi
e_to=0
e_nf=0
e_nm=0
cnt=0
max=9
if [ "${hash_type}" -eq 2500 ]; then
max=5
elif [ "${hash_type}" -eq 3000 ]; then
max=8
elif [ "${hash_type}" -eq 7700 ] || [ "${hash_type}" -eq 7701 ]; then
max=8
elif [ "${hash_type}" -eq 8500 ]; then
max=8
elif [ "${hash_type}" -eq 14000 ]; then
max=5
elif [ "${hash_type}" -eq 14100 ]; then
max=5
elif [ "${hash_type}" -eq 14900 ]; then
max=5
elif [ "${hash_type}" -eq 15400 ]; then
max=5
elif [ "${hash_type}" -eq 16800 ]; then
max=5
elif [ "${hash_type}" -eq 22000 ]; then
max=5
fi
if is_in_array "${hash_type}" ${TIMEOUT_ALGOS}; then
max=7
if [ "${hash_type}" -eq 3200 ]; then
max=4
fi
fi
i=2
while [ "$i" -lt "$max" ]; do
hash_file=${OUTD}/${hash_type}_hashes_multi_${i}.txt
dict_file=${OUTD}/${hash_type}_dict2_multi_${i}
mask=${mask_7[$i]}
# if file_only -> decode all base64 "hashes" and put them in the temporary file
if [ "${file_only}" -eq 1 ]; then
temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
rm -f "${temp_file}"
hash_file=${temp_file}
while read -r base64_hash; do
echo -n "${base64_hash}" | base64 -d >> "${temp_file}"
done < "${OUTD}/${hash_type}_hashes_multi_${i}.txt"
# a little hack: since we don't want to have a very large mask (and wpa has minimum length of 8),
# we need to create a temporary dict file on-the-fly and use it like this: [small mask] [long(er) words in dict]
dict_file=${OUTD}/${hash_type}_dict2_multi_${i}_longer
rm -f "${dict_file}"
mask_len=${#mask}
mask_len=$((mask_len / 2))
j=1
while read -r -u 9 hash; do
pass_part_1=$(sed -n ${j}p "${OUTD}/${hash_type}_dict1_multi_${i}")
pass_part_2=$(sed -n ${j}p "${OUTD}/${hash_type}_dict2_multi_${i}")
pass="${pass_part_1}${pass_part_2}"
pass_suffix=$(echo "${pass}" | cut -b $((mask_len + 1))-)
echo "${pass_suffix}" >> "${dict_file}"
j=$((j + 1))
done 9< "${OUTD}/${hash_type}_hashes_multi_${i}.txt"
fi
CMD="./${BIN} ${OPTS} -a 7 -m ${hash_type} ${hash_file} ${mask} ${dict_file}"
echo "> Testing hash type $hash_type with attack mode 7, markov ${MARKOV}, multi hash with word len ${i}." >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(./${BIN} ${OPTS} -a 7 -m ${hash_type} ${hash_file} ${mask} ${dict_file} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
if [ "${ret}" -eq 0 ]; then
j=1
while read -r -u 9 hash; do
line_dict1=$(sed -n ${j}p "${OUTD}/${hash_type}_dict1_multi_${i}")
line_dict2=$(sed -n ${j}p "${OUTD}/${hash_type}_dict2_multi_${i}")
if [ "${pass_only}" -eq 1 ]; then
search=":${line_dict1}${line_dict2}"
else
search="${hash}:${line_dict1}${line_dict2}"
fi
echo "${output}" | grep -F "${search}" >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]; then
ret=10
break
fi
j=$((j + 1))
done 9< "${OUTD}/${hash_type}_hashes_multi_${i}.txt"
fi
status ${ret}
i=$((i + 1))
done
msg="OK"
if [ "${e_nf}" -ne 0 ] || [ "${e_nm}" -ne 0 ]; then
msg="Error"
elif [ "${e_to}" -ne 0 ]; then
msg="Warning"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 7, Mode multi, Device-Type ${TYPE}, Vector-Width ${VECTOR} ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
fi
}
function truecrypt_test()
{
hashType=$1
tcMode=$2
CMD="unset"
case $hashType in
6211)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6211 ${TDIR}/tc_tests/hashcat_ripemd160_aes.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6211 ${TDIR}/tc_tests/hashcat_ripemd160_serpent.tc hashca?l"
;;
2)
CMD="./${BIN} ${OPTS} -a 3 -m 6211 ${TDIR}/tc_tests/hashcat_ripemd160_twofish.tc hashca?l"
;;
esac
;;
6212)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6212 ${TDIR}/tc_tests/hashcat_ripemd160_aes-twofish.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6212 ${TDIR}/tc_tests/hashcat_ripemd160_serpent-aes.tc hashca?l"
;;
2)
CMD="./${BIN} ${OPTS} -a 3 -m 6212 ${TDIR}/tc_tests/hashcat_ripemd160_twofish-serpent.tc hashca?l"
;;
esac
;;
6213)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6213 ${TDIR}/tc_tests/hashcat_ripemd160_aes-twofish-serpent.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6213 ${TDIR}/tc_tests/hashcat_ripemd160_serpent-twofish-aes.tc hashca?l"
;;
esac
;;
6221)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6221 ${TDIR}/tc_tests/hashcat_sha512_aes.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6221 ${TDIR}/tc_tests/hashcat_sha512_serpent.tc hashca?l"
;;
2)
CMD="./${BIN} ${OPTS} -a 3 -m 6221 ${TDIR}/tc_tests/hashcat_sha512_twofish.tc hashca?l"
;;
esac
;;
6222)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6222 ${TDIR}/tc_tests/hashcat_sha512_aes-twofish.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6222 ${TDIR}/tc_tests/hashcat_sha512_serpent-aes.tc hashca?l"
;;
2)
CMD="./${BIN} ${OPTS} -a 3 -m 6222 ${TDIR}/tc_tests/hashcat_sha512_twofish-serpent.tc hashca?l"
;;
esac
;;
6223)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6223 ${TDIR}/tc_tests/hashcat_sha512_aes-twofish-serpent.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6223 ${TDIR}/tc_tests/hashcat_sha512_serpent-twofish-aes.tc hashca?l"
;;
esac
;;
6231)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6231 ${TDIR}/tc_tests/hashcat_whirlpool_aes.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6231 ${TDIR}/tc_tests/hashcat_whirlpool_serpent.tc hashca?l"
;;
2)
CMD="./${BIN} ${OPTS} -a 3 -m 6231 ${TDIR}/tc_tests/hashcat_whirlpool_twofish.tc hashca?l"
;;
esac
;;
6232)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6232 ${TDIR}/tc_tests/hashcat_whirlpool_aes-twofish.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6232 ${TDIR}/tc_tests/hashcat_whirlpool_serpent-aes.tc hashca?l"
;;
2)
CMD="./${BIN} ${OPTS} -a 3 -m 6232 ${TDIR}/tc_tests/hashcat_whirlpool_twofish-serpent.tc hashca?l"
;;
esac
;;
6233)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6233 ${TDIR}/tc_tests/hashcat_whirlpool_aes-twofish-serpent.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6233 ${TDIR}/tc_tests/hashcat_whirlpool_serpent-twofish-aes.tc hashca?l"
;;
esac
;;
6241)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6241 ${TDIR}/tc_tests/hashcat_ripemd160_aes_boot.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6241 ${TDIR}/tc_tests/hashcat_ripemd160_serpent_boot.tc hashca?l"
;;
2)
CMD="./${BIN} ${OPTS} -a 3 -m 6241 ${TDIR}/tc_tests/hashcat_ripemd160_twofish_boot.tc hashca?l"
;;
esac
;;
6242)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6242 ${TDIR}/tc_tests/hashcat_ripemd160_aes-twofish_boot.tc hashca?l"
;;
1)
CMD="./${BIN} ${OPTS} -a 3 -m 6242 ${TDIR}/tc_tests/hashcat_ripemd160_serpent-aes_boot.tc hashca?l"
;;
esac
;;
6243)
case $tcMode in
0)
CMD="./${BIN} ${OPTS} -a 3 -m 6243 ${TDIR}/tc_tests/hashcat_ripemd160_aes-twofish-serpent_boot.tc hashca?l"
;;
esac
;;
esac
if [ ${#CMD} -gt 5 ]; then
echo "> Testing hash type $hashType with attack mode 3, markov ${MARKOV}, single hash, Device-Type ${TYPE}, vector-width ${VECTOR}, tcMode ${tcMode}" >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(${CMD} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
cnt=1
e_nf=0
msg="OK"
if [ ${ret} -ne 0 ]; then
e_nf=1
msg="Error"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 3, Mode single, Device-Type ${TYPE}, Vector-Width ${VECTOR}, tcMode ${tcMode} ] > $msg : ${e_nf}/${cnt} not found"
status ${ret}
fi
}
# Compose and execute hashcat command on a VeraCrypt test container
# Must not be called for hash types other than 137XY
# $1: cipher variation, can be 0-6
function veracrypt_test()
{
cipher_variation=$1
hash_function=""
hash_digit="${hash_type:3:1}"
[ "$hash_digit" -eq "1" ] && hash_function="ripemd160"
[ "$hash_digit" -eq "2" ] && hash_function="sha512"
[ "$hash_digit" -eq "3" ] && hash_function="whirlpool"
[ "$hash_digit" -eq "5" ] && hash_function="sha256"
[ "$hash_digit" -eq "7" ] && hash_function="streebog"
[ -n "$hash_function" ] || return
cipher_cascade=""
cipher_digit="${hash_type:4:1}"
case $cipher_digit in
1)
[ "$cipher_variation" -eq "0" ] && cipher_cascade="aes"
[ "$cipher_variation" -eq "1" ] && cipher_cascade="serpent"
[ "$cipher_variation" -eq "2" ] && cipher_cascade="twofish"
[ "$cipher_variation" -eq "3" ] && cipher_cascade="camellia"
[ "$cipher_variation" -eq "5" ] && cipher_cascade="kuznyechik"
;;
2)
[ "$cipher_variation" -eq "0" ] && cipher_cascade="aes-twofish"
[ "$cipher_variation" -eq "1" ] && cipher_cascade="serpent-aes"
[ "$cipher_variation" -eq "2" ] && cipher_cascade="twofish-serpent"
[ "$cipher_variation" -eq "3" ] && cipher_cascade="camellia-kuznyechik"
[ "$cipher_variation" -eq "4" ] && cipher_cascade="camellia-serpent"
[ "$cipher_variation" -eq "5" ] && cipher_cascade="kuznyechik-aes"
[ "$cipher_variation" -eq "6" ] && cipher_cascade="kuznyechik-twofish"
;;
3)
[ "$cipher_variation" -eq "0" ] && cipher_cascade="aes-twofish-serpent"
[ "$cipher_variation" -eq "1" ] && cipher_cascade="serpent-twofish-aes"
[ "$cipher_variation" -eq "5" ] && cipher_cascade="kuznyechik-serpent-camellia"
;;
esac
[ -n "$cipher_cascade" ] || return
filename="${TDIR}/vc_tests/hashcat_${hash_function}_${cipher_cascade}.vc"
# The hash-cipher combination might be invalid (e.g. RIPEMD-160 + Kuznyechik)
[ -f "${filename}" ] || return
CMD="echo hashca{a..z} | ./${BIN} ${OPTS} -a 0 -m ${hash_type} ${filename}"
echo "> Testing hash type ${hash_type} with attack mode 0, markov ${MARKOV}, single hash, Device-Type ${TYPE}, vector-width ${VECTOR}, cipher ${cipher_cascade}" >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(${CMD} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
cnt=1
e_nf=0
msg="OK"
if [ ${ret} -ne 0 ]; then
e_nf=1
msg="Error"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 0, Mode single, Device-Type ${TYPE}, Vector-Width ${VECTOR}, Cipher ${cipher_cascade} ] > $msg : ${e_nf}/${cnt} not found"
status ${ret}
}
function luks_test()
{
hashType=$1
attackType=$2
# if -m all was set let us default to -a 3 only. You could specify the attack type directly, e.g. -m 0
# the problem with defaulting to all=0,1,3,6,7 is that it could take way too long
if [ "${attackType}" -eq 65535 ]; then
attackType=3
fi
#LUKS_HASHES="sha1 sha256 sha512 ripemd160 whirlpool"
LUKS_HASHES="sha1 sha256 sha512 ripemd160"
LUKS_CIPHERS="aes serpent twofish"
LUKS_MODES="cbc-essiv cbc-plain64 xts-plain64"
LUKS_KEYSIZES="128 256 512"
LUKS_PASSWORD=$(cat "${TDIR}/luks_tests/pw")
for luks_h in ${LUKS_HASHES}; do
for luks_c in ${LUKS_CIPHERS}; do
for luks_m in ${LUKS_MODES}; do
for luks_k in ${LUKS_KEYSIZES}; do
CMD=""
# filter out not supported combinations:
case "${luks_k}" in
128)
case "${luks_m}" in
cbc-essiv|cbc-plain64)
;;
*)
continue
;;
esac
;;
256)
case "${luks_m}" in
cbc-essiv|cbc-plain64|xts-plain64)
;;
*)
continue
;;
esac
;;
512)
case "${luks_m}" in
xts-plain64)
;;
*)
continue
;;
esac
;;
esac
luks_mode="${luks_h}-${luks_c}-${luks_m}-${luks_k}"
luks_file="${TDIR}/luks_tests/hashcat_${luks_h}_${luks_c}_${luks_m}_${luks_k}.luks"
luks_main_mask="?l"
luks_mask="${luks_main_mask}"
# for combination or hybrid attacks
luks_pass_part_file1="${OUTD}/${hashType}_dict1"
luks_pass_part_file2="${OUTD}/${hashType}_dict2"
case $attackType in
0)
CMD="./${BIN} ${OPTS} -a 0 -m ${hashType} ${luks_file} ${TDIR}/luks_tests/pw"
;;
1)
luks_pass_part1_len=$((${#LUKS_PASSWORD} / 2))
luks_pass_part2_start=$((luks_pass_part1_len + 1))
echo "${LUKS_PASSWORD}" | cut -c-${luks_pass_part1_len} > "${luks_pass_part_file1}"
echo "${LUKS_PASSWORD}" | cut -c${luks_pass_part2_start}- > "${luks_pass_part_file2}"
CMD="./${BIN} ${OPTS} -a 6 -m ${hashType} ${luks_file} ${luks_pass_part_file1} ${luks_pass_part_file2}"
;;
3)
luks_mask_fixed_len=$((${#LUKS_PASSWORD} - 1))
luks_mask="$(echo "${LUKS_PASSWORD}" | cut -c-${luks_mask_fixed_len})"
luks_mask="${luks_mask}${luks_main_mask}"
CMD="./${BIN} ${OPTS} -a 3 -m ${hashType} ${luks_file} ${luks_mask}"
;;
6)
luks_pass_part1_len=$((${#LUKS_PASSWORD} - 1))
echo "${LUKS_PASSWORD}" | cut -c-${luks_pass_part1_len} > "${luks_pass_part_file1}"
CMD="./${BIN} ${OPTS} -a 6 -m ${hashType} ${luks_file} ${luks_pass_part_file1} ${luks_mask}"
;;
7)
echo "${LUKS_PASSWORD}" | cut -c2- > "${luks_pass_part_file1}"
CMD="./${BIN} ${OPTS} -a 7 -m ${hashType} ${luks_file} ${luks_mask} ${luks_pass_part_file1}"
;;
esac
if [ -n "${CMD}" ]; then
echo "> Testing hash type ${hashType} with attack mode ${attackType}, markov ${MARKOV}, single hash, Device-Type ${TYPE}, vector-width ${VECTOR}, luksMode ${luks_mode}" >> "${OUTD}/logfull.txt" 2>> "${OUTD}/logfull.txt"
output=$(${CMD} 2>&1)
ret=${?}
echo "${output}" >> "${OUTD}/logfull.txt"
cnt=1
e_nf=0
msg="OK"
if [ ${ret} -ne 0 ]; then
e_nf=1
msg="Error"
fi
echo "[ ${OUTD} ] [ Type ${hash_type}, Attack ${attackType}, Mode single, Device-Type ${TYPE}, Vector-Width ${VECTOR}, luksMode ${luks_mode} ] > $msg : ${e_nf}/${cnt} not found"
status ${ret}
fi
done
done
done
done
}
function usage()
{
cat << EOF
> Usage : ${0} <options>
OPTIONS:
-V Backend vector-width (either 1, 2, 4 or 8), overrides value from device query :
'1' => vector-width 1
'2' => vector-width 2 (default)
'4' => vector-width 4
'8' => vector-width 8
'all' => test sequentially vector-width ${VECTOR_WIDTHS}
-t Select test mode :
'single' => single hash (default)
'multi' => multi hash
'all' => single and multi hash
-m Select hash type :
'all' => all hash type supported
(int) => hash type integer code (default : 0)
(int)-(int) => hash type integer range
-a Select attack mode :
'all' => all attack modes
(int) => attack mode integer code (default : 0)
-x Select cpu architecture :
'32' => 32 bit architecture
'64' => 64 bit architecture (default)
-o Select operating system :
'win' => Windows operating system (use .exe file extension)
'linux' => Linux operating system (use .bin file extension)
'macos' => macOS operating system (use .app file extension)
-d Select the Backend device :
(int)[,int] => comma separated list of devices (default : 1)
-D Select the OpenCL device types :
'1' => CPU
'2' => GPU (default)
'3' => FPGA, DSP, Co-Processor
(int)[,int] => multiple comma separated device types from the list above
-O Use optimized kernels (default : -O)
-P Use pure kernels instead of optimized kernels (default : -O)
-s Use this session name instead of the default one (default : "hashcat")
-c Disables markov-chains
-p Package the tests into a .7z file
-F Use this folder as test folder instead of the default one
(string) => path to folder
-I Use this folder as input/output folder for packaged tests
(string) => path to folder
-h Show this help
EOF
exit 1
}
BIN="hashcat"
MARKOV="enabled"
ATTACK=0
MODE=0
TYPE="null"
VECTOR="default"
HT=0
PACKAGE=0
OPTIMIZED=1
while getopts "V:t:m:a:b:hcpd:x:o:d:D:F:POI:s:" opt; do
case ${opt} in
"V")
if [ "${OPTARG}" = "1" ]; then
VECTOR=1
elif [ "${OPTARG}" = "2" ]; then
VECTOR=2
elif [ "${OPTARG}" = "4" ]; then
VECTOR=4
elif [ "${OPTARG}" = "8" ]; then
VECTOR=8
elif [ "${OPTARG}" = "16" ]; then
VECTOR=16
elif [ "${OPTARG}" = "all" ]; then
VECTOR="all"
else
usage
fi
;;
"t")
if [ "${OPTARG}" = "single" ]; then
MODE=0
elif [ "${OPTARG}" = "multi" ]; then
MODE=1
elif [ "${OPTARG}" = "all" ]; then
MODE=2
else
usage
fi
;;
"m")
if [ "${OPTARG}" = "all" ]; then
HT=65535
else
HT=${OPTARG}
fi
;;
"a")
if [ "${OPTARG}" = "all" ]; then
ATTACK=65535
elif [ "${OPTARG}" = "0" ]; then
ATTACK=0
elif [ "${OPTARG}" = "1" ]; then
ATTACK=1
elif [ "${OPTARG}" = "3" ]; then
ATTACK=3
elif [ "${OPTARG}" = "6" ]; then
ATTACK=6
elif [ "${OPTARG}" = "7" ]; then
ATTACK=7
else
usage
fi
;;
"c")
OPTS="${OPTS} --markov-disable"
MARKOV="disabled"
;;
"I")
PACKAGE_FOLDER=$( echo "${OPTARG}" | sed 's!/$!!g' )
;;
"s")
OPTS="${OPTS} --session \"${OPTARG}\""
;;
"p")
PACKAGE=1
;;
"x")
if [ "${OPTARG}" = "32" ]; then
ARCHITECTURE=32
elif [ "${OPTARG}" = "64" ]; then
ARCHITECTURE=64
else
usage
fi
;;
"o")
if [ "${OPTARG}" = "win" ]; then
EXTENSION="exe"
elif [ "${OPTARG}" = "linux" ]; then
EXTENSION="bin"
elif [ "${OPTARG}" = "macos" ]; then
EXTENSION="app"
else
usage
fi
;;
"O")
# optimized is already default, ignore it
;;
"d")
OPTS="${OPTS} -d ${OPTARG}"
;;
"D")
if [ "${OPTARG}" = "1" ]; then
OPTS="${OPTS} -D 1"
TYPE="Cpu"
elif [ "${OPTARG}" = "2" ]; then
OPTS="${OPTS} -D 2"
TYPE="Gpu"
else
OPTS="${OPTS} -D ${OPTARG}"
TYPE="Cpu + Gpu"
fi
;;
"F")
OUTD=$( echo "${OPTARG}" | sed 's!/$!!g' )
;;
"P")
OPTIMIZED=0
;;
\?)
usage
;;
"h")
usage
;;
esac
done
export IS_OPTIMIZED=${OPTIMIZED}
if [ "${OPTIMIZED}" -eq 1 ]; then
OPTS="${OPTS} -O"
fi
if [ "${TYPE}" = "null" ]; then
OPTS="${OPTS} -D 2"
TYPE="Gpu"
fi
if [ "${HT}" -eq 20510 ]; then # special case for PKZIP Master Key
if [ "${MODE}" -eq 1 ]; then # if "multi" was forced we need to exit
echo "ERROR: -m 20510 = PKZIP Master Key can only be run with a single hash"
exit 1
fi
fi
if [ -n "${ARCHITECTURE}" ]; then
BIN="${BIN}${ARCHITECTURE}"
fi
if [ -n "${EXTENSION}" ]; then
BIN="${BIN}.${EXTENSION}"
fi
if [ -n "${PACKAGE_FOLDER}" ]; then
if [ ! -e "${PACKAGE_FOLDER}" ]; then
echo "! folder '${PACKAGE_FOLDER}' does not exist"
exit 1
fi
fi
if [ "${PACKAGE}" -eq 0 ] || [ -z "${PACKAGE_FOLDER}" ]; then
# check existence of binary
if [ ! -e "${BIN}" ]; then
echo "! ${BIN} not found, please build binary before run test."
exit 1
fi
HT_MIN=0
HT_MAX=0
if echo -n "${HT}" | grep -q '^[0-9]\+$'; then
HT_MIN=${HT}
HT_MAX=${HT}
elif echo -n "${HT}" | grep -q '^[0-9]\+-[1-9][0-9]*$'; then
HT_MIN=$(echo -n ${HT} | sed "s/-.*//")
HT_MAX=$(echo -n ${HT} | sed "s/.*-//")
if [ "${HT_MIN}" -gt "${HT_MAX}" ]; then
echo "! hash type range -m ${HT} is not valid ..."
usage
fi
else
echo "! hash type is not a number ..."
usage
fi
HT=${HT_MIN}
# filter by hash_type
if [ "${HT}" -ne 65535 ]; then
# validate filter
if ! is_in_array "${HT_MIN}" ${HASH_TYPES}; then
echo "! invalid hash type selected ..."
usage
fi
if ! is_in_array "${HT_MAX}" ${HASH_TYPES}; then
echo "! invalid hash type selected ..."
usage
fi
fi
if [ -z "${PACKAGE_FOLDER}" ]; then
# make new dir
mkdir -p "${OUTD}"
# generate random test entry
if [ "${HT}" -eq 65535 ]; then
for TMP_HT in ${HASH_TYPES}; do
if [ "${TMP_HT}" -ne ${LUKS_MODE} ]; then
if ! is_in_array "${TMP_HT}" ${TC_MODES}; then
if ! is_in_array "${TMP_HT}" ${VC_MODES}; then
perl tools/test.pl single "${TMP_HT}" >> "${OUTD}/all.sh"
fi
fi
fi
done
else
for TMP_HT in $(seq "${HT_MIN}" "${HT_MAX}"); do
if ! is_in_array "${TMP_HT}" ${HASH_TYPES}; then
continue
fi
if [ "${TMP_HT}" -ne ${LUKS_MODE} ]; then
# Exclude TrueCrypt and VeraCrypt testing modes
if ! is_in_array "${TMP_HT}" ${TC_MODES}; then
if ! is_in_array "${TMP_HT}" ${VC_MODES}; then
perl tools/test.pl single "${TMP_HT}" >> "${OUTD}/all.sh"
fi
fi
fi
done
fi
else
OUTD=${PACKAGE_FOLDER}
fi
rm -rf "${OUTD}/logfull.txt" && touch "${OUTD}/logfull.txt"
# populate array of hash types where we only should check if pass is in output (not both hash:pass)
IFS=';' read -ra PASS_ONLY <<< "${HASHFILE_ONLY} ${NOCHECK_ENCODING}"
IFS=';' read -ra TIMEOUT_ALGOS <<< "${SLOW_ALGOS}"
IFS=';' read -ra NEVER_CRACK_ALGOS <<< "${NEVER_CRACK}"
# for these particular algos we need to save the output to a temporary file
IFS=';' read -ra FILE_BASED_ALGOS <<< "${HASHFILE_ONLY}"
for hash_type in $HASH_TYPES; do
if [ "${HT}" -ne 65535 ]; then
# check if the loop variable "hash_type" is between HT_MIN and HT_MAX (both included)
if [ "${hash_type}" -lt "${HT_MIN}" ]; then
continue
elif [ "${hash_type}" -gt "${HT_MAX}" ]; then
# we are done because hash_type is larger than range:
break
fi
fi
if [ -z "${PACKAGE_FOLDER}" ]; then
# init test data
init
else
echo "[ ${OUTD} ] > Run packaged test for hash type $hash_type."
fi
if [ "${PACKAGE}" -eq 0 ]; then
# should we check only the pass?
pass_only=0
is_in_array "${hash_type}" ${PASS_ONLY} && pass_only=1
IS_SLOW=0
is_in_array "${hash_type}" ${SLOW_ALGOS} && IS_SLOW=1
# we use phpass as slow hash for testing the AMP kernel
[ "${hash_type}" -eq 400 ] && IS_SLOW=0
OPTS_OLD=${OPTS}
VECTOR_OLD=${VECTOR}
MODE_OLD=${MODE}
if [ "${hash_type}" -eq 20510 ]; then # special case for PKZIP Master Key
if [ "${MODE}" -eq 1 ]; then # if "multi" was forced we need to skip it
continue
fi
MODE=0 # force single only
fi
for CUR_WIDTH in $VECTOR_WIDTHS; do
if [ "${VECTOR_OLD}" = "all" ] || [ "${VECTOR_OLD}" = "default" ] || [ "${VECTOR_OLD}" = "${CUR_WIDTH}" ]; then
if [ "${VECTOR_OLD}" = "default" ] && \
[ "${CUR_WIDTH}" != "1" ] && \
[ "${CUR_WIDTH}" != "4" ]; then
continue
fi
VECTOR=${CUR_WIDTH}
OPTS="${OPTS_OLD} --backend-vector-width ${VECTOR}"
if [ ${IS_SLOW} -eq 1 ]; then
# Look up if this is one of supported VeraCrypt modes
if is_in_array "${hash_type}" ${VC_MODES}; then
veracrypt_test 0 # aes
veracrypt_test 1 # serpent
veracrypt_test 2 # twofish
veracrypt_test 3 # camellia
veracrypt_test 4 # camellia (alternative cascade)
veracrypt_test 5 # kuznyechik
veracrypt_test 6 # kuznyechik (alternative cascade)
elif is_in_array "${hash_type}" ${TC_MODES}; then
# run truecrypt tests
truecrypt_test "${hash_type}" 0
truecrypt_test "${hash_type}" 1
truecrypt_test "${hash_type}" 2
elif [ "${hash_type}" -eq ${LUKS_MODE} ]; then
# run luks tests
luks_test "${hash_type}" ${ATTACK}
else
# run attack mode 0 (stdin)
if [ ${ATTACK} -eq 65535 ] || [ ${ATTACK} -eq 0 ]; then attack_0; fi
fi
else
# run attack mode 0 (stdin)
if [ ${ATTACK} -eq 65535 ] || [ ${ATTACK} -eq 0 ]; then attack_0; fi
# run attack mode 1 (combinator)
if [ ${ATTACK} -eq 65535 ] || [ ${ATTACK} -eq 1 ]; then attack_1; fi
# run attack mode 3 (bruteforce)
if [ ${ATTACK} -eq 65535 ] || [ ${ATTACK} -eq 3 ]; then attack_3; fi
# run attack mode 6 (dict+mask)
if [ ${ATTACK} -eq 65535 ] || [ ${ATTACK} -eq 6 ]; then attack_6; fi
# run attack mode 7 (mask+dict)
if [ ${ATTACK} -eq 65535 ] || [ ${ATTACK} -eq 7 ]; then attack_7; fi
fi
fi
done
OPTS="${OPTS_OLD}"
VECTOR="${VECTOR_OLD}"
MODE=${MODE_OLD}
fi
done
else
OUTD=${PACKAGE_FOLDER}
fi
# fix logfile
if [ "${PACKAGE}" -eq 0 ]; then
cat -vet "${OUTD}/logfull.txt" | sed -e 's/\^M \^M//g' | sed -e 's/\$$//g' > "${OUTD}/test_report.log"
fi
rm -rf "${OUTD}/logfull.txt"
if [ "${PACKAGE}" -eq 1 ]; then
echo "[ ${OUTD} ] > Generate package ${OUTD}/${OUTD}.7z"
cp "${BASH_SOURCE[0]}" "${OUTD}/test.sh"
copy_luks_dir=0
copy_tc_dir=0
copy_vc_dir=0
if [ "${HT}" -eq 65535 ]; then
copy_luks_dir=1
copy_tc_dir=1
copy_vc_dir=1
else
for TMP_HT in $(seq "${HT_MIN}" "${HT_MAX}"); do
if [ "${TMP_HT}" -eq "${LUKS_MODE}" ]; then
copy_luks_dir=1
elif is_in_array "${TMP_HT}" ${TC_MODES}; then
copy_tc_dir=1
elif is_in_array "${TMP_HT}" ${VC_MODES}; then
copy_vc_dir=1
fi
done
fi
if [ "${copy_luks_dir}" -eq 1 ]; then
mkdir "${OUTD}/luks_tests/"
cp ${TDIR}/luks_tests/* "${OUTD}/luks_tests/"
fi
if [ "${copy_tc_dir}" -eq 1 ]; then
mkdir "${OUTD}/tc_tests/"
cp ${TDIR}/tc_tests/* "${OUTD}/tc_tests/"
fi
if [ "${copy_vc_dir}" -eq 1 ]; then
mkdir "${OUTD}/vc_tests/"
cp ${TDIR}/vc_tests/* "${OUTD}/vc_tests/"
fi
# if we package from a given folder, we need to check if e.g. the files needed for multi mode are there
if [ -n "${PACKAGE_FOLDER}" ]; then
MODE=2
ls "${PACKAGE_FOLDER}"/*multi* >/dev/null 2>/dev/null
if [ "${?}" -ne 0 ]
then
MODE=0
fi
HT=$(grep -o -- "-m *[0-9]*" "${PACKAGE_FOLDER}/all.sh" | sort -u | sed 's/-m //' 2> /dev/null)
if [ -n "${HT}" ]; then
HT_COUNT=$(echo "${HT}" | wc -l)
if [ "${HT_COUNT}" -gt 1 ]; then
HT=65535
fi
fi
#ATTACK=65535 # more appropriate ?
fi
# for convenience: 'run package' is default action for packaged test.sh ( + add other defaults too )
SED_IN_PLACE='-i'
UNAME=$(uname -s)
# of course macOS requires us to implement a special case (sed -i "" for the backup file)
if [ "${UNAME}" = "Darwin" ] ; then
SED_IN_PLACE='-i ""'
fi
HT_PACKAGED=${HT}
if [ "${HT_MIN}" -ne "${HT_MAX}" ]; then
HT_PACKAGED=${HT_MIN}-${HT_MAX}
fi
HASH_TYPES_PACKAGED=$( echo "${HASH_TYPES}" | tr '\n' ' ' | sed 's/ $//')
HASHFILE_ONLY_PACKAGED=$(echo "${HASHFILE_ONLY}" | tr '\n' ' ' | sed 's/ $//')
NEVER_CRACK_PACKAGED=$( echo "${NEVER_CRACK}" | tr '\n' ' ' | sed 's/ $//')
SLOW_ALGOS_PACKAGED=$( echo "${SLOW_ALGOS}" | tr '\n' ' ' | sed 's/ $//')
sed "${SED_IN_PLACE}" -e 's/^\(PACKAGE_FOLDER\)=""/\1="$( echo "${BASH_SOURCE[0]}" | sed \"s!test.sh\\$!!\" )"/' \
-e "s/^\(HASH_TYPES\)=\$(.*/\1=\"${HASH_TYPES_PACKAGED}\"/" \
-e "s/^\(HASHFILE_ONLY\)=\$(.*/\1=\"${HASHFILE_ONLY_PACKAGED}\"/" \
-e "s/^\(NEVER_CRACK\)=\$(.*/\1=\"${NEVER_CRACK_PACKAGED}\"/" \
-e "s/^\(SLOW_ALGOS\)=\$(.*/\1=\"${SLOW_ALGOS_PACKAGED}\"/" \
-e "s/^\(HT\)=0/\1=${HT_PACKAGED}/" \
-e "s/^\(MODE\)=0/\1=${MODE}/" \
-e "s/^\(ATTACK\)=0/\1=${ATTACK}/" \
"${OUTD}/test.sh"
"${PACKAGE_CMD}" "${OUTD}/${OUTD}.7z" "${OUTD}/" >/dev/null 2>/dev/null
fi