View Javadoc
1   /*******************************************************************************
2    * Copyhacked (H) 2012-2025.
3    * This program and the accompanying materials
4    * are made available under no term at all, use it like
5    * you want, but share and discuss it
6    * every time possible with every body.
7    *
8    * Contributors:
9    *      ron190 at ymail dot com - initial implementation
10   *******************************************************************************/
11  package com.jsql.view.swing.manager.util;
12  
13  import com.jsql.util.I18nUtil;
14  import com.jsql.util.LogLevelUtil;
15  import com.jsql.util.bruter.Bruter;
16  import com.jsql.util.bruter.HashBruter;
17  import com.jsql.view.swing.manager.ManagerBruteForce;
18  import com.jsql.view.swing.util.I18nViewUtil;
19  import org.apache.commons.lang3.StringUtils;
20  import org.apache.logging.log4j.LogManager;
21  import org.apache.logging.log4j.Logger;
22  
23  import javax.swing.*;
24  import javax.swing.text.BadLocationException;
25  import java.awt.event.ActionEvent;
26  import java.awt.event.ActionListener;
27  import java.util.Locale;
28  
29  /**
30   * Run a brute force attack.
31   */
32  public class ActionBruteForce implements ActionListener, Runnable {
33      
34      private static final Logger LOGGER = LogManager.getRootLogger();
35  
36      private final ManagerBruteForce bruteForceManager;
37      
38      private boolean isStopped = false;
39      
40      public ActionBruteForce(ManagerBruteForce bruteForceManager) {
41          this.bruteForceManager = bruteForceManager;
42      }
43  
44      @Override
45      public void actionPerformed(ActionEvent actionEvent) {
46          if (this.bruteForceManager.getRun().getState() == StateButton.STOPPABLE) {
47              this.bruteForceManager.getRun().setEnabled(false);
48              this.isStopped = true;
49          } else {
50              if (StringUtils.isEmpty(this.bruteForceManager.getHash().getText())) {
51                  LOGGER.log(LogLevelUtil.CONSOLE_ERROR, () -> I18nUtil.valueByKey("BRUTEFORCE_EMPTY_HASH"));
52                  return;
53              } else if (this.isRangeNotSelected()) {
54                  LOGGER.log(LogLevelUtil.CONSOLE_ERROR, () -> I18nUtil.valueByKey("BRUTEFORCE_CHARACTER_RANGE"));
55                  return;
56              } else if (this.isLengthNotValid()) {
57                  LOGGER.log(LogLevelUtil.CONSOLE_ERROR, () -> I18nUtil.valueByKey("BRUTEFORCE_INCORRECT_MIN_MAX_LENGTH"));
58                  return;
59              }
60              new Thread(this, "ThreadDisplayBruteForce").start();
61          }
62      }
63  
64      private boolean isLengthNotValid() {
65          return Integer.parseInt(this.bruteForceManager.getMaximumLength().getValue().toString())
66              < Integer.parseInt(this.bruteForceManager.getMinimumLength().getValue().toString());
67      }
68  
69      private boolean isRangeNotSelected() {
70          return !this.bruteForceManager.getSpecialCharacters().isSelected()
71              && !this.bruteForceManager.getUpperCaseCharacters().isSelected()
72              && !this.bruteForceManager.getLowerCaseCharacters().isSelected()
73              && !this.bruteForceManager.getNumericCharacters().isSelected();
74      }
75  
76      @Override
77      public void run() {
78          // Reset the panel
79          this.bruteForceManager.getRun().setText(I18nViewUtil.valueByKey("BRUTEFORCE_STOP"));
80          this.bruteForceManager.getRun().setState(StateButton.STOPPABLE);
81          this.bruteForceManager.showLoader(true);
82          this.bruteForceManager.getResult().setText(null);
83  
84          final var hashBruter = new HashBruter();
85          this.initBruter(hashBruter);
86  
87          // Begin the reverse hashing process
88          new Thread(hashBruter::tryBruteForce, "ThreadRunBruteForce").start();
89          while (!hashBruter.isDone() && !hashBruter.isFound() && !this.isStopped) {
90              
91              hashBruter.setEndtime(System.nanoTime());
92  
93              try {
94                  Thread.sleep(1000);  // delay to update result panel
95              } catch (InterruptedException e) {
96                  LOGGER.log(LogLevelUtil.IGNORE, e, e);
97                  Thread.currentThread().interrupt();
98              }
99              
100             int selectionStart = this.bruteForceManager.getResult().getSelectionStart();
101             int selectionEnd = this.bruteForceManager.getResult().getSelectionEnd();
102             
103             this.updateResult(hashBruter);
104 
105             this.bruteForceManager.getResult().setSelectionStart(selectionStart);
106             this.bruteForceManager.getResult().setSelectionEnd(selectionEnd);
107             
108             if (this.isStopped) {
109                 hashBruter.setIsDone(true);
110                 hashBruter.setFound(true);
111                 break;
112             }
113         }
114 
115         this.displayResult(hashBruter);
116 
117         this.isStopped = false;
118         this.bruteForceManager.showLoader(false);
119         this.bruteForceManager.getRun().setText(I18nViewUtil.valueByKey("BRUTEFORCE_RUN_BUTTON_LABEL"));
120         this.bruteForceManager.getRun().setEnabled(true);
121         this.bruteForceManager.getRun().setState(StateButton.STARTABLE);
122     }
123 
124     private void updateResult(final HashBruter hashBruter) {
125         this.bruteForceManager.getResult().setText(I18nUtil.valueByKey("BRUTEFORCE_CURRENT_STRING") + ": " + hashBruter.getPassword());
126         this.append(I18nUtil.valueByKey("BRUTEFORCE_CURRENT_HASH") + ": " + hashBruter.getGeneratedHash() + "\n");
127         this.append(I18nUtil.valueByKey("BRUTEFORCE_POSSIBILITIES") + ": " + hashBruter.getNumberOfPossibilities());
128         this.append(I18nUtil.valueByKey("BRUTEFORCE_CHECKED_HASHES") + ": " + hashBruter.getCounter());
129         this.append(I18nUtil.valueByKey("BRUTEFORCE_ESTIMATED") + ": " + hashBruter.getRemainder());
130         this.append(I18nUtil.valueByKey("BRUTEFORCE_PERSECOND") + ": " + hashBruter.getPerSecond() + "\n");
131         this.append(hashBruter.calculateTimeElapsed());
132 
133         if (hashBruter.getPerSecond() != 0) {
134             float remainingDuration = Float.parseFloat(Long.toString(hashBruter.getRemainder())) / hashBruter.getPerSecond();
135             this.append(String.format(
136                 Bruter.PATTERN_PERIOD,
137                 I18nUtil.valueByKey("BRUTEFORCE_TRAVERSING_REMAINING"),
138                 Math.round(Math.floor(remainingDuration / 60f / 60.0f / 24f)), I18nUtil.valueByKey("BRUTEFORCE_DAYS"),
139                 Math.round(Math.floor(remainingDuration / 60f / 60f % 24)), I18nUtil.valueByKey("BRUTEFORCE_HOURS"),
140                 Math.round(Math.floor(remainingDuration / 60f % 60)), I18nUtil.valueByKey("BRUTEFORCE_MINUTES"),
141                 Math.round(remainingDuration % 60), I18nUtil.valueByKey("BRUTEFORCE_SECONDS")
142             ));
143         }
144 
145         this.append(String.format(
146             "%s: %s%%",
147             I18nUtil.valueByKey("BRUTEFORCE_PERCENT_DONE"),
148             100 * (float) hashBruter.getCounter() / hashBruter.getNumberOfPossibilities()
149         ));
150     }
151 
152     private void initBruter(final HashBruter hashBruter) {
153         hashBruter.setMinLength(Integer.parseInt(this.bruteForceManager.getMinimumLength().getValue().toString()));
154         hashBruter.setMaxLength(Integer.parseInt(this.bruteForceManager.getMaximumLength().getValue().toString()));
155 
156         if (this.bruteForceManager.getSpecialCharacters().isSelected()) {
157             hashBruter.addSpecialCharacters();
158         }
159         if (this.bruteForceManager.getUpperCaseCharacters().isSelected()) {
160             hashBruter.addUpperCaseLetters();
161         }
162         if (this.bruteForceManager.getLowerCaseCharacters().isSelected()) {
163             hashBruter.addLowerCaseLetters();
164         }
165         if (this.bruteForceManager.getNumericCharacters().isSelected()) {
166             hashBruter.addDigits();
167         }
168         if (StringUtils.isNotEmpty(this.bruteForceManager.getExclude().getText())) {
169             hashBruter.excludeChars(this.bruteForceManager.getExclude().getText());
170         }
171 
172         hashBruter.setType((String) this.bruteForceManager.getHashTypes().getSelectedItem());
173         hashBruter.setHash(
174             this.bruteForceManager.getHash().getText()
175             .toUpperCase(Locale.ROOT)
176             .replaceAll("[^a-zA-Z0-9]", StringUtils.EMPTY)
177             .trim()
178         );
179     }
180 
181     private void displayResult(final HashBruter hashBruter) {
182         // Display the result
183         if (this.isStopped) {
184             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, () -> I18nUtil.valueByKey("BRUTEFORCE_ABORTED"));
185         } else if (hashBruter.isFound()) {
186             this.append(String.format(
187                 "%n%s:%n%s => %s",
188                 I18nUtil.valueByKey("BRUTEFORCE_FOUND_HASH"),
189                 hashBruter.getGeneratedHash(),
190                 hashBruter.getPassword()
191             ));
192             LOGGER.log(
193                 LogLevelUtil.CONSOLE_SUCCESS,
194                 "{}: {} => {}",
195                 () -> I18nUtil.valueByKey("BRUTEFORCE_FOUND_HASH"),
196                 hashBruter::getGeneratedHash,
197                 hashBruter::getPassword
198             );
199         } else if (hashBruter.isDone()) {
200             this.append("\n"+ I18nUtil.valueByKey("BRUTEFORCE_HASH_NOT_FOUND"));
201             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, () -> I18nUtil.valueByKey("BRUTEFORCE_HASH_NOT_FOUND"));
202         }
203     }
204 
205     private void append(String text) {
206         try {
207             JTextPane textPane = this.bruteForceManager.getResult();
208             textPane.getDocument().insertString(
209                 textPane.getDocument().getLength(),
210                 (textPane.getDocument().getLength() == 0 ? StringUtils.EMPTY : "\n") + text,
211                 null
212             );
213         } catch (BadLocationException e) {
214             LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
215         }
216     }
217 }