Merge pull request #169 from magnumripper/onetwenty
[hashcat.git] / tools / test.sh
1 #!/bin/bash
2
3 ##
4 ## Authors.....: Gabriele Gristina <matrix@hashcat.net>
5 ## Jens Steube <jens.steube@gmail.com>
6 ##
7 ## License.....: MIT
8 ##
9
10 # missing hash types: 5200,6211,6221,6231,6241,6251,6261,6271,6281
11
12 HASH_TYPES="0 10 11 12 20 21 22 23 30 40 50 60 100 101 110 111 112 120 121 122 130 131 132 140 141 150 160 190 200 300 400 500 900 1000 1100 1400 1410 1420 1430 1440 1441 1450 1460 1500 1600 1700 1710 1711 1720 1722 1730 1731 1740 1750 1760 1800 2100 2400 2410 2500 2600 2611 2612 2711 2811 3000 3100 3200 3710 3711 3800 4300 4400 4500 4700 4800 4900 5000 5100 5300 5400 5500 5600 5700 5800 6000 6100 6300 6400 6500 6600 6700 6800 6900 7100 7200 7300 7400 7500 7600 7700 7800 7900 8000 8100 8200 8300 8400 8500 8600 8700 8900 9100 9200 9300 9400 9500 9600 9700 9800 9900 10000 10100 10200 10300 10400 10500 10600 10700 10800 10900 11000 11100 11200 11300 11400 11500 11600 11900 12000 12100 12200 12300 12400 12600 12800 12900 13000"
13
14 ATTACK_MODES="0 1 3 6 7"
15
16 MATCH_PASS_ONLY="2500 5300 5400 6600 6800 8200"
17
18 HASHFILE_ONLY="2500"
19
20 NEVER_CRACK="11600"
21
22 SLOW_ALGOS="400 500 501 1600 1800 2100 2500 3200 5200 5800 6211 6221 6231 6241 6251 6261 6271 6281 6300 6400 6500 6600 6700 6800 7100 7200 7400 7900 8200 8800 8900 9000 9100 9200 9300 9400 9500 9600 10000 10300 10500 10700 10900 11300 11600 11900 12000 12100 12200 12300 12400 12500 12800 12900 13000"
23
24 OPTS="--quiet --force --potfile-disable --runtime 200 --gpu-temp-disable --weak-hash-threshold=0 --opencl-device-types 2 --opencl-vector-width 2"
25
26 OUTD="test_$(date +%s)"
27
28 PACKAGE_CMD="7z a"
29 PACKAGE_FOLDER=""
30
31 mask_3[0]=""
32 mask_3[1]="?d"
33 mask_3[2]="?d?d"
34 mask_3[3]="?d?d?d"
35 mask_3[4]="?d?d?d?d"
36 mask_3[5]="?d?d?d?d?d"
37 mask_3[6]="?d?d?d?d?d?d"
38 mask_3[7]="?d?d?d?d?d?d?d"
39 mask_3[8]="?d?d?d?d?d?d?d?d"
40 mask_3[9]="?d?d?d?d?d?d?d?d?d"
41 mask_3[10]="?d?d?d?d?d?d?d?d?d?d"
42 mask_3[11]="?d?d?d?d?d?d?d?d?d?d?d"
43 mask_3[12]="?d?d?d?d?d?d?d?d?d?d?d?d"
44 mask_3[13]="?d?d?d?d?d?d?d?d?d?d?d?d?d"
45 mask_3[14]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d"
46 mask_3[15]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d"
47 mask_3[16]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0"
48 mask_3[17]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00"
49 mask_3[18]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000"
50 mask_3[19]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000"
51 mask_3[20]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00000"
52 mask_3[21]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000000"
53 mask_3[22]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000000"
54 mask_3[23]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00000000"
55 mask_3[24]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000000000"
56 mask_3[25]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000000000"
57 mask_3[26]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00000000000"
58 mask_3[27]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000000000000"
59 mask_3[28]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000000000000"
60 mask_3[29]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d00000000000000"
61 mask_3[30]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d000000000000000"
62 mask_3[31]="?d?d?d?d?d?d?d?d?d?d?d?d?d?d?d0000000000000000"
63
64 mask_6[0]=""
65 mask_6[1]=""
66 mask_6[2]="?d"
67 mask_6[3]="?d?d"
68 mask_6[4]="?d?d"
69 mask_6[5]="?d?d?d"
70 mask_6[6]="?d?d?d"
71 mask_6[7]="?d?d?d?d"
72 mask_6[8]="?d?d?d?d"
73 mask_6[9]="?d?d?d?d?d"
74 mask_6[10]="?d?d?d?d?d"
75 mask_6[11]="?d?d?d?d?d?d"
76 mask_6[12]="?d?d?d?d?d?d"
77 mask_6[13]="?d?d?d?d?d?d?d"
78 mask_6[14]="?d?d?d?d?d?d?d"
79 mask_6[15]="?d?d?d?d?d?d?d?d"
80 mask_6[16]="?d?d?d?d?d?d?d?d"
81 mask_6[17]="?d?d?d?d?d?d?d?d0"
82 mask_6[18]="?d?d?d?d?d?d?d?d0"
83 mask_6[19]="?d?d?d?d?d?d?d?d00"
84 mask_6[20]="?d?d?d?d?d?d?d?d00"
85 mask_6[21]="?d?d?d?d?d?d?d?d000"
86 mask_6[22]="?d?d?d?d?d?d?d?d000"
87 mask_6[23]="?d?d?d?d?d?d?d?d0000"
88 mask_6[24]="?d?d?d?d?d?d?d?d0000"
89 mask_6[25]="?d?d?d?d?d?d?d?d00000"
90 mask_6[26]="?d?d?d?d?d?d?d?d00000"
91 mask_6[27]="?d?d?d?d?d?d?d?d000000"
92 mask_6[28]="?d?d?d?d?d?d?d?d000000"
93 mask_6[29]="?d?d?d?d?d?d?d?d0000000"
94 mask_6[30]="?d?d?d?d?d?d?d?d0000000"
95 mask_6[31]="?d?d?d?d?d?d?d?d00000000"
96
97 mask_7[0]=""
98 mask_7[1]=""
99 mask_7[2]="?d"
100 mask_7[3]="?d"
101 mask_7[4]="?d?d"
102 mask_7[5]="?d?d"
103 mask_7[6]="?d?d?d"
104 mask_7[7]="?d?d?d"
105 mask_7[8]="?d?d?d?d"
106 mask_7[9]="?d?d?d?d"
107 mask_7[10]="?d?d?d?d?d"
108 mask_7[11]="?d?d?d?d?d"
109 mask_7[12]="?d?d?d?d?d?d"
110 mask_7[13]="?d?d?d?d?d?d"
111 mask_7[14]="?d?d?d?d?d?d?d"
112 mask_7[15]="?d?d?d?d?d?d?d"
113 mask_7[16]="?d?d?d?d?d?d?d?d"
114 mask_7[17]="?d?d?d?d?d?d?d?d"
115 mask_7[18]="?d?d?d?d?d?d?d?d0"
116 mask_7[19]="?d?d?d?d?d?d?d?d0"
117 mask_7[20]="?d?d?d?d?d?d?d?d00"
118 mask_7[21]="?d?d?d?d?d?d?d?d00"
119 mask_7[22]="?d?d?d?d?d?d?d?d000"
120 mask_7[23]="?d?d?d?d?d?d?d?d000"
121 mask_7[24]="?d?d?d?d?d?d?d?d0000"
122 mask_7[25]="?d?d?d?d?d?d?d?d0000"
123 mask_7[26]="?d?d?d?d?d?d?d?d00000"
124 mask_7[27]="?d?d?d?d?d?d?d?d00000"
125 mask_7[28]="?d?d?d?d?d?d?d?d000000"
126 mask_7[29]="?d?d?d?d?d?d?d?d000000"
127 mask_7[30]="?d?d?d?d?d?d?d?d0000000"
128 mask_7[31]="?d?d?d?d?d?d?d?d0000000"
129
130 contains ()
131 {
132 for element in "${@:2}"; do
133
134 if [ "${element}" == "${1}" ]; then
135 return 1
136 fi
137
138 done
139
140 return 0
141 }
142
143 function init()
144 {
145 if [ "${PACKAGE}" -eq 1 ]; then
146
147 echo "[ ${OUTD} ] > Generate tests for hash type $hash_type."
148
149 else
150
151 echo "[ ${OUTD} ] > Init test for hash type $hash_type."
152
153 fi
154
155 rm -rf ${OUTD}/${hash_type}.sh ${OUTD}/${hash_type}_passwords.txt ${OUTD}/${hash_type}_hashes.txt
156
157 # create list of password and hashes of same type
158 grep " ${hash_type} '" ${OUTD}/all.sh > ${OUTD}/${hash_type}.sh
159
160 # create separate list of password and hashes
161 cat ${OUTD}/${hash_type}.sh | awk '{print $3}' > ${OUTD}/${hash_type}_passwords.txt
162 cat ${OUTD}/${hash_type}.sh | awk '{print $11}' | cut -d"'" -f2 > ${OUTD}/${hash_type}_hashes.txt
163
164 if [ "${hash_type}" -eq 10300 ]; then
165 cat ${OUTD}/${hash_type}.sh | cut -d' ' -f11- | cut -d"'" -f2 > ${OUTD}/${hash_type}_hashes.txt
166 fi
167
168 # truncate dicts
169 rm -rf ${OUTD}/${hash_type}_dict1 ${OUTD}/${hash_type}_dict2
170 touch ${OUTD}/${hash_type}_dict1 ${OUTD}/${hash_type}_dict2
171
172 # foreach password entry split password in 2 (skip first entry, is len 1)
173 i=1
174
175 # minimum password length
176
177 min_len=0
178
179 if [ "${hash_type}" -eq 2500 ]; then
180
181 min_len=7 # means length 8, since we start with 0
182
183 fi
184
185 while read -u 9 pass; do
186
187 if [ ${i} -gt 1 ]; then
188
189 # split password, 'i' is the len
190 p0=$((i / 2))
191 p1=$((p0 + 1))
192
193 # special case (passwords longer than expected)
194 pass_len=${#pass}
195
196 if [ "${pass_len}" -gt 1 ]
197 then
198
199 p1=$((p1 + ${min_len}))
200 p0=$((p0 + ${min_len}))
201
202 if [ "${p1}" -gt ${pass_len} ]; then
203
204 p1=${pass_len}
205 p0=$((p1 - 1))
206
207 fi
208
209 # add splitted password to dicts
210
211 echo ${pass} | cut -c -${p0} >> ${OUTD}/${hash_type}_dict1
212 echo ${pass} | cut -c ${p1}- >> ${OUTD}/${hash_type}_dict2
213
214 fi
215 fi
216
217 ((i++))
218
219 done 9< ${OUTD}/${hash_type}_passwords.txt
220
221 min_len=0
222
223 if [ "${hash_type}" -eq 2500 ]; then
224
225 min_len=7 # means length 8, since we start with 0
226
227 fi
228
229 # generate multiple pass/hash foreach len (2 to 8)
230 if [ ${MODE} -ge 1 ]; then
231
232 for ((i = 2; i < 9; i++)); do
233
234 rm -rf ${OUTD}/${hash_type}_multi_${i}.txt ${OUTD}/${hash_type}_passwords_multi_${i}.txt ${OUTD}/${hash_type}_hashes_multi_${i}.txt
235 rm -rf ${OUTD}/${hash_type}_dict1_multi_${i} ${OUTD}/${hash_type}_dict2_multi_${i}
236 touch ${OUTD}/${hash_type}_dict1_multi_${i} ${OUTD}/${hash_type}_dict2_multi_${i}
237
238 perl tools/test.pl single ${hash_type} ${i} > ${OUTD}/${hash_type}_multi_${i}.txt
239
240 cat ${OUTD}/${hash_type}_multi_${i}.txt | awk '{print $3}' > ${OUTD}/${hash_type}_passwords_multi_${i}.txt
241 cat ${OUTD}/${hash_type}_multi_${i}.txt | awk '{print $11}' | cut -d"'" -f2 > ${OUTD}/${hash_type}_hashes_multi_${i}.txt
242
243 if [ "${hash_type}" -eq 10300 ]; then
244 cat ${OUTD}/${hash_type}_multi_${i}.txt | cut -d' ' -f11- | cut -d"'" -f2 > ${OUTD}/${hash_type}_hashes_multi_${i}.txt
245 fi
246
247 # split password, 'i' is the len
248 p0=$((i / 2))
249 p1=$((p0 + 1))
250
251 p0=$((p0 + ${min_len}))
252 p1=$((p1 + ${min_len}))
253
254 while read -u 9 pass; do
255
256 # add splitted password to dicts
257 echo ${pass} | cut -c -${p0} >> ${OUTD}/${hash_type}_dict1_multi_${i}
258 echo ${pass} | cut -c ${p1}- >> ${OUTD}/${hash_type}_dict2_multi_${i}
259
260 done 9< ${OUTD}/${hash_type}_passwords_multi_${i}.txt
261
262 done
263
264 fi
265 }
266
267 function status()
268 {
269 RET=$1
270
271 ((cnt++))
272
273 if [ ${RET} -ne 0 ]; then
274 case ${RET} in
275 1)
276 if contains ${hash_type} ${NEVER_CRACK_ALGOS}; then
277
278 echo "password not found, cmdline : ${CMD}" &>> ${OUTD}/logfull.txt
279 ((e_nf++))
280
281 fi
282
283 ;;
284 2)
285 echo "timeout reached, cmdline : ${CMD}" &>> ${OUTD}/logfull.txt
286 ((e_to++))
287
288 ;;
289 10)
290 if [ "${pass_only}" -eq 1 ]; then
291 echo "plains not found in output, cmdline : ${CMD}" &>> ${OUTD}/logfull.txt
292 else
293 echo "hash:plains not matched in output, cmdline : ${CMD}" &>> ${OUTD}/logfull.txt
294 fi
295 ((e_nm++))
296
297 ;;
298 *)
299 echo "! unhandled return code ${RET}, cmdline : ${CMD}" &>> ${OUTD}/logfull.txt
300 echo "! unhandled return code, see ${OUTD}/logfull.txt for details."
301 ((e_nf++))
302 ;;
303 esac
304 fi
305 }
306
307 function attack_0()
308 {
309 file_only=0
310
311 if ! contains ${hash_type} ${FILE_BASED_ALGOS}; then
312
313 file_only=1
314
315 fi
316
317 # single hash
318 if [ ${MODE} -ne 1 ]; then
319
320 e_to=0
321 e_nf=0
322 e_nm=0
323 cnt=0
324
325 echo "> Testing hash type $hash_type with attack mode 0, markov ${MARKOV}, single hash." &>> ${OUTD}/logfull.txt
326
327 max=32
328
329 if ! contains ${hash_type} ${TIMEOUT_ALGOS}; then
330
331 max=12
332
333 fi
334
335 i=0
336
337 while read -u 9 line; do
338
339 if [ "${i}" -ge ${max} ]; then
340
341 break
342
343 fi
344
345 hash="$(echo "$line" | cut -d\' -f2)"
346 pass="$(echo "$line" | cut -d' ' -f3)"
347
348 if [ -z "${hash}" ]; then
349
350 break
351
352 fi
353
354 if [ "${file_only}" -eq 1 ]; then
355
356 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
357 echo ${hash} | base64 -d > ${temp_file}
358 hash="${temp_file}"
359
360 fi
361
362 CMD="echo -n "${pass}" | ./${BIN} ${OPTS} -a 0 -m ${hash_type} '${hash}'"
363
364 echo -n "[ len $((i + 1)) ] " &>> ${OUTD}/logfull.txt
365
366 output=$(echo -n "${pass}" | ./${BIN} ${OPTS} -a 0 -m ${hash_type} "${hash}" 2>&1)
367
368 ret=${?}
369
370 echo "${output}" >> ${OUTD}/logfull.txt
371
372 if [ "${ret}" -eq 0 ]; then
373
374 if [ ${pass_only} -eq 1 ]; then
375 search=":${pass}"
376 else
377 search="${hash}:${pass}"
378 fi
379
380 echo "${output}" | grep -F "${search}" &> /dev/null
381
382 if [ "${?}" -ne 0 ]; then
383
384 ret=10
385
386 fi
387
388 fi
389
390 status ${ret}
391
392 i=$((i + 1))
393
394 done 9< ${OUTD}/${hash_type}.sh
395
396 msg="OK"
397
398 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
399
400 msg="Error"
401
402 elif [ "${e_to}" -ne 0 ]; then
403
404 msg="Warning"
405
406 fi
407
408 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 0, Mode single ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
409
410 fi
411
412 # multihash
413 if [ ${MODE} -ne 0 ]; then
414
415 e_to=0
416 e_nf=0
417 e_nm=0
418 cnt=0
419
420 echo "> Testing hash type $hash_type with attack mode 0, markov ${MARKOV}, multi hash." &>> ${OUTD}/logfull.txt
421
422 hash_file=${OUTD}/${hash_type}_hashes.txt
423
424 # if file_only -> decode all base64 "hashes" and put them in the temporary file
425
426 if [ "${file_only}" -eq 1 ]; then
427
428 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
429 rm -f ${temp_file}
430
431 hash_file=${temp_file}
432
433 while read base64_hash; do
434
435 echo -n ${base64_hash} | base64 -d >> ${temp_file}
436
437 done < ${OUTD}/${hash_type}_hashes.txt
438
439 fi
440
441 CMD="cat ${OUTD}/${hash_type}_passwords.txt | ./${BIN} ${OPTS} -a 0 -m ${hash_type} ${hash_file}"
442
443 output=$(cat ${OUTD}/${hash_type}_passwords.txt | ./${BIN} ${OPTS} -a 0 -m ${hash_type} ${hash_file} 2>&1)
444
445 ret=${?}
446
447 echo "${output}" >> ${OUTD}/logfull.txt
448
449 if [ "${ret}" -eq 0 ]; then
450
451 i=1
452
453 while read -u 9 hash; do
454
455 pass=$(sed -n ${i}p ${OUTD}/${hash_type}_passwords.txt)
456
457 if [ ${pass_only} -eq 1 ]; then
458 search=":${pass}"
459 else
460 search="${hash}:${pass}"
461 fi
462
463 echo "${output}" | grep -F "${search}" &> /dev/null
464
465 if [ "${?}" -ne 0 ]; then
466
467 ret=10
468
469 break
470
471 fi
472
473 i=$((i + 1))
474
475 done 9< ${OUTD}/${hash_type}_hashes.txt
476
477 fi
478
479 status ${ret}
480
481 msg="OK"
482
483 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
484
485 msg="Error"
486
487 elif [ "${e_to}" -ne 0 ]; then
488
489 msg="Warning"
490
491 fi
492
493 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 0, Mode multi ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
494
495 fi
496 }
497
498 function attack_1()
499 {
500 file_only=0
501
502 if ! contains ${hash_type} ${FILE_BASED_ALGOS}; then
503
504 file_only=1
505
506 fi
507
508 # single hash
509 if [ ${MODE} -ne 1 ]; then
510
511 e_to=0
512 e_nf=0
513 e_nm=0
514 cnt=0
515
516 echo "> Testing hash type $hash_type with attack mode 1, markov ${MARKOV}, single hash." &>> ${OUTD}/logfull.txt
517 i=1
518 while read -u 9 hash; do
519
520 if [ $i -gt 1 ]; then
521
522 if [ "${file_only}" -eq 1 ]; then
523
524 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
525 echo ${hash} | base64 -d > ${temp_file}
526 hash="${temp_file}"
527
528 fi
529
530 CMD="./${BIN} ${OPTS} -a 1 -m ${hash_type} '${hash}' ${OUTD}/${hash_type}_dict1 ${OUTD}/${hash_type}_dict2"
531
532 echo -n "[ len $i ] " &>> ${OUTD}/logfull.txt
533
534 output=$(./${BIN} ${OPTS} -a 1 -m ${hash_type} "${hash}" ${OUTD}/${hash_type}_dict1 ${OUTD}/${hash_type}_dict2 2>&1)
535
536 ret=${?}
537
538 echo "${output}" >> ${OUTD}/logfull.txt
539
540 if [ "${ret}" -eq 0 ]; then
541
542 line_nr=$((i - 1))
543
544 line_dict1=$(sed -n ${line_nr}p ${OUTD}/${hash_type}_dict1)
545 line_dict2=$(sed -n ${line_nr}p ${OUTD}/${hash_type}_dict2)
546
547 if [ ${pass_only} -eq 1 ]; then
548 search=":${line_dict1}${line_dict2}"
549 else
550 search="${hash}:${line_dict1}${line_dict2}"
551 fi
552
553 echo "${output}" | grep -F "${search}" &> /dev/null
554
555 if [ "${?}" -ne 0 ]; then
556
557 ret=10
558
559 fi
560
561 fi
562
563 status ${ret}
564
565 fi
566
567 ((i++))
568
569 done 9< ${OUTD}/${hash_type}_hashes.txt
570
571 msg="OK"
572
573 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
574
575 msg="Error"
576
577 elif [ "${e_to}" -ne 0 ]; then
578
579 msg="Warning"
580
581 fi
582
583 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 1, Mode single ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
584
585 fi
586
587 # multihash
588 if [ ${MODE} -ne 0 ]; then
589
590 e_to=0
591 e_nf=0
592 e_nm=0
593 cnt=0
594
595 offset=14
596
597 if [ ${hash_type} -eq 2500 ]; then
598 offset=7
599 elif [ ${hash_type} -eq 5800 ]; then
600 offset=6
601 elif [ ${hash_type} -eq 3000 ]; then
602 offset=6
603 elif [ ${hash_type} -eq 2100 ]; then
604 offset=11
605 elif [ ${hash_type} -eq 1500 ]; then
606 offset=7
607 elif [ ${hash_type} -eq 7700 ]; then
608 offset=7
609 elif [ ${hash_type} -eq 8500 ]; then
610 offset=7
611 fi
612
613 hash_file=${OUTD}/${hash_type}_multihash_combi.txt
614
615 tail -n ${offset} ${OUTD}/${hash_type}_hashes.txt > ${hash_file}
616
617 # if file_only -> decode all base64 "hashes" and put them in the temporary file
618
619 if [ "${file_only}" -eq 1 ]; then
620
621 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
622 rm -f ${temp_file}
623
624 hash_file=${temp_file}
625
626 while read base64_hash; do
627
628 echo -n ${base64_hash} | base64 -d >> ${temp_file}
629
630 done < ${OUTD}/${hash_type}_multihash_combi.txt
631
632 fi
633
634 CMD="./${BIN} ${OPTS} -a 1 -m ${hash_type} ${hash_file} ${OUTD}/${hash_type}_dict1 ${OUTD}/${hash_type}_dict2"
635
636 echo "> Testing hash type $hash_type with attack mode 1, markov ${MARKOV}, multi hash." &>> ${OUTD}/logfull.txt
637
638 output=$(./${BIN} ${OPTS} -a 1 -m ${hash_type} ${hash_file} ${OUTD}/${hash_type}_dict1 ${OUTD}/${hash_type}_dict2 2>&1)
639
640 ret=${?}
641
642 echo "${output}" >> ${OUTD}/logfull.txt
643
644 if [ "${ret}" -eq 0 ]; then
645
646 i=0
647
648 while read -u 9 hash; do
649
650 line_nr=$((offset - i))
651
652 line_dict1=$(tail -n ${line_nr} ${OUTD}/${hash_type}_dict1 | head -1)
653 line_dict2=$(tail -n ${line_nr} ${OUTD}/${hash_type}_dict2 | head -1)
654
655 if [ ${pass_only} -eq 1 ]; then
656 search=":${line_dict1}${line_dict2}"
657 else
658 search="${hash}:${line_dict1}${line_dict2}"
659 fi
660
661 echo "${output}" | grep -F "${search}" &> /dev/null
662
663 if [ "${?}" -ne 0 ]; then
664
665 ret=10
666
667 break
668
669 fi
670
671 i=$((i + 1))
672
673 done 9< ${OUTD}/${hash_type}_multihash_combi.txt
674
675 fi
676
677 status ${ret}
678
679 msg="OK"
680
681 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
682
683 msg="Error"
684
685 elif [ "${e_to}" -ne 0 ]; then
686
687 msg="Warning"
688
689 fi
690
691 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 1, Mode multi ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
692
693 fi
694 }
695
696 function attack_3()
697 {
698 file_only=0
699
700 if ! contains ${hash_type} ${FILE_BASED_ALGOS}; then
701
702 file_only=1
703
704 fi
705
706 # single hash
707 if [ ${MODE} -ne 1 ]; then
708
709 e_to=0
710 e_nf=0
711 e_nm=0
712 cnt=0
713
714 echo "> Testing hash type $hash_type with attack mode 3, markov ${MARKOV}, single hash." &>> ${OUTD}/logfull.txt
715
716 max=8
717 mask_offset=0
718
719 # some algos have a minimum password length
720
721 if [ "${hash_type}" -eq 2500 ];then
722
723 mask_offset=7
724 max=7
725
726 fi
727
728 i=1
729
730 while read -u 9 hash; do
731
732 if [ "${i}" -gt 6 ]; then
733
734 if ! contains ${hash_type} ${TIMEOUT_ALGOS}; then
735
736 break;
737
738 fi
739
740 fi
741
742 if [ "${file_only}" -eq 1 ]; then
743
744 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
745 echo ${hash} | base64 -d > ${temp_file}
746 hash="${temp_file}"
747
748 fi
749
750 mask=${mask_3[$((i + ${mask_offset}))]}
751
752 # modify "default" mask if needed (and set custom charset to reduce keyspace)
753
754 if [ "${hash_type}" -eq 2500 ]; then
755
756 pass=$(sed -n ${i}p ${OUTD}/${hash_type}_passwords.txt)
757
758 mask=${pass}
759
760 # replace the first x positions in the mask with ?d's
761
762 # first: remove first i (== amount) chars
763
764 mask=$(echo ${mask} | cut -b $((i + 1))-)
765
766 # prepend the ?d's
767
768 for i in $(seq 1 ${i}); do
769
770 mask="?d${mask}"
771
772 done
773
774 fi
775
776 CMD="./${BIN} ${OPTS} -a 3 -m ${hash_type} '${hash}' ${mask}"
777
778 echo -n "[ len $i ] " &>> ${OUTD}/logfull.txt
779
780 output=$(./${BIN} ${OPTS} -a 3 -m ${hash_type} "${hash}" ${mask} 2>&1)
781
782 ret=${?}
783
784 echo "${output}" >> ${OUTD}/logfull.txt
785
786 if [ "${ret}" -eq 0 ]; then
787
788 line_dict=$(sed -n ${i}p ${OUTD}/${hash_type}_passwords.txt)
789
790 if [ ${pass_only} -eq 1 ]; then
791 search=":${line_dict}"
792 else
793 search="${hash}:${line_dict}"
794 fi
795
796 echo "${output}" | grep -F "${search}" &> /dev/null
797
798 if [ "${?}" -ne 0 ]; then
799
800 ret=10
801
802 fi
803
804 fi
805
806 status ${ret}
807
808 if [ $i -eq ${max} ]; then break; fi
809
810 ((i++))
811
812 done 9< ${OUTD}/${hash_type}_hashes.txt
813
814 msg="OK"
815
816 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
817
818 msg="Error"
819
820 elif [ "${e_to}" -ne 0 ]; then
821
822 msg="Warning"
823
824 fi
825
826 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 3, Mode single ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
827
828 fi
829
830 # multihash
831 if [ ${MODE} -ne 0 ]; then
832
833 e_to=0
834 e_nf=0
835 e_nm=0
836 cnt=0
837
838 increment_max=8
839
840 if ! contains ${hash_type} ${TIMEOUT_ALGOS}; then
841
842 increment_max=5
843
844 fi
845
846 increment_min=1
847
848 if [ "${hash_type}" -eq 2500 ]; then
849
850 increment_min=8
851 increment_max=9
852
853 fi
854
855 hash_file=${OUTD}/${hash_type}_multihash_bruteforce.txt
856
857 head -n $((increment_max - ${increment_min} + 1)) ${OUTD}/${hash_type}_hashes.txt > ${hash_file}
858
859 # if file_only -> decode all base64 "hashes" and put them in the temporary file
860
861 if [ "${file_only}" -eq 1 ]; then
862
863 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
864 rm -f ${temp_file}
865
866 hash_file=${temp_file}
867
868 while read base64_hash; do
869
870 echo -n ${base64_hash} | base64 -d >> ${temp_file}
871
872 done < ${OUTD}/${hash_type}_multihash_bruteforce.txt
873
874 fi
875
876 mask=${mask_3[8]}
877 custom_charsets=""
878
879 # modify "default" mask if needed (and set custom charset to reduce keyspace)
880
881 if [ "${hash_type}" -eq 2500 ]; then
882
883 mask="?d?d?d?d?d?1?2?3?4"
884
885 charset_1=""
886 charset_2=""
887 charset_3=""
888 charset_4=""
889
890 # check positions (here we assume that mask is always composed of non literal chars
891 # i.e. something like ?d?l?u?s?1 is possible, but ?d?dsuffix not
892 charset_1_pos=$(expr index "${mask}" 1)
893 charset_2_pos=$(expr index "${mask}" 2)
894 charset_3_pos=$(expr index "${mask}" 3)
895 charset_4_pos=$(expr index "${mask}" 4)
896
897 # divide each charset position by 2 since each of them occupies 2 positions in the mask
898
899 charset_1_pos=$((charset_1_pos / 2))
900 charset_2_pos=$((charset_2_pos / 2))
901 charset_3_pos=$((charset_3_pos / 2))
902 charset_4_pos=$((charset_4_pos / 2))
903
904 i=1
905
906 while read -u 9 hash; do
907
908 pass=$(sed -n ${i}p ${OUTD}/${hash_type}_passwords.txt)
909
910 # charset 1
911 char=$(echo "${pass}" | cut -b ${charset_1_pos})
912 charset_1=$(echo -e "${charset_1}\n${char}")
913
914 # charset 2
915 char=$(echo "${pass}" | cut -b ${charset_2_pos})
916 charset_2=$(echo -e "${charset_2}\n${char}")
917
918 # charset 3
919 char=$(echo "${pass}" | cut -b ${charset_3_pos})
920 charset_3=$(echo -e "${charset_3}\n${char}")
921
922 # charset 4
923 char=$(echo "${pass}" | cut -b ${charset_4_pos})
924 charset_4=$(echo -e "${charset_4}\n${char}")
925
926 i=$((i + 1))
927
928 done 9< ${OUTD}/${hash_type}_multihash_bruteforce.txt
929
930 # just make sure that all custom charset fields are initialized
931
932 if [ -z "${charset_1}" ]; then
933
934 charset_1="1"
935
936 fi
937
938 if [ -z "${charset_2}" ]; then
939
940 charset_2="2"
941
942 fi
943
944 if [ -z "${charset_3}" ]; then
945
946 charset_3="3"
947
948 fi
949
950 if [ -z "${charset_4}" ]; then
951
952 charset_4="4"
953
954 fi
955
956 # unique and remove new lines
957
958 charset_1=$(echo "${charset_1}" | sort -u | tr -d '\n')
959 charset_2=$(echo "${charset_2}" | sort -u | tr -d '\n')
960 charset_3=$(echo "${charset_3}" | sort -u | tr -d '\n')
961 charset_4=$(echo "${charset_4}" | sort -u | tr -d '\n')
962
963 custom_charsets="-1 ${charset_1} -2 ${charset_2} -3 ${charset_3} -4 ${charset_4}"
964 fi
965
966 CMD="./${BIN} ${OPTS} -a 3 -m ${hash_type} --increment --increment-min ${increment_min} --increment-max ${increment_max} ${custom_charsets} ${hash_file} ${mask} "
967
968 echo "> Testing hash type $hash_type with attack mode 3, markov ${MARKOV}, multi hash." &>> ${OUTD}/logfull.txt
969
970 output=$(./${BIN} ${OPTS} -a 3 -m ${hash_type} --increment --increment-min ${increment_min} --increment-max ${increment_max} ${custom_charsets} ${hash_file} ${mask} 2>&1)
971
972 ret=${?}
973
974 echo "${output}" >> ${OUTD}/logfull.txt
975
976 if [ "${ret}" -eq 0 ]; then
977
978 i=1
979
980 while read -u 9 hash; do
981
982 pass=$(sed -n ${i}p ${OUTD}/${hash_type}_passwords.txt)
983
984 if [ ${pass_only} -eq 1 ]; then
985 search=":${pass}"
986 else
987 search="${hash}:${pass}"
988 fi
989
990 echo "${output}" | grep -F "${search}" &> /dev/null
991
992 if [ "${?}" -ne 0 ]; then
993
994 ret=10
995
996 break
997
998 fi
999
1000 i=$((i + 1))
1001
1002 done 9< ${OUTD}/${hash_type}_multihash_bruteforce.txt
1003
1004 fi
1005
1006 status ${ret}
1007
1008 msg="OK"
1009
1010 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
1011
1012 msg="Error"
1013
1014 elif [ "${e_to}" -ne 0 ]; then
1015
1016 msg="Warning"
1017
1018 fi
1019
1020 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 3, Mode multi ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
1021
1022 fi
1023 }
1024
1025 function attack_6()
1026 {
1027 file_only=0
1028
1029 if ! contains ${hash_type} ${FILE_BASED_ALGOS}; then
1030
1031 file_only=1
1032
1033 fi
1034
1035 # single hash
1036 if [ ${MODE} -ne 1 ]; then
1037
1038 e_to=0
1039 e_nf=0
1040 e_nm=0
1041 cnt=0
1042
1043 echo "> Testing hash type $hash_type with attack mode 6, markov ${MARKOV}, single hash." &>> ${OUTD}/logfull.txt
1044
1045 i=1
1046
1047 max=8
1048
1049 if [ "${hash_type}" -eq 2500 ]; then
1050
1051 max=6
1052
1053 fi
1054
1055 while read -u 9 hash; do
1056
1057 if [ "${i}" -gt 6 ]; then
1058
1059 if ! contains ${hash_type} ${TIMEOUT_ALGOS}; then
1060
1061 break;
1062
1063 fi
1064
1065 fi
1066
1067 if [ $i -gt 1 ]; then
1068
1069 if [ "${file_only}" -eq 1 ]; then
1070
1071 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
1072 echo ${hash} | base64 -d > ${temp_file}
1073 hash="${temp_file}"
1074
1075 fi
1076
1077 CMD="./${BIN} ${OPTS} -a 6 -m ${hash_type} '${hash}' ${OUTD}/${hash_type}_dict1 ${mask_6[$i]}"
1078
1079 echo -n "[ len $i ] " &>> ${OUTD}/logfull.txt
1080
1081 output=$(./${BIN} ${OPTS} -a 6 -m ${hash_type} "${hash}" ${OUTD}/${hash_type}_dict1 ${mask_6[$i]} 2>&1)
1082
1083 ret=${?}
1084
1085 echo "${output}" >> ${OUTD}/logfull.txt
1086
1087 if [ "${ret}" -eq 0 ]; then
1088
1089 line_nr=$((i - 1))
1090
1091 line_dict1=$(sed -n ${line_nr}p ${OUTD}/${hash_type}_dict1)
1092 line_dict2=$(sed -n ${line_nr}p ${OUTD}/${hash_type}_dict2)
1093
1094 if [ ${pass_only} -eq 1 ]; then
1095 search=":${line_dict1}${line_dict2}"
1096 else
1097 search="${hash}:${line_dict1}${line_dict2}"
1098 fi
1099
1100 echo "${output}" | grep -F "${search}" &> /dev/null
1101
1102 if [ "${?}" -ne 0 ]; then
1103
1104 ret=10
1105
1106 fi
1107
1108 fi
1109
1110 status ${ret}
1111
1112 fi
1113
1114 if [ "${i}" -eq ${max} ]; then break; fi
1115
1116 ((i++))
1117
1118 done 9< ${OUTD}/${hash_type}_hashes.txt
1119
1120 msg="OK"
1121
1122 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
1123
1124 msg="Error"
1125
1126 elif [ "${e_to}" -ne 0 ]; then
1127
1128 msg="Warning"
1129
1130 fi
1131
1132 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 6, Mode single ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
1133
1134 fi
1135
1136 # multihash
1137 if [ ${MODE} -ne 0 ]; then
1138
1139 e_to=0
1140 e_nf=0
1141 e_nm=0
1142 cnt=0
1143
1144 max=9
1145
1146 if [ ${hash_type} -eq 2500 ]; then
1147 max=5
1148 elif [ ${hash_type} -eq 3000 ]; then
1149 max=8
1150 elif [ ${hash_type} -eq 7700 ]; then
1151 max=8
1152 elif [ ${hash_type} -eq 8500 ]; then
1153 max=8
1154 fi
1155
1156 if ! contains ${hash_type} ${TIMEOUT_ALGOS}; then
1157
1158 max=5
1159
1160 if [ "${hash_type}" -eq 3200 ]; then
1161
1162 max=3
1163
1164 fi
1165
1166 fi
1167
1168 for ((i = 2; i < ${max}; i++)); do
1169
1170 hash_file=${OUTD}/${hash_type}_hashes_multi_${i}.txt
1171
1172 # if file_only -> decode all base64 "hashes" and put them in the temporary file
1173
1174 if [ "${file_only}" -eq 1 ]; then
1175
1176 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
1177 rm -f ${temp_file}
1178
1179 hash_file=${temp_file}
1180
1181 while read base64_hash; do
1182
1183 echo -n ${base64_hash} | base64 -d >> ${temp_file}
1184
1185 done < ${OUTD}/${hash_type}_hashes_multi_${i}.txt
1186
1187 fi
1188
1189 CMD="./${BIN} ${OPTS} -a 6 -m ${hash_type} ${hash_file} ${OUTD}/${hash_type}_dict1_multi_${i} ${mask_6[$i]}"
1190
1191 echo "> Testing hash type $hash_type with attack mode 6, markov ${MARKOV}, multi hash with word len ${i}." &>> ${OUTD}/logfull.txt
1192
1193 output=$(./${BIN} ${OPTS} -a 6 -m ${hash_type} ${hash_file} ${OUTD}/${hash_type}_dict1_multi_${i} ${mask_6[$i]} 2>&1)
1194
1195 ret=${?}
1196
1197 echo "${output}" >> ${OUTD}/logfull.txt
1198
1199 if [ "${ret}" -eq 0 ]; then
1200
1201 j=1
1202
1203 while read -u 9 hash; do
1204
1205 line_dict1=$(sed -n ${j}p ${OUTD}/${hash_type}_dict1_multi_${i})
1206 line_dict2=$(sed -n ${j}p ${OUTD}/${hash_type}_dict2_multi_${i})
1207
1208 if [ ${pass_only} -eq 1 ]; then
1209 search=":${line_dict1}${line_dict2}"
1210 else
1211 search="${hash}:${line_dict1}${line_dict2}"
1212 fi
1213
1214 echo "${output}" | grep -F "${search}" &> /dev/null
1215
1216 if [ "${?}" -ne 0 ]; then
1217
1218 ret=10
1219
1220 break
1221
1222 fi
1223
1224 j=$((j + 1))
1225
1226 done 9< ${OUTD}/${hash_type}_hashes_multi_${i}.txt
1227
1228 fi
1229
1230 status ${ret}
1231
1232 done
1233
1234 msg="OK"
1235
1236 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
1237
1238 msg="Error"
1239
1240 elif [ "${e_to}" -ne 0 ]; then
1241
1242 msg="Warning"
1243
1244 fi
1245
1246 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 6, Mode multi ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
1247
1248 fi
1249 }
1250
1251 function attack_7()
1252 {
1253 file_only=0
1254
1255 if ! contains ${hash_type} ${FILE_BASED_ALGOS}; then
1256
1257 file_only=1
1258
1259 fi
1260
1261 # single hash
1262 if [ ${MODE} -ne 1 ]; then
1263
1264 e_to=0
1265 e_nf=0
1266 e_nm=0
1267 cnt=0
1268
1269 echo "> Testing hash type $hash_type with attack mode 7, markov ${MARKOV}, single hash." &>> ${OUTD}/logfull.txt
1270
1271 max=8
1272
1273 if [ "${hash_type}" -eq 2500 ]; then
1274
1275 max=5
1276
1277 fi
1278
1279 i=1
1280
1281 while read -u 9 hash; do
1282
1283 if [ $i -gt 1 ]; then
1284
1285 if [ "${file_only}" -eq 1 ]; then
1286
1287 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
1288 echo ${hash} | base64 -d > ${temp_file}
1289 hash="${temp_file}"
1290
1291 fi
1292
1293 mask=${mask_7[$i]}
1294
1295 # adjust mask if needed
1296
1297 if [ "${hash_type}" -eq 2500 ]; then
1298
1299 line_nr=$((i - 1))
1300
1301 pass_part_1=$(sed -n ${line_nr}p ${OUTD}/${hash_type}_dict1)
1302 pass_part_2=$(sed -n ${line_nr}p ${OUTD}/${hash_type}_dict2)
1303
1304 pass_part_2_len=${#pass_part_2}
1305
1306 pass=${pass_part_1}${pass_part_2}
1307 pass_len=${#pass}
1308
1309 # add first x chars of password to mask and append the (old) mask
1310
1311 mask_len=${#mask}
1312 mask_len=$((mask_len / 2))
1313
1314 mask_prefix=$(echo ${pass} | cut -b -$((pass_len - ${mask_len} - ${pass_part_2_len})))
1315 mask=${mask_prefix}${mask}
1316
1317 fi
1318
1319 CMD="./${BIN} ${OPTS} -a 7 -m ${hash_type} '${hash}' ${mask} ${OUTD}/${hash_type}_dict2"
1320
1321 echo -n "[ len $i ] " &>> ${OUTD}/logfull.txt
1322
1323 output=$(./${BIN} ${OPTS} -a 7 -m ${hash_type} "${hash}" ${mask} ${OUTD}/${hash_type}_dict2 2>&1)
1324
1325 ret=${?}
1326
1327 echo "${output}" >> ${OUTD}/logfull.txt
1328
1329 if [ "${ret}" -eq 0 ]; then
1330
1331 line_nr=$((i - 1))
1332
1333 line_dict1=$(sed -n ${line_nr}p ${OUTD}/${hash_type}_dict1)
1334 line_dict2=$(sed -n ${line_nr}p ${OUTD}/${hash_type}_dict2)
1335
1336 if [ ${pass_only} -eq 1 ]; then
1337 search=":${line_dict1}${line_dict2}"
1338 else
1339 search="${hash}:${line_dict1}${line_dict2}"
1340 fi
1341
1342 echo "${output}" | grep -F "${search}" &> /dev/null
1343
1344 if [ "${?}" -ne 0 ]; then
1345
1346 ret=10
1347
1348 fi
1349
1350 fi
1351
1352 status ${ret}
1353
1354 fi
1355
1356 if [ $i -eq ${max} ]; then break; fi
1357
1358 ((i++))
1359
1360 done 9< ${OUTD}/${hash_type}_hashes.txt
1361
1362 msg="OK"
1363
1364 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
1365
1366 msg="Error"
1367
1368 elif [ "${e_to}" -ne 0 ]; then
1369
1370 msg="Warning"
1371
1372 fi
1373
1374 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 7, Mode single ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
1375
1376 fi
1377
1378 # multihash
1379 if [ ${MODE} -ne 0 ]; then
1380
1381 e_to=0
1382 e_nf=0
1383 e_nm=0
1384 cnt=0
1385
1386 max=9
1387
1388 if [ ${hash_type} -eq 2500 ]; then
1389 max=5
1390 elif [ ${hash_type} -eq 3000 ]; then
1391 max=8
1392 elif [ ${hash_type} -eq 7700 ]; then
1393 max=8
1394 elif [ ${hash_type} -eq 8500 ]; then
1395 max=8
1396 fi
1397
1398 if ! contains ${hash_type} ${TIMEOUT_ALGOS}; then
1399
1400 max=7
1401
1402 if [ "${hash_type}" -eq 3200 ]; then
1403
1404 max=4
1405
1406 fi
1407
1408 fi
1409
1410 for ((i = 2; i < ${max}; i++)); do
1411
1412 hash_file=${OUTD}/${hash_type}_hashes_multi_${i}.txt
1413 dict_file=${OUTD}/${hash_type}_dict2_multi_${i}
1414
1415 mask=${mask_7[$i]}
1416
1417 # if file_only -> decode all base64 "hashes" and put them in the temporary file
1418
1419 if [ "${file_only}" -eq 1 ]; then
1420
1421 temp_file="${OUTD}/${hash_type}_filebased_only_temp.txt"
1422 rm -f ${temp_file}
1423
1424 hash_file=${temp_file}
1425
1426 while read base64_hash; do
1427
1428 echo -n ${base64_hash} | base64 -d >> ${temp_file}
1429
1430 done < ${OUTD}/${hash_type}_hashes_multi_${i}.txt
1431
1432 # a little hack: since we don't want to have a very large mask (and wpa has minimum length of 8),
1433 # we need to create a temporary dict file on-the-fly and use it like this: [small mask] [long(er) words in dict]
1434
1435 dict_file=${OUTD}/${hash_type}_dict2_multi_${i}_longer
1436 rm -f ${dict_file}
1437
1438 mask_len=${#mask}
1439 mask_len=$((mask_len / 2))
1440
1441 j=1
1442
1443 while read -u 9 hash; do
1444
1445 pass_part_1=$(sed -n ${j}p ${OUTD}/${hash_type}_dict1_multi_${i})
1446 pass_part_2=$(sed -n ${j}p ${OUTD}/${hash_type}_dict2_multi_${i})
1447
1448 pass="${pass_part_1}${pass_part_2}"
1449
1450 pass_suffix=$(echo "${pass}" | cut -b $((mask_len + 1))-)
1451
1452 echo "${pass_suffix}" >> ${dict_file}
1453
1454 j=$((j + 1))
1455
1456 done 9< ${OUTD}/${hash_type}_hashes_multi_${i}.txt
1457
1458 fi
1459
1460 CMD="./${BIN} ${OPTS} -a 7 -m ${hash_type} ${hash_file} ${mask} ${dict_file}"
1461
1462 echo "> Testing hash type $hash_type with attack mode 7, markov ${MARKOV}, multi hash with word len ${i}." &>> ${OUTD}/logfull.txt
1463
1464 output=$(./${BIN} ${OPTS} -a 7 -m ${hash_type} ${hash_file} ${mask} ${dict_file} 2>&1)
1465
1466 ret=${?}
1467
1468 echo "${output}" >> ${OUTD}/logfull.txt
1469
1470 if [ "${ret}" -eq 0 ]; then
1471
1472 j=1
1473
1474 while read -u 9 hash; do
1475
1476 line_dict1=$(sed -n ${j}p ${OUTD}/${hash_type}_dict1_multi_${i})
1477 line_dict2=$(sed -n ${j}p ${OUTD}/${hash_type}_dict2_multi_${i})
1478
1479 if [ ${pass_only} -eq 1 ]; then
1480 search=":${line_dict1}${line_dict2}"
1481 else
1482 search="${hash}:${line_dict1}${line_dict2}"
1483 fi
1484
1485 echo "${output}" | grep -F "${search}" &> /dev/null
1486
1487 if [ "${?}" -ne 0 ]; then
1488
1489 ret=10
1490
1491 break
1492
1493 fi
1494
1495 j=$((j + 1))
1496
1497 done 9< ${OUTD}/${hash_type}_hashes_multi_${i}.txt
1498
1499 fi
1500
1501 status ${ret}
1502
1503 done
1504
1505 msg="OK"
1506
1507 if [ "${e_nf}" -ne 0 -o "${e_nm}" -ne 0 ]; then
1508
1509 msg="Error"
1510
1511 elif [ "${e_to}" -ne 0 ]; then
1512
1513 msg="Warning"
1514
1515 fi
1516
1517 echo "[ ${OUTD} ] [ Type ${hash_type}, Attack 7, Mode multi ] > $msg : ${e_nf}/${cnt} not found, ${e_nm}/${cnt} not matched, ${e_to}/${cnt} timeout"
1518
1519 fi
1520 }
1521
1522 function usage()
1523 {
1524 cat << EOF
1525 > Usage : ${0} <options>
1526
1527 OPTIONS:
1528
1529 -t Select test mode :
1530 'single' => single hash (default)
1531 'multi' => multi hash
1532 'all' => single and multi hash
1533
1534 -m Select hash type :
1535 'all' => all hash type supported
1536 (int) => hash type integer code (default : 0)
1537
1538 -a Select attack mode :
1539 'all' => all attack modes
1540 (int) => attack mode integer code (default : 0)
1541
1542 -x Select cpu architecture :
1543 '32' => 32 bit architecture
1544 '64' => 64 bit architecture (default)
1545
1546 -o Select operating system :
1547 'win' => windows operating system (use .exe file extension etc)
1548 'linux' => *nix based operating systems (.bin for binaries)
1549 'osx' => mac osx operating systems (.app for binaries)
1550
1551 -c Disables markov-chains
1552
1553 -p Package the tests into a .7z file
1554
1555 -d Use this folder as input/output folder for packaged tests
1556 (string) => path to folder
1557
1558 -h Show this help
1559
1560 EOF
1561
1562 exit 1
1563 }
1564
1565 BIN="oclHashcat"
1566 MARKOV="enabled"
1567 ATTACK=0
1568 MODE=0
1569 HT=0
1570 PACKAGE=0
1571
1572 while getopts "t:m:a:b:hcpd:x:o:" opt; do
1573
1574 case ${opt} in
1575 "t")
1576 if [ ${OPTARG} == "single" ]; then
1577 MODE=0
1578 elif [ ${OPTARG} == "multi" ]; then
1579 MODE=1
1580 elif [ ${OPTARG} == "all" ]; then
1581 MODE=2
1582 else
1583 usage
1584 fi
1585 ;;
1586
1587 "m")
1588 if [ ${OPTARG} == "all" ]; then
1589 HT=65535
1590 else
1591 HT=${OPTARG}
1592 fi
1593 ;;
1594
1595 "a")
1596 if [ ${OPTARG} == "all" ]; then
1597 ATTACK=65535
1598 elif [ ${OPTARG} == "0" ]; then
1599 ATTACK=0
1600 elif [ ${OPTARG} == "1" ]; then
1601 ATTACK=1
1602 elif [ ${OPTARG} == "3" ]; then
1603 ATTACK=3
1604 elif [ ${OPTARG} == "6" ]; then
1605 ATTACK=6
1606 elif [ ${OPTARG} == "7" ]; then
1607 ATTACK=7
1608 else
1609 usage
1610 fi
1611 ;;
1612
1613 "c")
1614 OPTS="${OPTS} --markov-disable"
1615 MARKOV="disabled"
1616 ;;
1617
1618 "d")
1619 PACKAGE_FOLDER=$( echo ${OPTARG} | sed 's!/$!!g' )
1620 ;;
1621
1622 "p")
1623 PACKAGE=1
1624 ;;
1625
1626 "x")
1627 if [ ${OPTARG} == "32" ]; then
1628 ARCHITECTURE=32
1629 elif [ ${OPTARG} == "64" ]; then
1630 ARCHITECTURE=64
1631 else
1632 usage
1633 fi
1634 ;;
1635
1636 "o")
1637 if [ ${OPTARG} == "win" ]; then
1638 EXTENSION="exe"
1639 elif [ ${OPTARG} == "linux" ]; then
1640 EXTENSION="bin"
1641 elif [ ${OPTARG} == "osx" ]; then
1642 EXTENSION="app"
1643 else
1644 usage
1645 fi
1646 ;;
1647
1648 \?)
1649 usage
1650 ;;
1651
1652 "h")
1653 usage
1654 ;;
1655 esac
1656
1657 done
1658
1659 if [ -n "${ARCHITECTURE}" ]; then
1660
1661 BIN="${BIN}${ARCHITECTURE}"
1662
1663 fi
1664
1665 if [ -n "${EXTENSION}" ]; then
1666
1667 BIN="${BIN}.${EXTENSION}"
1668
1669 fi
1670
1671 if [ -n "${PACKAGE_FOLDER}" ]; then
1672
1673 if [ ! -e "${PACKAGE_FOLDER}" ]; then
1674 echo "! folder '${PACKAGE_FOLDER}' does not exist"
1675 exit 1
1676 fi
1677
1678 fi
1679
1680 if [ "${PACKAGE}" -eq 0 -o -z "${PACKAGE_FOLDER}" ]; then
1681
1682 # check existence of binary
1683 if [ ! -e "${BIN}" ]; then
1684 echo "! ${BIN} not found, please build binary before run test."
1685 exit 1
1686 fi
1687
1688 # filter by hash_type
1689 if [ ${HT} -ne 65535 ]; then
1690
1691 # validate filter
1692 check=0
1693 for hash_type in $(echo ${HASH_TYPES}); do
1694
1695 if [ ${HT} -ne ${hash_type} ]; then continue; fi
1696
1697 check=1
1698
1699 break
1700
1701 done
1702
1703 if [ ${check} -ne 1 ]; then
1704 echo "! invalid hash type selected ..."
1705 usage
1706 fi
1707
1708 fi
1709
1710 if [ -z "${PACKAGE_FOLDER}" ]; then
1711
1712 # make new dir
1713 mkdir -p ${OUTD}
1714
1715 # generate random test entry
1716 if [ ${HT} -eq 65535 ]; then
1717 perl tools/test.pl single > ${OUTD}/all.sh
1718 else
1719 perl tools/test.pl single ${HT} > ${OUTD}/all.sh
1720 fi
1721
1722 else
1723
1724 OUTD=${PACKAGE_FOLDER}
1725
1726 fi
1727
1728 rm -rf ${OUTD}/logfull.txt && touch ${OUTD}/logfull.txt
1729
1730 # populate array of hash types where we only should check if pass is in output (not both hash:pass)
1731 IFS=';' read -ra PASS_ONLY <<< "${MATCH_PASS_ONLY}"
1732 IFS=';' read -ra TIMEOUT_ALGOS <<< "${SLOW_ALGOS}"
1733
1734 IFS=';' read -ra NEVER_CRACK_ALGOS <<< "${NEVER_CRACK}"
1735
1736 # for these particular algos we need to save the output to a temporary file
1737 IFS=';' read -ra FILE_BASED_ALGOS <<< "${HASHFILE_ONLY}"
1738
1739 for hash_type in $(echo $HASH_TYPES); do
1740
1741 if [[ ${HT} -ne 65535 ]] && [[ ${HT} -ne ${hash_type} ]]; then continue; fi
1742
1743 if [ -z "${PACKAGE_FOLDER}" ]; then
1744
1745 # init test data
1746 init
1747
1748 else
1749
1750 echo "[ ${OUTD} ] > Run packaged test for hash type $hash_type."
1751
1752 fi
1753
1754 if [ "${PACKAGE}" -eq 0 ]; then
1755
1756 # should we check only the pass?
1757 contains ${hash_type} ${PASS_ONLY}
1758 pass_only=$?
1759
1760 contains ${hash_type} ${SLOW_ALGOS}
1761 IS_SLOW=$?
1762
1763 if [[ ${hash_type} -eq 400 ]]; then
1764 # we use phpass as slow hash for testing the AMP kernel
1765 IS_SLOW=0
1766 fi
1767
1768 if [[ ${IS_SLOW} -eq 1 ]]; then
1769
1770 # run attack mode 0 (stdin)
1771 if [[ ${ATTACK} -eq 65535 ]] || [[ ${ATTACK} -eq 0 ]]; then attack_0; fi
1772
1773 else
1774 # run attack mode 0 (stdin)
1775 if [[ ${ATTACK} -eq 65535 ]] || [[ ${ATTACK} -eq 0 ]]; then attack_0; fi
1776
1777 # run attack mode 1 (combinator)
1778 if [[ ${ATTACK} -eq 65535 ]] || [[ ${ATTACK} -eq 1 ]]; then attack_1; fi
1779
1780 # run attack mode 3 (bruteforce)
1781 if [[ ${ATTACK} -eq 65535 ]] || [[ ${ATTACK} -eq 3 ]]; then attack_3; fi
1782
1783 # run attack mode 6 (dict+mask)
1784 if [[ ${ATTACK} -eq 65535 ]] || [[ ${ATTACK} -eq 6 ]]; then attack_6; fi
1785
1786 # run attack mode 7 (mask+dict)
1787 if [[ ${ATTACK} -eq 65535 ]] || [[ ${ATTACK} -eq 7 ]]; then attack_7; fi
1788 fi
1789 fi
1790
1791 done
1792
1793 else
1794
1795 OUTD=${PACKAGE_FOLDER}
1796
1797 fi
1798
1799 # fix logfile
1800 if [ "${PACKAGE}" -eq 0 ]; then
1801
1802 cat -A ${OUTD}/logfull.txt | sed -e 's/\^M \^M//g' | sed -e 's/\$$//g' > ${OUTD}/test_report.log
1803
1804 fi
1805
1806 rm -rf ${OUTD}/logfull.txt
1807
1808 if [ "${PACKAGE}" -eq 1 ]; then
1809
1810 echo "[ ${OUTD} ] > Generate package ${OUTD}/${OUTD}.7z"
1811
1812 cp "${BASH_SOURCE[0]}" ${OUTD}/test.sh
1813
1814 # if we package from a given folder, we need to check if e.g. the files needed for multi mode are there
1815
1816 if [ -n "${PACKAGE_FOLDER}" ]; then
1817
1818 MODE=2
1819
1820 ls "${PACKAGE_FOLDER}"/*multi* &> /dev/null
1821
1822 if [ "${?}" -ne 0 ]
1823 then
1824
1825 MODE=0
1826
1827 fi
1828
1829 HT=$(grep -o -- "-m *[0-9]*" ${PACKAGE_FOLDER}/all.sh | sort -u | sed 's/-m //' 2> /dev/null)
1830
1831 if [ -n "${HT}" ]; then
1832
1833 HT_COUNT=$(echo "${HT}" | wc -l)
1834
1835 if [ "${HT_COUNT}" -gt 1 ]; then
1836
1837 HT=65535
1838
1839 fi
1840
1841 fi
1842
1843 #ATTACK=65535 # more appropriate ?
1844 fi
1845
1846 # for convenience: 'run package' is default action for packaged test.sh ( + add other defaults too )
1847
1848 sed -i -e 's/^\(PACKAGE_FOLDER\)=""/\1="$( echo "${BASH_SOURCE[0]}" | sed \"s!test.sh\\$!!\" )"/' \
1849 -e "s/^\(HT\)=0/\1=${HT}/" \
1850 -e "s/^\(MODE\)=0/\1=${MODE}/" \
1851 -e "s/^\(ATTACK\)=0/\1=${ATTACK}/" \
1852 ${OUTD}/test.sh
1853
1854 ${PACKAGE_CMD} ${OUTD}/${OUTD}.7z ${OUTD}/ &> /dev/null
1855
1856 fi