Password list generation

I crafted an answer using Javascript, because it's what I am used to and no language is specified. I am confident that you can find/create an analog in whatever other language you please.

First off, I stole a function from This answer to create a cartesian product. The explanation of cartesian products is not really in the scope of this question, but suffice to say it combines arrays of possible characters into arrays of possible strings (very oversimplified).

OK, so ckozl's function is :

function cartProd(paramArray) {

  function addTo(curr, args) {

    var i, copy, 
        rest = args.slice(1),
        last = !rest.length,
        result = [];

    for (i = 0; i < args[0].length; i++) {

      copy = curr.slice();
      copy.push(args[0][i]);

      if (last) {
        result.push(copy);

      } else {
        result = result.concat(addTo(copy, rest));
      }
    }

    return result;
  }


  return addTo([], Array.prototype.slice.call(paramArray));
}

and mine is :

function findSubs(string) {
        //create a linked list of sub characters
        //expect lower case input
        subs={
                "p":["p","P"],
                "a":["a","A","4","@"],
                "s":["s","S","$","5"]
        }
        //create an (initially empty) array to store possible characters in each position
        result=[]
        for (var i=0;i<string.length;i++) {
                result[i]=subs[string.charAt(i)]; //Would be more robust if you added logic here to handle it not being a key in the subs object. 
        }
        /*
        so result might look like:
        [
                ["p","P"],
                ["a","A","4","@"],
                ["s","S","$","5"],
                ["s","S","$","5"]
        ]
        for an input of "pass"
        */
        return cartProd(result)
}

Honestly, ckzol's function does all the heavy lifting here. You would need to flesh out the subs array before use, and this does not handle adding characters at the end of the string (because it seems kind of arbitrary).

Also note I have ever so slightly modified the cartProd function, such that we can hand it an array of arrays as input params rather than multiple arrays overloading the arguments.

Edit: also note that the returned value is an array of arrays, so you would want to iterate through it and for each element e do e.join("").

Edit again: also note that you could easily extend this to apply other mutations to the password. For instance, if you wanted to add a number between 0 and 99 to the end of the string you could push an extra array onto the end of result, containing ["0","1","2",...,"99"]. You could include an empty element ("") in this array to also output possibilities not including the number suffix. The same logic could be used to add a prefix. Essentially you are building an array of arrays of possible characters in the result array, so you can include any mutations you can think of.


The first tool in my toolbox for generating permuted wordlists is RSMangler. So far, I wasn't able to find a better tool.

It's written in Ruby, it's open source, super easy to modify and extend, has a ton of options, and it's licenced under CC BY-SA UK.

You may easily extend the leet_swap array. For example

leet_swap = {
  'a' => '@',
  'C' => '(',
}

It automatically add numbers before and after each string, it even gives the option to append some common words to your wordlist in the array common_words.

All the options are enabled by default, so when you set the option --common you're disabling the common words feature. Same goes for the other options.

I'd highly advise disabling the --perms option, as it creates an extremely exhaustive permutation list. When I say "extremely exhaustive" I'm not overstating it. My non-mutated wordlist was expanded to nearly 900GB wordlist.