[Java Source] ArchiveCracker - Deque - 01-02-2013
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.
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-Create-a-wordlist-generator-i-e-for-bruteforcing
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;
}
}
[Java Source] ArchiveCracker - Deque - 01-02-2013
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.
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-Create-a-wordlist-generator-i-e-for-bruteforcing
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;
}
}
RE: [Java Source] ArchiveCracker - The Alchemist - 01-03-2013
Haha... I'm glad that you've finally made this. Nice share!!
The story goes like this : Once I'd seen a code made by Deque that extracts password protected archives. I just asked him if he could make a cracker along with this.
And now, I'm seeing it in front of my eyes!!
RE: [Java Source] ArchiveCracker - isuru - 01-03-2013
First thank you for the code. It seems like you are a pro. :wub:
But I have one question, what library did you use. I did a google search and found out this library from sourceforge. http://sevenzipjbind.sourceforge.net/first_steps.html
Is it the library?
RE: [Java Source] ArchiveCracker - Deque - 01-03-2013
(01-03-2013, 06:06 PM)isuru Wrote: First thank you for the code. It seems like you are a pro. :wub:
But I have one question, what library did you use. I did a google search and found out this library from sourceforge. http://sevenzipjbind.sourceforge.net/first_steps.html
Is it the library?
Yes it is. I mentioned in my first post, that I use 7-Zip JBinder.
RE: [Java Source] ArchiveCracker - piyushaegis - 01-12-2013
Hi...
thanks for your code, really very useful for me.
RE: [Java Source] ArchiveCracker - piyushaegis - 01-12-2013
Hi...
thanks for your code, really very useful for me.
|