#!C:\Perl\bin\perl.exe # Change the above line to point to Perl on your system ########################################################################################## # # Written to help crack the hackthissite.org realistic mission level 6 XECryption challenge. # # By Dave Lauderdale : Published at projects.digi-dl.com (Win32 version BETA) # # This script was tested on Windows XP with Active State Perl. NOTE: The Linux version # is much quicker overall. Windows users can run the Linux version if you download # cygwin with the proper packages. # # Place the hash file in the same directory as this script and name it "hash.txt". # If you want to use the -a option then also be sure to place the wordlist file # in the same directory and name it "wordlist.txt". For messing around I recommend the # smaller wordlist, it's much faster and will help you crack both ciphertext files. # # I do NOT recommend using the large wordlist on the windows version unless you have time ;) # # This is an educational tool and logs a lot of data to disk for further analysis, these # logs are deleted when the program exits. # If you dont use notepad then enter your text editor here my $txt_editor='notepad'; # ########################################################################################## use strict; use warnings; # set global variables my @hash_array;my @sorted_array;my $key_value;my $total_chars;my $min_val;my $ascii_val;my $ARGV;my $automate_it="FALSE";my $sum_list;my $file_type; # display usage if(!@ARGV) {usage();} if($ARGV[0] eq "-a") {$automate_it='TRUE';} # if user enters something other than an integer or -a or -c then show usage if($ARGV[0] ne "-a" && $ARGV[0] ne "-c" && $ARGV[0] =~ /[^0987654321]/){usage();} # If key used is an extended ASCII char then errors/warnings might occur # you can comment this out to use the extended values 127-255 if($ARGV[0] ne "-a" && $ARGV[0] ne "-c" && $ARGV[0] > 126){usage();} else {$key_value = $ARGV[0];} sub usage{ for (my $line=0;$line<55;$line++) {print "=";} print "\nUSAGE: $0 [option]\n\n"; print "Options:\n"; print " is the ASCII char key to use: 10 = LF, 32 = SPACE. Also try 33-126\n\n"; print "-a This option will automate the key process. This will calculate all 1 - 126 ASCII chars into "; print "keys, do the math then place the results in RESULTS/*.txt for further analysis. If you want to "; print "attempt to brute force the result files you will be prompted to enter \"-b\".\n\n"; print "-c This option will simply crack the HTS level6 XECryption challenge.\n\n"; print "NOTES:\n"; print "If you DONT use the -a option your results will be opened in $txt_editor. If you use another text "; print "editor you will want to change this in the source code.\n"; for (my $line=0;$line<55;$line++) {print "=";} print "\n"; exit 0; } # let's begin... # Lets get rid of OLD results files if there are any if (-e "CRACKED.txt") {system("del CRACKED.txt");} if (-e "RESULTS") { system("rmdir /S /Q RESULTS");} if (-e "STRING.txt") { system("del STRING.txt; del SUMS.txt; del SORT.txt; rmdir /Q /S tmp; del SIZE.txt; del ASCII.txt; del crack_it.bat>> del.log");} # open hash file open(FILE, "hash.txt") || no_file_error($file_type='hash'); # import data from hash file (as is) while (defined (my $hash_list = )){ chomp($hash_list); #remove first period of hash my $char_compare = substr($hash_list, 0, 1); if($char_compare eq ".") {$hash_list = substr($hash_list, 1);} # in case user broke up elements for counting we write data back to disk but as a single string open(STRING, ">>STRING.txt") || die "Error: can't open STRING file: $!"; print (STRING $hash_list); close(STRING) || die "Error: can't close STRING file: $!"; } close(FILE) || die "Error: can't close hash file: $!"; # open the tmp file and import hash data as single string open(TMP2, "STRING.txt") || die "Error: can't open TMP2 file: $!"; # set starting points for array calculations my $hash_set1="0"; my $hash_set2="1"; my $hash_set3="2"; # create an array to hold each set of numbers while (defined (my $hash_line = )){ @hash_array = split(/\./, $hash_line); # let get total hash elements, xxx.xxx.xxx = 3 elements my $total_hash_elements=@hash_array; # each three elements = one ASCII char $total_chars=int($total_hash_elements/3); for(my $x=0;$x<$total_chars;$x++){ # grab first three number sets and do the math my $sum=int($hash_array[$hash_set1] + $hash_array[$hash_set2] + $hash_array[$hash_set3]); open(SUM, ">>SUMS.txt") || die "Error: can't open SUM file: $!"; print (SUM $sum,"\n"); close(SUM) || die "Error: can't close SUM file: $!"; # increment by three : next loop will grab next three number sets to calculate etc... $hash_set1=int($hash_set1+3); $hash_set2=int($hash_set2+3); $hash_set3=int($hash_set3+3); } } close(TMP2) || die "Error: can't close TMP2 file: $!"; # open SUM file and import sums into an array open (SUM2, "SUMS.txt") || die "Error: can't open SUM2 file: $!"; my @sum_list=(); my $x_val=int($total_chars - 1); # sort sum_list for minimum and maximum values @sorted_array = sort @sum_list; $min_val=int($sorted_array[0]); my $max_val=int($sorted_array[$x_val]); print "Lets get some necessary values...\n"; print "Maximum value = ",$max_val,"\nMinimum value = ",$min_val,"\n"; # save sorted data to disk open(SORT, ">SORT.txt") || die "Error: can't open SORT file: $!"; print (SORT @sorted_array); close(SORT) || die "Error: can't close SORT file: $!"; close(SUM2) || die "Error: can't close SUM2 file: $!"; my $results_dir="FALSE"; my $prev_dir = "RESULTS"; if(-e $prev_dir) {$results_dir="TRUE";} if($automate_it eq 'TRUE'){ print "\nYou chose to automate the key process. This may take some time...the Linux version is *much* quicker. Please be patient.\n\n"; if($results_dir eq "FALSE") { mkdir("RESULTS") || die "Cannot make directory RESULTS: $!"; } open(SUM3, "SUMS.txt") || die "Error: can't open SUM3 file: $!"; while (defined (my $sum_list = )){ for(my $ascii_table=0;$ascii_table<127;$ascii_table++){ # delete key from pre calculated sums my $ascii_sum = int($sum_list - ($min_val-$ascii_table)); $ascii_val=chr($ascii_sum); # place new values in results file open(RESULTS, ">> RESULTS/$ascii_table.txt") || die "Error: can't open RESULTS file: $!"; print (RESULTS $ascii_val); close(RESULTS) || die "Error: can't close RESULTS file: $!"; } } print "###DONE!\n"; close(SUM3) || die "Error: can't close SUM3 file: $!"; crack_it(); } if($automate_it eq 'FALSE') { open(SUM3, "SUMS.txt") || die "Error: can't open SUM3 file: $!"; while (defined ($sum_list = )){ # if user just wants to crack the challenge then supply the correct value 10 = LF = if($ARGV[0] eq "-c") {$key_value="10";} # delete key from pre calculated sums my $ascii_sum = int($sum_list - ($min_val-$key_value)); $ascii_val=chr($ascii_sum); # place new values in ascii file open(ASC, ">>ASCII.txt") || die "Error: can't open ASC file: $!"; print (ASC $ascii_val); close(ASC) || die "Error: can't close ASC file: $!"; } close(SUM3) || die "Error: can't close SUM3 file: $!"; # display results system("$txt_editor ASCII.txt"); print "\#\#\# DONE! Press any key to exit program: "; my $foo_bar=; clean_up(); } sub crack_it{ print "\nYour results files are located in RESULTS/* the files are named after the ASCII key used. Example: If the 32.txt file has your plaintext message then 32 was they key used to crack the ciphertext.\n\nIf you want to attempt to brute force the results using the wordlist file then type \"-b\". Note: This is a crude/buggy brute forcing technique but it works good enough for this script also, this is *much* slower than the Linux version. To skip brute forcing and just exit press \: "; chomp(my $user_answer=); if($user_answer ne "-b") {clean_up();} if (! -e "wordlist.txt") { no_file_error($file_type='wordlist');} open(ORIGWORD, "wordlist.txt") || die "Error: can't open ORIGWORD file: $!"; my @original_list=(); my @sorted_list = sort @original_list; open(NEWWORD, ">>new_wordlist.txt") || die "Error: can't open NEWWORD file: $!"; print (NEWWORD @sorted_list); close(NEWWORD) || die "Error: can't close NEWWORD file: $!"; close(ORIGWORD) || die "Error: can't close ORIGWORD file: $!"; system("move new_wordlist.txt wordlist.txt"); # attempt a crude brute forcing of the RESULTS files. open(WORDS, "wordlist.txt") || no_file_error($file_type='wordlist'); print "\nAttempting to brute force the results files:\n"; # for (my $a=0;$a<55;$a++) {print"=";} print "\n"; my $word_count=0; # lazy me ;) open(BATCH, ">>crack_it.bat") || die "Error: can't open BATCH file: $!"; print (BATCH "\@echo off\n"); print (BATCH "cd RESULTS\n"); print (BATCH "findstr \" %1 \" %2.txt >> ../CRACKED.txt\n"); close(BATCH) || die "Error: can't close BATCH file: $!"; while (defined (my $word = )){ chomp($word); # eachtime we try a word we increase the count for(my $y=0;$y<126;$y++){ system("crack_it.bat $word $y"); $word_count++; print "."; } } close(WORDS) || die "Error: can't close WORDS file: $!"; print "\n\nEOF : wordlist.txt is exausted.\n"; for (my $z=0;$z<10;$z++) {print"=";} print "\n"; # the word count is buggy here...works fine under Linux ;) #print "Total words tried: \[",$word_count,"\]\n"; my $cracked_file_size = -s 'CRACKED.txt'; if($cracked_file_size gt "1"){ print "Successfull hit: \[Yes\]\t(Note: This could contain some false positives)\n\n"; print "\#\#\# DONE! Your results are in CRACKED.txt. If you would like to view this file in $txt_editor then type \"-v\" or just press enter to exit program: "; chomp(my $input=); if($input ne "-v") {clean_up();} else {system("$txt_editor CRACKED.txt"); clean_up();} } else {print "Successfull hit: \[No\]\n\n"; clean_up();} } sub clean_up{ # delete data file(s) and exit. If you do not want to delete the files then comment # out this line and all the files will be left on disk for further analysis system("del STRING.txt; del SUMS.txt; del SORT.txt; rmdir tmp; del SIZE.txt; del crack_it.bat; del ASCII.txt >> del.log"); # exit program ; do not comment out this line exit 0; } sub no_file_error{ print "\n* Error: You have to place \"$file_type.txt\" in the same directory as $0\n\n"; clean_up(); }