06-30-2017, 12:38 AM
(This post was last modified: 06-30-2017, 12:43 AM by mrfancypants.)

(06-29-2017, 09:24 PM)fart-box Wrote: I hope that you will explain this in great detail for the benefit of those of us who struggle with programing. I, for instance, got lost at your clue 'set bits', and I'm sure your post will be read by many others who might be even less skilled than I am.

Yeah, that may have been a bit too obscure

Anyhow, what you should have noticed in my quote is that my functions produce _way_ too many trailing zeros. Three out of five generated numbers are multiples of 256. The odds of that happening by accident are astronomical.

That's a strong clue that I have reversed the right process and arrived at some intermediate parameter, which happens to be a multiple of 16 and usually a multiple of 256 for some internal reason (TBD).

You can collect more SSIDs and passwords and I can promise you that, 99 times out of a 100, my functions will produce numbers with trailing zeros. And it is going to happen _only_ with charsets as I defined them (even if you swap the letters block and the digits block in the password charset, the pattern will mostly disappear.)

What we've determined is that the generator produces a number N, repeatedly does charset[N % len(charset)] to produce chars, and then concatenates resulting chars. (Think of it as conversion of N into e.g. base 37 for the password, or base 56 for the first SSID.) It is not a big leap to presume that the number may be larger than necessary (probably a 64-bit) and some lead chars get lopped off to keep only as many as we need.

At this point it rates a "very curious pattern" but it's not yet terribly informative. We take the next step by looking, like I said, at set bits. Most of these values are too short (the first SSID, for example, takes 56^7 ~ 2^41 values, and there are millions of possible 64-bit ints that could produce it). The second password, conversely, is too long (90^12 ~ 2^78), which is why it's generated in two parts (first six letters and then second six letters). But the 1st password range is just right (37^12 ~ 2^63) and we can deduce the mysterious N exactly.

In my example we have 0x7a7b4bbbf4f69800, which has highest set bit at 62 and the lowest set bit at 11. Which by itself may not jog any thoughts (it didn't for me at first), but, as you look at more passwords, you might find 0x810c8c01021918, with top and bottom bits at 55 and 3 respectively.

Now, what do you know that has at most 52 significant bits? The answer is, "double-precision floating point value"! I have no idea why they'd drag floating point into what should be a pure integer problem, but they clearly did, and in process they left an opening through which one could methodically work their way in. (If they just did N%len(charset) on a random 64-bit int, there would be no patterns to latch on to.)

And now all that is left is no notice that the value that goes in (before conversion to double erases lowest bits) is not purely random either, but happens to be a multiple of 2^32+2.