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