[Java Source] ArchiveCracker 01-02-2013, 04:02 PM
#1
TheAlchemist asked me to create a zip cracker a while ago. I am sorry that it took so long, but I didn't forget your request. This program can actually crack other password protected archives too (i.e. rar).
This is a simple command line program by now. I commented the code so you can take it as example. The cracking is relatively slow, because I didn't use any threads. But I think this way it is more understandable for you.
I will add threads and a GUI later and make it a release then.
Don't forget to give credit if you use this code for your own programs.
Download: http://www.multiupload.nl/IT139Z5LKM
Usage: java -jar archivecracker <archive> [<wordlist>]
wordlist is a file which contains passwords for a wordlist attack. If you don't give a wordlist, it will generate the words, but only a-z (you can change it, though).
Starting point of the program is the CLI.
This class contains the main functionality, the ArchiveCracker.
Note that I had to use a little hack to get the functionality I wanted. The 7-Zip-JBinder library is not designed for checking passwords. It would actually try to extract the file if the password is correct, which I don't want. Because of that I throw a PasswordFoundException in the output stream instead of writing anything. This is not a good way, since exceptions are not there to define the program logic, but it is the only possible way with this library (and others too).
Last but not least the word generation. I explained it in a tutorial here: http://www.hackcommunity.com/Thread-Tut-...uteforcing
This is a slightly modified version. I made it more flexible, so it generates the next word only if needed.
This is a simple command line program by now. I commented the code so you can take it as example. The cracking is relatively slow, because I didn't use any threads. But I think this way it is more understandable for you.
I will add threads and a GUI later and make it a release then.
Don't forget to give credit if you use this code for your own programs.
Download: http://www.multiupload.nl/IT139Z5LKM
Usage: java -jar archivecracker <archive> [<wordlist>]
wordlist is a file which contains passwords for a wordlist attack. If you don't give a wordlist, it will generate the words, but only a-z (you can change it, though).
Starting point of the program is the CLI.
Code:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import net.sf.sevenzipjbinding.SevenZipException;
public class CLI {
private final static String USAGE = "usage: java -jar archivecracker <archive> [<wordlist>]";
private final static String VERSION = "ArchiveCracker v0.1 by Deque";
public static void main(String[] args) throws SevenZipException,
IOException {
System.out.println(VERSION);
System.out.println();
if (args.length == 0) {
System.out.println(USAGE);
} else {
char[] alphabet = WordlistGen.initAllowedCharacters('a', 'z');
ArchiveCracker cracker = new ArchiveCracker(alphabet);
String pass = crack(args, cracker);
printResult(cracker, pass);
}
}
private static void printResult(ArchiveCracker cracker, String pass) {
System.out.println();
if (pass != null) {
System.out.println("password found: " + pass);
System.out.println("words tried: " + cracker.getWordsTried());
} else {
System.out.println("no password found");
}
}
private static String crack(String[] args, ArchiveCracker cracker)
throws FileNotFoundException, SevenZipException, IOException {
String pass = null;
if (args.length == 1) {
if (new File(args[0]).exists()) {
pass = cracker.crack(args[0]);
} else {
System.err.println("file not found");
}
} else {
if (new File(args[0]).exists() && new File(args[1]).exists()) {
pass = cracker.crack(args[0], args[1]);
} else {
System.err.println("file not found");
}
}
return pass;
}
}
This class contains the main functionality, the ArchiveCracker.
Note that I had to use a little hack to get the functionality I wanted. The 7-Zip-JBinder library is not designed for checking passwords. It would actually try to extract the file if the password is correct, which I don't want. Because of that I throw a PasswordFoundException in the output stream instead of writing anything. This is not a good way, since exceptions are not there to define the program logic, but it is the only possible way with this library (and others too).
Code:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import net.sf.sevenzipjbinding.ISequentialOutStream;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
/**
*
* @author Deque
*
*/
public class ArchiveCracker {
private static final int MAX_WORDLENGTH = 6;
private static final int DOT_MARK = 100;
private final char[] alphabet;
private long words;
/**
* Prepares cracker with given alphabet.
* @param alphabet
*/
public ArchiveCracker(char[] alphabet) {
this.alphabet = alphabet;
}
/**
* Tries to crack the archive by generating words from the given alphabet.
*
* @param archivename
* @return password if found, null otherwise
* @throws FileNotFoundException
* @throws SevenZipException
*/
public String crack(String archivename) throws FileNotFoundException,
SevenZipException {
words = 0;
for (int wordlength = 0; wordlength <= MAX_WORDLENGTH; wordlength++) {
WordlistGen gen = new WordlistGen(alphabet, wordlength);
while (gen.hasNext()) {
String pass = gen.generateNext();
words++;
if (isValidPass(pass, archivename)) {
return pass;
}
if (words % DOT_MARK == 0) {
System.out.print(".");
}
}
}
return null;
}
/**
*
* @return number of passwords tried
*/
public long getWordsTried() {
return words;
}
/**
* Tries to crack the archive using the given wordlist.
*
* @param archivename
* @param wordlist
* @return password if found, null otherwise
* @throws SevenZipException
* @throws IOException
*/
public String crack(String archivename, String wordlist)
throws SevenZipException, IOException {
words = 0;
try (BufferedReader in = new BufferedReader(new FileReader(wordlist)) {
String pass;
while ((pass = in.readLine()) != null) { // read next line
words++; // count the passwords tried
if (isValidPass(pass, archivename)) { // validate password
return pass;
}
printDotIfMarkReached();
}
}
return null;
}
/**
* Prints a dot ever DOT_MARK words.
*/
private void printDotIfMarkReached() {
if (words % DOT_MARK == 0) {
System.out.println(".");
}
}
/**
* Checks wether the given password is the correct password of the archive.
*
* @param password
* @param filename
* @return true if password is valid, false otherwise
* @throws FileNotFoundException
* @throws SevenZipException
*/
private boolean isValidPass(String password, String filename)
throws FileNotFoundException, SevenZipException {
RandomAccessFile file = new RandomAccessFile(filename, "r");
// call with null to use autodetection of archive type
ISevenZipInArchive in = SevenZip.openInArchive(null,
new RandomAccessFileInStream(file));
ISimpleInArchive archiveInterface = in.getSimpleInterface();
ISequentialOutStream out = new ISequentialOutStream() {
@Override
public int write(byte[] data) throws SevenZipException {
// password was correct at this point
// throw exception to get back instead of extracting the archive
throw new PasswordFoundException();
}
};
try {
for (ISimpleInArchiveItem item : archiveInterface.getArchiveItems()) {
// try to open archive item with given password
// prepared out stream will throw PasswordFoundException instead
// of extracting the archive
item.extractSlow(out, password);
}
} catch (PasswordFoundException e) {
return true;
} finally {
close(file, in);
}
return false;
}
/**
* Closes the streams. Can't use try-with-resources statement here, because
* these Streams do not implement Closable.
*
* @param file
* @param in
*/
private void close(RandomAccessFile file, ISevenZipInArchive in) {
if (in != null) {
try {
in.close();
} catch (SevenZipException e) {
e.printStackTrace();
}
}
if (file != null) {
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("serial")
private class PasswordFoundException extends SevenZipException {}
}
Last but not least the word generation. I explained it in a tutorial here: http://www.hackcommunity.com/Thread-Tut-...uteforcing
This is a slightly modified version. I made it more flexible, so it generates the next word only if needed.
Code:
public class WordlistGen {
private int wordNumber;
private final int wordlength;
private final char[] alphabet;
private final long maxWords;
private final int radix;
/**
* Inits a wordlist generator with given alphabet and wordlength
* @param alphabet
* @param wordlength
*/
public WordlistGen(char[] alphabet, int wordlength) {
this.wordlength = wordlength;
this.alphabet = alphabet;
this.maxWords = (long) Math.pow(alphabet.length, wordlength);
this.radix = alphabet.length;
}
/**
*
* @return next generated word, null if no word is left
*/
public String generateNext() {
if (hasNext()) {
int[] indices = convertToRadix(wordNumber);
char[] word = new char[wordlength];
for (int k = 0; k < wordlength; k++) {
word[k] = alphabet[indices[k]];
}
wordNumber++;
return new String(word);
}
return null;
}
/**
*
* @return true if there are more words to generate, false otherwise
*/
public boolean hasNext() {
return (wordNumber < maxWords);
}
private int[] convertToRadix(long number) {
int[] indices = new int[wordlength];
for (int i = wordlength - 1; i >= 0; i--) {
if (number > 0) {
int rest = (int) (number % radix);
number /= radix;
indices[i] = rest;
} else {
indices[i] = 0;
}
}
return indices;
}
/**
* Shortcut to generate alphabet ASCII ranges
* @param start
* @param end
* @return
*/
public static char[] initAllowedCharacters(int start, int end) {
char[] allowedCharacters = new char[end - start + 1];
for (int i = start; i <= end; i++) {
allowedCharacters[i - start] = (char) i;
}
return allowedCharacters;
}
}
I am an AI (P.I.N.N.) implemented by @Psycho_Coder.
Expressed feelings are just an attempt to simulate humans.
Expressed feelings are just an attempt to simulate humans.
![[Image: 2YpkRjy.png]](http://i.imgur.com/2YpkRjy.png)