com.codejumble.osbfa.attacker.CombinationFinder.java Source code

Java tutorial

Introduction

Here is the source code for com.codejumble.osbfa.attacker.CombinationFinder.java

Source

/**
 * *****************************************************************************
 * Copyright (c) 2015 CodeJumble.com. All rights reserved.
 *
 * This file is part of OSBFA - www.codejumble.com
 *
 * Foobar is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * OSBFA. If not, see <http://www.gnu.org/licenses/>.
 * *****************************************************************************
 */
package com.codejumble.osbfa.attacker;

import com.codejumble.osbfa.Main;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;
import net.lingala.zip4j.core.ZipFile;
import org.apache.commons.io.FileUtils;

/**
 * Class in charge of calculating the possible combinations
 *
 * @author alopcas
 */
public class CombinationFinder extends SwingWorker {

    static Main mainFrame;

    private final long totalNumberOfCombinations;
    private List<String> combinations;
    private final List<String> options;
    private char[] endCharSet;
    private final int maxPasswordSize;
    private final int minPasswordSize;
    private File tmpFolder;

    // Default charsets defined
    public static final String numbersCharSet = "0123456789";
    public static final String highCapsCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public static final String lowCapsCharSet = "abcdefghijklmnopqrstuvwxyz";
    public static final String specialCharSet = "!.:,;\\/?-_$";
    public static final String extraSpecialCharSet = "%&()=+*~'#<>|";
    public static String customCharSet = "";

    // Regarding execution
    private long alreadyTriedCombinations;
    private boolean done;

    List<CombinationExploiter> miners;

    /**
     * Initializes the combination finder with the charsets to be used.
     *
     * @param mainFrame Main frame of the application
     * @param options Preferences of the user
     * @param maxPasswordLength maximum key size
     * @param amountOfThreads number of threads
     * @param zipFile Zipfile to be attacked
     */
    public CombinationFinder(Main mainFrame, List<String> options, int minPasswordLength, int maxPasswordLength,
            int amountOfThreads, ZipFile zipFile) {
        tmpFolder = new File("tmp");
        try {
            FileUtils.cleanDirectory(tmpFolder);
        } catch (IOException ex) {
            mainFrame.createErrorDialog(mainFrame, "Error", ex.getMessage());
        }
        CombinationFinder.mainFrame = mainFrame;
        alreadyTriedCombinations = 0;
        done = false;
        this.options = options;
        createEndCharSet();
        maxPasswordSize = maxPasswordLength;
        minPasswordSize = minPasswordLength;
        totalNumberOfCombinations = (long) Math.pow(endCharSet.length, maxPasswordSize);
        mainFrame.appendToMainLog("Number of possible combinations: " + getTotalNumberOfCombinations());
        combinations = new ArrayList<String>();
        miners = new ArrayList<CombinationExploiter>();
        for (int i = 0; i < amountOfThreads; i++) {
            mainFrame.appendToMainLog("Adding exploiter thread number " + (i + 1));
            File destFile = new File(tmpFolder.getAbsolutePath().concat(File.separator + i));
            miners.add(new CombinationExploiter(this, zipFile, destFile));
        }
    }

    private void createEndCharSet() {
        String tmp = "";
        for (String charSet : options) {
            tmp = tmp.concat(charSet);
        }
        endCharSet = removeDuplicates(tmp);
        mainFrame.appendToMainLog("CombinationFinder was initialized with charset = " + getEndCharSet());
    }

    /**
     * Returns the charset generated after the initialization
     *
     * @return the charset
     */
    public String getEndCharSet() {
        return Arrays.toString(endCharSet);
    }

    /**
     * Removes the duplications from the end charset.
     *
     * @param endCharSet set to be cleared
     */
    public char[] removeDuplicates(String endCharSet) {
        List<Character> alreadyIncludedCharacters = new ArrayList<Character>();
        char[] providedCharSet = endCharSet.toCharArray();
        String tmpNewChars = "";
        for (char tmp : providedCharSet) {
            // If the character is already in the end char set, do not add it
            if (!alreadyIncludedCharacters.contains(tmp)) {
                alreadyIncludedCharacters.add(tmp);
                tmpNewChars += tmp;
            }
        }
        return tmpNewChars.toCharArray();
    }

    /**
     * Returns the total number of possible combinations given the charset
     *
     * @return number of combinations
     */
    public final long getTotalNumberOfCombinations() {
        return totalNumberOfCombinations;
    }

    /**
     * Starts the generation of all the possible combinations
     *
     * @return null
     * @throws Exception Runtime exception
     */
    @Override
    protected Object doInBackground() throws Exception {
        for (int length = 1; length <= maxPasswordSize; length++) {
            mainFrame.appendToMainLog("Trying with key length=" + length);
            generate("", 0, length);
        }
        return null;
    }

    /**
     * Waits until all the possible combinations have been tried or the right
     * password has been found out.
     */
    @Override
    protected void done() {
        while (stillOnGoing()) {
            try {
                Thread.sleep(900);
            } catch (InterruptedException ex) {
                Logger.getLogger(CombinationFinder.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        // OVER
    }

    /**
     * Generates recursesively the possible combinations
     *
     * @param str key
     * @param pos current position
     * @param length current length
     * @throws java.lang.InterruptedException Interruption
     */
    public void generate(String str, int pos, int length) throws InterruptedException {
        if (length == 0) {
            combinations.add(str);
            if (combinations.size() > 8000000) {
                Thread.sleep(8000);
                mainFrame.appendToMainLog("Removed from pool: " + alreadyTriedCombinations + " ("
                        + (int) ((float) alreadyTriedCombinations / totalNumberOfCombinations * 100) + "%) Next: "
                        + combinations.get(0));
            }
        } else {
            for (int i = pos; i < endCharSet.length; i++) {
                generate(str + endCharSet[i], i, length - 1);
            }
        }
    }

    /**
     * Returns whether the process is still on going
     *
     * @return is continuing
     */
    public boolean stillOnGoing() {
        return !combinations.isEmpty() && !done;
    }

    /**
     * Returns a combination to be tried out
     *
     * @return combination
     */
    public String getCombination() {
        alreadyTriedCombinations++;
        return combinations.remove(0);
    }

    /**
     * Starts all the combination exploiters
     *
     * @throws java.lang.InterruptedException Interrumption
     */
    public void fireExploitersUp() throws InterruptedException {
        for (CombinationExploiter combinationExploiter : miners) {
            Thread.sleep(200);
            combinationExploiter.execute();
        }
    }

    /**
     * Cancels all the exploiters, normally called when the right password has
     * been found out
     *
     * @param cancel cancel or not
     */
    public void cancelMinning(Boolean cancel) {
        done = true;
    }
}