08-17-2017, 01:14 AM
(08-15-2017, 02:26 AM)mrfancypants Wrote: [ -> ]I am not sure I even understand your difficulty.
Let's take NVG589 specifically. We have an algorithm that takes in a 64-bit integer 'x' and spits out a 12-letter password:
for n in range(0,6):
pw=pw_charset[x%37] + pw
x/=37
pw=chr(50+(x%8)) + pw
x/=37
For whatever reason, AT&T people don't just pull an 'x' out of a RNG or something, instead they pull a 31-bit int and multiply it by a magic number that is approximately 465661287.5245797. (Or possibly do some slightly longer sequence of multiplications and additions which amounts to the same thing, because simply multiplying by that number does not always yield the exact result. But ignore that for now.)
Now, where did they get 465661287.5245797? Beats me. All I know is: (1) if they are starting with a 31-bit number, they had to multiply by _something_ (to span the whole range of passwords), since feeding a 31-bit value direct into code above would always result in passwords that start with 2a2a2a..; (2) that exact value reproduces many of the passwords I see in the wild and that can't be a coincidence. (To calculate it, I basically had the computer run through all possible values until it found one that gave lots of hits.)
for NVG599, they tweak the number->password conversion algorithm and replace the 465... value with 2^32+2. Again why 2^32+2? Not a clue.
Any guesses as to the float number that the 5268AC might be using?
Or is the 5268AC using a variation of the 599 scheme?
I haven't looked at this in at least a couple weeks, but I got as far as modifying some of the python for the 599 and experimenting with different values for where the pwgen function starts (normally at 2^32+2).
Something like this. I am incrementing "m" in this example. The first 6 digits were input from an Ebay listing for testing.
Code:
pw_charset='abcdefghijkmnpqrstuvwxyz23456789#%+=?'
for m in range (0, 2147483648):
def pwgen(x):
x*=2**32+(m)
x=int(float(x))
pw=''
for n in range(0,12):
rem=x%37
pw=pw_charset[rem]+pw
x/=37
return pw
def pw_to_candidate_ints(x):
val=0
l=len(x)
for n in range(0,l):
val+=pw_charset.find(x[n])*(37**(11-n))
cands=range(val/0x100000002, (val+37**(12-l))/0x100000002+1)
val+=37**12
cands+=range(val/0x100000002, (val+37**(12-l))/0x100000002+1)
return [y for y in cands if pwgen(y)[:l]==x]
candidates=pw_to_candidate_ints('9d4c8c')
for x in candidates:
print m, pwgen(x)
I was aiming to get it to produce output valid for 5268AC devices. It was worth a shot, but didn't work.
I am going to have to go back in this thread and see if there was python for the 589 that can be tested. Perhaps all that is needed for the 5268AC is a different "magic number", a correct floating point value that produces the correct result.
Has anyone had time to experiment?