Import brute-force cracker.

This commit is contained in:
Peter Boraros 2011-11-09 04:41:42 +01:00
parent 604a8f36d9
commit ea9646bfd9
5 changed files with 401 additions and 0 deletions

3
bin/cracker.sh Normal file
View file

@ -0,0 +1,3 @@
#!/bin/bash
. libs.sh
java -cp $CP cz.cvut.keyczar.homework.Cracker $@

View file

@ -0,0 +1,73 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cz.cvut.keyczar.homework;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
*
* @author pborky
*/
public class Cracker {
public static final String MESSAGE = "Hello world!";
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Runnable messageVerifier;
if (args.length < 4) {
System.out.println("Usage:");
System.out.println("cracker <host> <port> <message> <limitIterations> [<signatureByte0> [<signatureByte1> [ ... <signatureByte24>]]]");
System.out.println("\t<host>, <port> - u know");
System.out.println("\t<message> - what to send");
System.out.println("\t<limitIterations> - max. number of iterations per one byte");
System.out.println("\t<signatureByteX> - is hex of the signature`s byte");
System.out.println("\tnote: you must provide at least 5 bytes of signature");
System.exit(-1);
}
String host = args[0]; //
int port = Integer.parseInt(args[1]); //
String msg = args[2]; // message
int iMax = Integer.parseInt(args[3]); // max. iterations
byte[] sig = null;
if (args.length>3) {
sig = new byte[args.length-4];
for (int i = 4; i < args.length; i++) {
sig[i - 4] = (byte)Integer.parseInt(args[i],16);
}
}
char[] m = msg.isEmpty()?MESSAGE.toCharArray():msg.toCharArray();
messageVerifier = createMessageGenerator(host, port, iMax, sig, m);
messageVerifier.run();
}
private static Runnable createMessageGenerator(String host, int port, int iMax, byte[] signature, char[] msg) {
try {
Socket sock;
sock = new Socket(host, port);
System.out.println("Connected");
InputStream is = sock.getInputStream();
OutputStream os = sock.getOutputStream();
return new HmacCracker(os, is, iMax, signature, msg);
}
catch (Throwable t) {
System.err.println("Can't load Generator: " + t.getMessage());
throw new RuntimeException(t);
}
}
}

View file

@ -0,0 +1,31 @@
package cz.cvut.keyczar.homework;
import java.util.ArrayList;
import java.util.List;
public class CrackerCore {
public static byte[] select(List<long[]> stats) {
// each item of the stats must have length exactly Byte.MAX_VALUE
double[] means = Stats.mean(stats);
if (means.length >= Byte.MAX_VALUE) {
throw new RuntimeException("Something gone wrong. Expecting exactly "+ Byte.MAX_VALUE+ " items.");
}
ArrayList<Byte> idx = new ArrayList<Byte>();
// TODO: implement your code here **************************
// for each byte test the condition
for (byte i = 0; i< means.length; i++) {
idx.add(i);
}
// *********************************************************
if (idx.isEmpty() || idx.size() > 6) return null;
byte[] result = new byte[idx.size()];
int i = 0; for (byte b : idx) result[i++] = b;
return result;
}
}

View file

