package no.ntnu.item.cda; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.security.Security; import org.apache.hadoop.filecache.DistributedCache; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapred.FileInputFormat; import org.apache.hadoop.mapred.FileOutputFormat; import org.apache.hadoop.mapred.JobClient; import org.apache.hadoop.mapred.JobConf; import org.apache.hadoop.mapred.TextOutputFormat; import org.apache.hadoop.mapred.lib.NLineInputFormat; public class Processor { public static byte[] ciphertext; public static byte[] salt; public static String password; public static boolean found; public static double time; public static long start; public static int words_read; public static void printHelp() { System.out.println("************************************************"); System.out.println("\t\tHELP"); System.out.println("************************************************"); System.out.println("Cloud Dictionary attack"); System.out .println("\t [1 arg]: Path to dictionary file in distributed file system. The dictionary file should contain lines with passwords separated by SPACE. The number of passwords per line must be a multiple of the number of threads used per server ([5 arg])."); System.out .println("\t [2 arg]: Path to output file in distributed file system"); System.out .println("\t [3 arg]: Path to credentials file in distributed file system"); System.out.println("\t [4 arg]: Number of working server nodes to use"); System.out .println("\t [5 arg]: Number of threads to use for each server node"); System.out .println("\nNOTE: Make sure you have installed the Java(TM) \nCryptography Extension (JCE) Jurisdiction Policy \nFiles and that you are using Bouncy Castle as \nprimary JCE provider prior to execution. Check \nout [0] for more information.\n\n[0] http://znjp.com/mcdaniel/BC.html"); } public static int[] getDictionaryMetadata(String filename, JobConf conf) throws IOException { FSDataInputStream in = null; FileSystem fs = FileSystem.get(conf); Path path = new Path(filename); in = fs.open(path); InputStream is = new BufferedInputStream(in); try { byte[] c = new byte[1024]; int col_count = 0; int row_count = 0; int readChars = 0; while ((readChars = is.read(c)) != -1) { for (int i = 0; i < readChars; ++i) { if (c[i] == '\n') { ++row_count; } if (row_count == 0 && c[i] == ' ') ++col_count; } } int[] metadata = { row_count, col_count }; return metadata; } finally { is.close(); } } public static void main(String[] args) throws Exception { Security.insertProviderAt( new org.bouncycastle.jce.provider.BouncyCastleProvider(), 1); if (args.length < 5 || args.length > 5 || args[0].equalsIgnoreCase("-h") || args[0].equalsIgnoreCase("--help")) { printHelp(); System.exit(0); } JobConf conf = new JobConf(Processor.class); conf.setJobName("dictionaryattack"); int[] dict_metadata = getDictionaryMetadata(args[0], conf); int MAPPERS = 0; try { MAPPERS = Integer.parseInt(args[3]); } catch (Exception e) { System.out .println("ERROR: The number of server nodes given is not a number."); System.exit(1); } int THREADS = 0; try { THREADS = Integer.parseInt(args[4]); if (THREADS > 0) { conf.setInt("THREADS", THREADS); } else { throw new Exception(); } if (dict_metadata[1] >= THREADS) { conf.setInt("PASSWORDS_PER_LINE", dict_metadata[1]); } else { throw new Exception(); } } catch (Exception e) { System.out .println("ERROR: The number of threads given is not a valid number. Make sure that the number of threads is greater than or equal to the number of passwords, per line, in the dictionary.\n\n Use the -h or --help option for more information."); System.exit(1); } conf.setOutputKeyClass(Text.class); conf.setOutputValueClass(LongWritable.class); conf.setMapperClass(CDAMapper.class); conf.setInputFormat(NLineInputFormat.class); conf.setOutputFormat(TextOutputFormat.class); FileInputFormat.setInputPaths(conf, new Path(args[0])); FileOutputFormat.setOutputPath(conf, new Path(args[1])); conf.setNumReduceTasks(0); conf.setNumMapTasks(MAPPERS); conf.setCompressMapOutput(true); int dict_lines = dict_metadata[0]; double lines_per_mapper = dict_lines / MAPPERS; if (Math.floor(lines_per_mapper) == lines_per_mapper) { conf.setInt("mapred.line.input.format.linespermap", dict_lines / MAPPERS); } else { conf.setInt("mapred.line.input.format.linespermap", (dict_lines / MAPPERS) + 1); } DistributedCache.addCacheFile(new URI(args[2]), conf); JobClient.runJob(conf); } }