This is easy if the length of the password is known, but of course this will not be the case most of the time.
In order to break the password, we need to ascertain the length of the password portion. I will again consider my admin password 'ADAD', which has been coded (in full) to 0x6DAF (28079).
I don't know the length of this password though, I just have the full code 28079.
If I subtract all possible filler codes from this password, I get the following list of values:
Pot Len | Filler | Remain |
0 | 28304 | -255 |
1 | 28012 | 67 |
2 | 27657 | 422 |
3 | 27074 | 1005 |
4 | 25959 | 2120 |
5 | 24997 | 3082 |
6 | 23493 | 4586 |
7 | 21539 | 6540 |
8 | 19826 | 8253 |
9 | 17521 | 10558 |
10 | 15561 | 12518 |
11 | 12783 | 15296 |
12 | 9773 | 18306 |
13 | 6388 | 21691 |
14 | 3180 | 24899 |
15 | 0 | 28079 |
Assuming that I don't know that 2120 is the correct code, I need a way of working out which remaining codes are valid. Obviously, 0 isn't valid (-255), so we know this is not a blank password.
The answer, as it turns out, is quite straight forward. Basically, if you consider all the characters between 0-9 and A-Z (remember all passwords are converted to upper case), and how they are coded (XOR 0x96), then the lowest possible password code is 160 (0xA0), for '6', and the highest is 223 (0xDF) for 'I'.
Now if, at each potential length, we work out the values of the equivalent lengths of '6's and 'I's, as so:
Pot Len | Min (6) | Max (I) |
0 | 0 | 0 |
1 | 160 | 223 |
2 | 480 | 669 |
3 | 960 | 1338 |
4 | 1600 | 2230 |
5 | 2400 | 3345 |
6 | 3360 | 4683 |
7 | 4480 | 6244 |
8 | 5760 | 8028 |
9 | 7200 | 10035 |
10 | 8800 | 12265 |
11 | 10560 | 14718 |
12 | 12480 | 17394 |
13 | 14560 | 20293 |
14 | 16800 | 23415 |
15 | 19200 | 26760 |
It becomes clear that for the remaining code to be valid for a length 4 password, it has to fall between the range 1600 ('6666') and 2230 ('IIII').
If you consider our remaining codes from our coded password (28079), I have listed the codes that appear to fall within the valid ranges:
Pot Len | Filler | Remain | Valid? |
0 | 28304 | -255 | No |
1 | 28012 | 67 | No |
2 | 27657 | 422 | No |
3 | 27074 | 1005 | Yes |
4 | 25959 | 2120 | Yes |
5 | 24997 | 3082 | Yes |
6 | 23493 | 4586 | Yes |
7 | 21539 | 6540 | No |
8 | 19826 | 8253 | No |
9 | 17521 | 10558 | No |
10 | 15561 | 12518 | No |
11 | 12783 | 15296 | No |
12 | 9773 | 18306 | No |
13 | 6388 | 21691 | No |
14 | 3180 | 24899 | No |
15 | 0 | 28079 | No |
Based on the above list, we could actually have a valid password consisting of 3, 4, 5 and 6 characters for the code 28079.
From my example in my part one of this post, we know that a 4 character password could be 'KNSB'. There are many other 4 character passwords that would generate a code of 28079.
Based upon the above list though, I want to see if I can also generate 3, 5 and 6 character passwords.
Working with a 3 character password which has a target code of 1005, if I use the lowest possible password, '666', I get a value of 960, thus:
Pos | Char Code | Code Value | Total |
1 | 54 (0x36) '6' | 160 * 1 | 160 |
2 | 54 (0x36) '6' | 160 * 2 = 320 | 480 (160 + 320) |
3 | 54 (0x36) '6' | 160 * 3 = 480 | 960 (480 + 480) |
This is exactly 45 less than our intended target code, 1005.
If I add a value of 1 to the character at position 1, this will increase the code by 1.
Adding a value of 1 to character position 2 will increase the code by 2, and so on.
So to make an additional 45, without causing any of the codes to pass above the maximum ('I', 223), the simplest solution is to add 15 to the coded value of position 3, so change the code value 160 to 175 (which is the coded value of '9'):
Pos | Char Code | Code Value | Total |
1 | 54 (0x36) '6' | 160 * 1 | 160 |
2 | 54 (0x36) '6' | 160 * 2 = 320 | 480 (160 + 320) |
3 | 57 (0x39) '9' | 175 * 3 = 525 | 1005 (480 + 525) |
So this means a potential 3 character password could be '669'.
Taking this idea and applying it to the 5 and 6 character codes, we get the potential passwords '76PII' and '6XIIII' respectively.
I tried all of these in SourceSafe and was immensely pleased to discover that they all worked.
This article has demonstrated that it is possible to break SourceSafe passwords, and using the above method I could gain access to a SourceSafe repository using any user account... providing I know the password code.
Of course, as I am unlikely to have the code (without using a debugger), I am going to try and find a way to get the codes directly from SourceSafe in my next article...
No comments:
Post a Comment