1 /* This program takes an 'encrypted' Windows 95 share password and decrypts it.
3 * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Network\LanMan
4 * to find a machine's shares. Within the data for each share are two
5 * registry entries, Parm1enc and Parm2enc. Parm1enc is the "Full access"
6 * password. Parm2enc is the "Read only" password.
11 * Do not distribute this program for any commercial purpose without first
12 * contacting me for permission.
14 * DO NOT USE THIS PROGRAM FOR ILLEGAL OR UNETHICAL PURPOSES!
16 * A technical description of the 'code' can be found later on in this
19 * Oh yeah... a totally unsolicited self promotion here... If anyone has
20 * a job for a junior year Computer Science student for summer '96, please
21 * let me know! I'm familiar with Windows and Mac networking (especially
22 * involving TCP/IP), fluent in C and C++, and working on becoming a
23 * proficient Windows programmer.
32 int DecodeCharOne(unsigned char *);
33 int DecodeCharTwo(unsigned char *);
34 int DecodeCharThree(unsigned char *);
35 int DecodeCharFour(unsigned char *);
36 int DecodeCharFive(unsigned char *);
37 int DecodeCharSix(unsigned char *);
38 int DecodeCharSeven(unsigned char *);
39 int DecodeCharEight(unsigned char *);
43 int i; /* Generic counter */
44 int eocc = 0; /* Records if there has been an error */
46 /* The following structure stores the encoded bytes. Decoded values
47 * replace the encoded values as the decoding process moves along
48 * The initial values show here are not used and are unimportant
50 unsigned char mybytes[] = { 0x15, 0xba, 0x6d, 0x86, 0x73, 0x89, 0xf4, 0x4a };
51 unsigned short tempshort; /* Used as a go-between from sscanf() to
52 mybytes[] so unaligned data accesses
55 int goupto = 0; /* Records how many characters there are to be decoded */
57 /* The following code handles input */
61 printf("Input the byte code in hex (ex: 76 d5 09 e3): ");
62 fgets(inpt, BUFFER, stdin);
64 inptptr = strtok(inpt, " ");
66 while ((inptptr != NULL) && (goupto < 8)) {
67 sscanf(inptptr, "%hx", &tempshort);
68 mybytes[goupto++] = tempshort;
69 inptptr = strtok(NULL, " ");
72 /* Decode all the characters. I could have made this stop immediately
73 * after an error has been found, but it really doesn't matter
75 if (!DecodeCharOne(&mybytes[0])) eocc = 1;
76 if (!DecodeCharTwo(&mybytes[1])) eocc = 1;
77 if (!DecodeCharThree(&mybytes[2])) eocc = 1;
78 if (!DecodeCharFour(&mybytes[3])) eocc = 1;
79 if (!DecodeCharFive(&mybytes[4])) eocc = 1;
80 if (!DecodeCharSix(&mybytes[5])) eocc = 1;
81 if (!DecodeCharSeven(&mybytes[6])) eocc = 1;
82 if (!DecodeCharEight(&mybytes[7])) eocc = 1;
84 /* If the password could be decoded, print it */
85 if (eocc) printf("The encrypted password is invalid.\n");
87 printf("The decoded password is: \"");
88 for (i = 0; i < goupto; i++) printf("%c",mybytes[i]);
94 * I will document this function, but not the seven other functions
95 * which decode the subsequent seven characters. All of these functions
96 * are essentially the same. Multiple functions are necessary though
97 * because each column of the password has a different set of encoding
100 * The following section will attempt to explain the encoding scheme
101 * for share passwords as stored in the Windows 95 registry. I will
102 * try to explain this as clearly as I can, however I really have no
103 * background in encryption. If you have any questions, please feel
104 * free to send them to me at snakey@cs.umd.edu.
106 * First off, share passwords can be anywhere from one character to
107 * eight. "Read only" passwords and "Full access" passwords both use
108 * the same encoding scheme, and so they both can be decoded by this
109 * program. There is a one-to-one relationship between the number of
110 * characters in a password and the number of bytes in the encoded
111 * password stored in the registry. In fact, each encoded byte directly
112 * corresponds to the letter in the corresponding column of the
113 * unencoded password! Ie: If I change a password "passwd" to "masswd",
114 * only the first byte of the encrypted password will change. Knowing
115 * this, it is easy to see that all that needs to be done to decode
116 * the password is to find a mapping from an encoded byte to a decoded
117 * letter. That's what this program does. Unfortunately, things get
118 * a little tricky because a letter in the first column of a password
119 * is encoded using a slightly different algorithm than a letter
120 * in the second column, and so on.
122 * There is another complexity which we do not really need to worry
123 * about to a great extent, but we still need to be aware of. Many
124 * characters, when entered into a password, map to the same encoded
125 * byte. The best example of this is that both 'A' and 'a' are the
126 * same as far as share passwords are concerned. There are numerous
127 * other examples of this, and this allows us to effectively limit the
128 * range of characters we need to be able to decode. The range of
129 * ASCII values we will have to be able to decode turns out to be
130 * from 32 to 159. ASCII values higher than 159 tend to map to
131 * encoded bytes which also represent more normal ASCII values. So
132 * if a user manages to create a password with high ASCII values
133 * in it, that password will still be decoded by this program.
134 * Although the decoded password won't look the same as the original,
135 * it will work just as well.
137 * With all of the preliminaries out of the way, I can now move on
138 * to describing the mapping from an encoded byte to it's corresponding
139 * ASCII value. I think the best way to describe this would be through
140 * a picture of exactly how the characters from 32 to 63 are mapped
141 * out in the code for the first letter in a password. This table goes
142 * beyond the 80 column format maintained in the rest of this document,
143 * but it is really the best solution. If the table below doesn't look
144 * right, load this file up in a text editor that supports greater than
147 * Encoded byte (hex) - 1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 14 11 10 0F OE 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
148 * ASCII value (decimal) - 42 43 40 41 46 47 44 45 34 35 32 33 38 39 36 37 58 59 56 57 62 63 60 61 50 51 48 49 54 55 52 53
149 * Pair # - |_6_| |_5_| |_8_| |_7_| |_2_| |_1_| |_4_| |_3_| |14_| |13_| |16_| |15_| |10_| |_9_| |12_| |11_|
150 * Quad # - |__________2__________| |__________1__________| |__________3__________| |__________4__________|
151 * 32 byte block # - |______________________________________________1______________________________________________|
153 * The "Pair #", "Quad #", and "32 byte block #" rows each are there to
154 * make the general ordering of the code more visible. The first thing to
155 * note is that the range of encoded byte values runs from 00 to 1f. This
156 * will not always be the case for the first set of 32 characters. In
157 * fact, the next set of 32 characters (ASCII 64 to ASCII 95) is not in
158 * the range of 20 to 3f in encoded form. I never concerned myself with
159 * predicting exactly where each of the four 32 byte ranges are aligned
160 * within the range of 0 to 256. In my decoding scheme, I simply specify
161 * the location of the first character in a 32 byte block (which I have
162 * pre-determined via experimentation) and determine the locations of the
163 * rest of the characters in the block relative to the inital value. This
164 * amounts to a total of four hand-decoded characters for the entire code.
166 * From a starting point which is given (in this case the fact that ASCII
167 * 32 is encoded as 0x15), my decoding scheme follows a pattern that is
168 * probably already apparent to you if you have examined the above table
169 * closely. First, if the encoded byte number is odd, it simple subtracts
170 * one from this byte number to get the byte number of the encoded form of
171 * the subsequent character. This is much more simple than it sounds.
172 * As an example, given that the code for ASCII 32 is 0x15, the program
173 * knows that the code for ASCII 33 must be 0x14. The tricky part is that
174 * this is not always true for every code. Recall that there is a different
175 * coding scheme for each of the 8 columns in a password, and that the above
176 * table only describes the coding scheme for the first column. Other columns
177 * reverse this relationship between the two ASCII values of a certain pair.
179 * Pairs are grouped into units of four, appearing in a predefined pattern.
180 * In this case, the first pair (by first I mean the pair with the lowest
181 * set of ASCII values) is put in the second slot of a quad (which contains
182 * four pairs). The second pair is put in the first slot, the third is put
183 * in the fourth quad, and the fourth is put in the third quad. This changes
184 * depending on the specific code used (of the 8 possible).
186 * Quads also fill a block in the same manner, however the ordering is NOT
187 * necessarily the same as the way pairs fit into quads! As I described
188 * above, there are four blocks, and they fit into the entire range of
189 * 128 values just as pairs fit into quads and quads fit into blocks,
190 * via a pattern determined by whoever invented this encoding scheme. It
191 * is important to realize that the range of 128 possible encoded
192 * values can be anywhere within the range of 0 to 256. Ie: One block can
193 * be positioned from 0x00 to 0x1f, while another block in the same code
194 * can be positioned from 0xa0 to 0xbf.
196 * I realize that the above description is a bit complex, and it doesn't
197 * really cover much of _how_ my program decodes the the encoded values.
198 * If you honestly can't understand a word I've said, just go back to
199 * the table and really take a long look at it. Print it out, put it
200 * under your pillow when you go to sleep. Sooner or later the order
201 * of it all will dawn on you and you should be able to step through
202 * my code and see how it derives its answer, at least for the
203 * DecodeCharOne() routine. Seven other tables (which I have rough
204 * copies of here on notebook paper) were needed to come up with
205 * the seven other decoders for the seven other character places.
209 int DecodeCharOne(unsigned char *mychar) {
210 int i = 0; /* Keeps track of the decoded character # minus 32 */
211 int cletter = 1; /* Sets the current letter of the 8 char quad */
212 int blockl1 = 1; /* Sets the current quad */
213 int blockl2 = 1; /* Sets the current 32 char block */
215 /* We are on this col of the table: */
216 unsigned char code = 0x15; /* The code for a space */
218 /* This is the main loop. It walks through each decoded character, finds
219 * its corresponding encoded value, and looks to see if that's the same as
220 * the encoded value we are looking for. If it is, we have found our
223 while((i<256) && (code != *mychar)) {
255 switch (blockl1) { /* After we hit character number 8, we have */
256 case 1: /* to do a relative jump to the next quad */
270 switch (blockl2) { /* After we hit the last quad, we have to */
271 case 1: /* jump to the next 32 character block. */
294 if (i == 256) retval = 0;
295 else *mychar = i + 32;
297 } /* End of DecodeCharOne() */
299 int DecodeCharTwo(unsigned char *mychar) {
305 unsigned char code = 0xba; /* The code for a space */
306 while((i<256) && (code != *mychar)) {
377 if (i == 256) retval = 0;
378 else *mychar = i + 32;
380 } /* End of DecodeCharTwo() */
382 int DecodeCharThree(unsigned char *mychar) {
388 unsigned char code = 0x6d; /* The code for a space */
389 while((i<256) && (code != *mychar)) {
460 if (i == 256) retval = 0;
461 else *mychar = i + 32;
463 } /* End of DecodeCharThree() */
465 int DecodeCharFour(unsigned char *mychar) {
471 unsigned char code = 0x86; /* The code for a space */
472 while((i<256) && (code != *mychar)) {
543 if (i == 256) retval = 0;
544 else *mychar = i + 32;
546 } /* End of DecodeCharFour() */
548 int DecodeCharFive(unsigned char *mychar) {
554 unsigned char code = 0x73; /* The code for a space */
555 while((i<256) && (code != *mychar)) {
626 if (i == 256) retval = 0;
627 else *mychar = i + 32;
629 } /* End of DecodeCharFive() */
631 int DecodeCharSix(unsigned char *mychar) {
637 unsigned char code = 0x89; /* The code for a space */
638 while((i<256) && (code != *mychar)) {
709 if (i == 256) retval = 0;
710 else *mychar = i + 32;
712 } /* End of DecodeCharSix() */
714 int DecodeCharSeven(unsigned char *mychar) {
720 unsigned char code = 0xf4; /* The code for a space */
721 while((i<256) && (code != *mychar)) {
792 if (i == 256) retval = 0;
793 else *mychar = i + 32;
795 } /* End of DecodeCharSeven() */
797 int DecodeCharEight(unsigned char *mychar) {
803 unsigned char code = 0x4a; /* The code for a space */
804 while((i<256) && (code != *mychar)) {
875 if (i == 256) retval = 0;
876 else *mychar = i + 32;
878 } /* End of DecodeCharEight() */