mirror of
https://github.com/brmlab/timingattack.git
synced 2025-06-08 17:14:10 +02:00
Import brute-force cracker.
This commit is contained in:
parent
604a8f36d9
commit
ea9646bfd9
5 changed files with 401 additions and 0 deletions
3
bin/cracker.sh
Normal file
3
bin/cracker.sh
Normal file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
. libs.sh
|
||||
java -cp $CP cz.cvut.keyczar.homework.Cracker $@
|
73
src/cz/cvut/keyczar/homework/Cracker.java
Normal file
73
src/cz/cvut/keyczar/homework/Cracker.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
31
src/cz/cvut/keyczar/homework/CrackerCore.java
Normal file
31
src/cz/cvut/keyczar/homework/CrackerCore.java
Normal 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;
|
||||
}
|
||||
}
|
195
src/cz/cvut/keyczar/homework/HmacCracker.java
Normal file
195
src/cz/cvut/keyczar/homework/HmacCracker.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
99
src/cz/cvut/keyczar/homework/Stats.java
Normal file
99
src/cz/cvut/keyczar/homework/Stats.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue