Wednesday, January 20, 2010

Writing a Sequential Bruteforce Attack in C/C++

The bruteforce attack is simple enough to understand. It is performed by entering in every possible password that can be accepted by a system until the correct password is entered. However, actually writing one is a bit more complex. There's a complex underlying logic involved simply entering in every password. This post will cover the logic of programming a sequential bruteforcer and cap off with writing a sequential ascending bruteforcer in C/C++. Lastly, I will show a quick trick to turn the sequential ascending bruteforcer into a sequential descending bruteforcer.

A bruteforcer has three main logical components: A selection where the user inputs specific location of the attack; Generating the passwords to test; Testing the password.

Having the user input the specific location to attack is arguably the easiest part of writing a bruteforcer. This part can actually be "hard-coded" (specified by the programmer so no input is required) so I was thinking of not even mentioning it. But, I decided to bring it up as any bruteforcer meant to be used by more then one person will include this. Let's say we've written a bruteforcer that attacks Yahoo accounts. In this case, the bruteforcer will be programmed to attack Yahoo accounts, but the user must input the Yahoo account to specifically attack. This first component of the bruteforcer will handle thus handles obtianing this information.

Once the bruteforcer knows what it is going to attack, it must generate the password to try. In a sequential bruteforcer, the password tried each time will be sequentially one step away from the last password tried. So, in a sequential ascending bruteforcer, the bruteforcer will try the password 000001 followed by 000002. This works in reverse in a sequential descending bruteforcer. The programming of this is generally handled by writing a continuous loop which breaks only when the password generated is successful. Meanwhile, a handful of variables constantly increment with each run through the loop. When all of the possible passwords are tried, the variables are all reset as low as possible, the number of characters in the password is incremented or decremented, and the process begins again with checking all of the passwords one character longer or shorter then the last number of characters in a password. In practice, this is simpler then it sounds.

The last main component of a bruteforcer is the part in which a bruteforcer checks to see if it's generated the correct password. In some cases, this can surprisingly be the hardest part of the bruteforcer to write. Using our Yahoo example again, writing this part of the bruteforcer requires a knowledge of the Yahoo API. It's really hard for me to write how to perform the password check as each check will be written differently. While all checks are simple from a broad perspective, this is liable to get quite complex depending on what you're trying to bruteforce. My recommendation is to look for a library to do the check for you so you can do the least amount of work possible to perform what is really be a trivial step overall.

Here is the code I wrote to an ascending bruteforcer in C/C++. It's really rather small code and thus pretty self-explanatory. (The comments should help explain things too):

/*Change "(" to "<" and change ")" to ">" */
#include (iostream)
#include (string)
  
      using namespace std;
  
      /*Prototypes*/
      void checkPassword(string password);
      void recurse(int width, int position, string baseString);
     
      /*Global Variables*/
      char chars[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
      string t;
 
      /*This function generates the password*/
      void recurse(int width, int position, string baseString) {
 
      for(int i=0;i<35;i++) {
 
      if (position < width-1) {
 
      recurse(width, position + 1, baseString+chars[i]);
 
      }
 
      checkPassword(baseString+chars[i]);
 
      }
 
      }
 
      /*This function checks to see if the generated password is correct*/
      void checkPassword(string password) {
          
      cout << "Trying this password: " << password << endl;

      if (password==t) {
 
      cout << "match [" << password << "]" << endl;
     
      int pause;
      cin >> pause;
 
      exit(1);
 
      }
 
      }
     
      int main() {
  
      cout << "Enter a string (No more then 10 characters for demonstration purposes): " << endl;
 
      cin >> t;
 
      int maxChars = 10;
 
      for(int i=1;i

      cout << "Checking passwords width [" << i << "]..." << endl;
 
      recurse(i,0,"");
 
      }
 
      return 0;
 
      }


To turn this into a sequential descending brutefrocer, make two small changes. Change the chars[] to equal: {'z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a','9','8','7','6','5','4','3','2','1','0'};
And lastly change the for loop in main() to:
for(int i = maxChars; i >0; i++) {

For those of you who still might not fully understand how all of the C/C++ works, I strongly encourage you to compile the bruteforcer program to further your study. I hope all of you reading this have found the subject of bruteforcers to be as fascinating as I find them to be.

6 comments:

  1. Blogger is being gay.

    The for loop near the bottom of the code should be for(int i=1;i<maxChars;i++){

    ReplyDelete
  2. How do i tell the program what to attack?

    ReplyDelete
  3. @Anonymous idk what you actually mean...
    @Arikado well done...your tutorials are very helpful ;) :P

    ReplyDelete
  4. how much time it takes to recover a password which is about 12 digit long contain special characters like @ # & etc with lower case and upper case alphabets

    ReplyDelete
    Replies
    1. I just tried out Arikado's code using
      http://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter
      as the timer.
      The word "lol" took about 1 minute.
      The word "soup" took about 50 minutes.

      The time it takes increases exponentially with the length of the password.

      Delete
    2. If you comment out the line displaying the attempts it's only about 7 seconds for the word "soup" ><

      Delete