@ -0,0 +1,195 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cz.cvut.keyczar.homework;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author pborky
*/
public class HmacCracker implements Runnable {
private final OutputStream outputStream;
private final InputStream inputStream;
byte[] message;
int hmacPtr = 0;
byte[] hmac;
int maxIterations;
int totalIterations = 0;
public HmacCracker(OutputStream outputStream, InputStream inputStream, int iMax, byte[] signature, char[] msg) {
this.outputStream = outputStream;
this.inputStream = inputStream;
try {
for (int r=this.inputStream.read(); r!='\n'; r=this.inputStream.read()) { }
} catch (IOException e) {
throw new RuntimeException(e);
}
this.message = new byte[msg.length];
for (int i=0; i<msg.length; i++) {
this.message[i] = (byte)msg[i];
}
this.hmac = new byte[26];
Arrays.fill(this.hmac, (byte)0xff);
this.hmac[this.hmacPtr++] = 0; // separator
maxIterations = iMax;
if (null != signature) {
if (signature.length > 25) {
throw new IllegalArgumentException("You may give up to 25 HMAC digits.");
}
System.arraycopy(signature, 0, this.hmac, 1, signature.length);
hmacPtr += signature.length;
if (hmacPtr > this.hmac.length) {
hmacPtr = this.hmac.length - 1;
}
}
}
public void run() {
try {
dfs(hmac, hmacPtr);
} catch (Success s) {
System.out.println("\nSuccess in "+totalIterations+" iterations!");
System.out.print("HMAC: ");
System.out.println(bytesToHexStr(s.getHMAC()));
return;
}
System.out.println("\nFailed to find HMAC! Try raise iteration limit.");
}
private boolean dfs(byte[] hmac, int ptr) {
byte[] guessed = null;
if (ptr <= this.hmac.length) {
guessed = guessNext(message, hmac, ptr, maxIterations, inputStream, outputStream);
if (guessed==null) {
System.out.println("\nDead end!");
return false;
}
System.out.print("\nPossible choices: ");
System.out.println(bytesToHexStr(guessed));
for (int g: guessed) {
System.out.print("\nGuessing: ");
System.out.println(Integer.toHexString((0xff & g)));
byte[] hm = Arrays.copyOf(hmac, hmac.length);
hm[ptr] = (byte) (0xff & g);
if (dfs(hm,ptr+1)) {
return true;
}
}
}
return false;
}
private byte[] guessNext(byte[] msg, byte[] hmac, int ptr, int maxIt, InputStream is, OutputStream os) {
List<long[]> statsPool = new ArrayList<long[]>();
System.out.print("\nHMAC: ");
System.out.println(bytesToHexStr(hmac));
System.out.print("Cracking");
int bin = 4;
while (maxIt>0) {
for (int j = 0 ; j < bin; j++ ) {
long[] stats = new long[256];
for (int b = 0; b<256; b++) {
if (ptr < hmac.length) {
hmac[ptr] = (byte)(0xff&b);
}
int resp = sendData(b, is, os, msg, hmac, stats);
if (resp == 'N') {
//
} else if (resp == 'O') {
throw new Success(hmac);
} else {
throw new UnexpectedContent();
}
totalIterations++;
}
System.out.write('.');System.out.flush();
statsPool.add(Arrays.copyOf(stats, stats.length));
maxIt--;
}
byte[] bestM = CrackerCore.select(statsPool);
if (bestM == null) {
bin = bin*2;
System.out.print("#"); // we need to collect more stats
continue;
}
return bestM;
}
return null;
}
private String bytesToHexStr(byte[] hmac) {
if (hmac==null) return "";
StringBuilder sb = new StringBuilder();
for (byte x:hmac) {
sb.append(Integer.toHexString(0xff&x)).append(' ');
}
return sb.toString();
}
private String bytesToHexStr(int[] hmac) {
if (hmac==null) return "";
StringBuilder sb = new StringBuilder();
for (int x:hmac) {
sb.append(Integer.toHexString(0xff&x)).append(' ');
}
return sb.toString();
}
private int sendData(int b, InputStream is, OutputStream os, byte[] msg, byte[] hmac, long[] stats) {
try { //[101, 99, 104, 111, 95, 97, 104, 111, 106, 0, 0, 215, 137, 187, 50, 234, 124, 87, 103, 149, 169, 195, 50, 10, 79, 183, 36, 166, 199, 0, 11, 157, 207, 34, 228]
os.write(msg);
os.write(hmac);
long start,stop;
start = System.nanoTime();
os.flush();
int s = is.read();
stop = System.nanoTime();
for (int r=is.read(); r!='\n'; r=is.read()) { }
if (stats != null) {
stats[b] = stop - start;
}
return s;
} catch (IOException ex) {
Logger.getLogger(HmacCracker.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
}
private class Success extends RuntimeException {
private byte [] hmac;
public Success(byte[] hmac) {
super(bytesToHexStr(hmac));
this.hmac = hmac;
}
public byte[] getHMAC() {
return this.hmac;
}
}
private class UnexpectedContent extends RuntimeException {
public UnexpectedContent() {
super();
}
public UnexpectedContent(String msg) {
super(msg);
}
}
}

View file

@ -0,0 +1,99 @@
package cz.cvut.keyczar.homework;
import java.util.List;
/**
*
* @author pborky
*/
public class Stats {
public static double[] mean(List<long[]> series) {
int width = series.get(0).length;
int height = series.size();
double[] sums = new double[width];
double[] means = new double[width];
for (long[] s: series) {
for (int i = 0; i<s.length; i++) {
sums[i] += s[i];
}
}
for (int i = 0; i < width; i++) {
means[i] = sums[i]/height;
}
return means;
}
public static double mean(long[] series) {
double sum = 0;
for (long s: series) {
sum += s;
}
return sum/series.length;
}
public static double mean(double[] series) {
double sum = 0;
for (double s: series) {
sum += s;
}
return sum/series.length;
}
public static double std(List<long[]> series, double mean) {
int width = series.get(0).length;
int height = series.size();
double stD = 0;
double sumsQ = 0;
for (long[] s: series) {
for (int i = 0; i<s.length; i++) {
double diff = s[i] - mean;
sumsQ += diff * diff;
}
}
return Math.sqrt(sumsQ/(width*height));
}
public static double[] std(List<long[]> series, double[] means) {
int width = series.get(0).length;
int height = series.size();
double[] stD = new double[width];
double[] sumsQ = new double[width];
for (long[] s: series) {
for (int i = 0; i<s.length; i++) {
double diff = s[i] - means[i];
sumsQ[i] += diff * diff;
}
}
for (int i = 0; i < width; i++) {
stD[i] = Math.sqrt(sumsQ[i]/height);
}
return stD;
}
public static double std(long[] series) {
return std(series, mean(series));
}
public static double std(long[] series, double mean) {
double sqDiffSum = 0;
for(long s: series ) {
double diff = s - mean;
sqDiffSum += diff * diff;
}
return Math.sqrt(sqDiffSum / series.length);
}
public static double std(double[] series) {
return std(series, mean(series));
}
public static double std(double[] series, double mean) {
double sqDiffSum = 0;
for(double s: series) {
double diff = s - mean;
sqDiffSum += diff * diff;
}
return Math.sqrt(sqDiffSum / series.length);
}
}