Skip to content

Instantly share code, notes, and snippets.

@jasiek
Created February 4, 2014 13:50
Show Gist options
  • Save jasiek/8803881 to your computer and use it in GitHub Desktop.
Save jasiek/8803881 to your computer and use it in GitHub Desktop.
Stripe CTF 2014 Java Miner.
import java.lang.ProcessBuilder;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.security.MessageDigest;
import javax.xml.bind.DatatypeConverter;
public class Miner {
public static String DIRECTORY = "level1";
public static void solve(String difficulty, String directory) throws Exception {
// Create an entry in the ledger.
FileWriter ledger = new FileWriter(directory + "/LEDGER.txt", true);
ledger.write("user-fn27nmtz: 1\n");
ledger.close();
run("git add LEDGER.txt", directory);
String tree = run("git write-tree", directory);
String parent = run("git rev-parse HEAD", directory);
long timestamp = System.currentTimeMillis() / 1000;
int counter = 0;
StringBuilder sb = new StringBuilder();
sb.append(String.format("tree %s\n", tree));
sb.append(String.format("parent %s\n", parent));
sb.append(String.format("author LOL <lol@biz.info> %d +0000", timestamp) + "\n");
sb.append(String.format("commiter LOL <lol@biz.info> %d +0000", timestamp) + "\n");
sb.append("\n");
String body = sb.toString();
String content = String.format("commit %d\0", body.length() + 10) + body;
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(content.getBytes("UTF-8"));
while (true) {
MessageDigest digestClone = (MessageDigest)digest.clone();
String counterString = formatCounter(counter);
digestClone.update(counterString.getBytes("UTF-8"));
String sha1 = DatatypeConverter.printHexBinary(digestClone.digest());
if (sha1.compareTo(difficulty) < 0) {
System.out.println("found: " + sha1);
FileWriter tmpbody = new FileWriter(directory + "/body");
tmpbody.write(body + counterString);
tmpbody.close();
puts(run("git hash-object -t commit -w body", directory));
puts(run(String.format("git reset --hard %s", sha1), directory));
break;
}
counter++;
}
}
public static String formatCounter(int counter) {
char[] digits = new char[10];
for (int d = 9; d >= 0; d--) {
digits[d] = Character.forDigit(counter % 10, 10);
counter /= 10;
}
return new String(digits);
}
public static String run(String command, String directory) throws Exception {
ProcessBuilder pb = new ProcessBuilder(command.split(" "));
pb.directory(new File(directory));
Process p = pb.start();
p.waitFor();
if (p.exitValue() != 0) throw new Exception("command: " + command + " failed.");
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
return reader.readLine();
}
public static String readDifficulty() throws Exception {
BufferedReader br = new BufferedReader(new FileReader("level1/difficulty.txt"));
return br.readLine();
}
public static int commit(String directory) throws Exception {
Process p = Runtime.getRuntime().exec("git push origin master".split(" "), null, new File(directory));
p.waitFor();
return p.exitValue();
}
public static void reset(String directory) throws Exception {
puts(run("git log", directory));
puts(run("git fetch origin master", directory));
puts(run("git reset --hard origin/master", directory));
}
public static void puts(String s) {
System.out.println(s);
}
public static void main(String[] args) {
try {
String difficulty = readDifficulty().toUpperCase();
reset(DIRECTORY);
while (true) {
solve(difficulty, DIRECTORY);
if (commit(DIRECTORY) == 0) {
break;
} else {
reset(DIRECTORY);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment