1 #include < stdio.h >
2 #include < stdlib.h >
3 #include < string.h >
4 #include < i86.h >
5
6 // =================================
7 // Таблицы перестановок
8 // исходная позиция
9 int src[12]={ 0x0, 0x1, 0x2, 0x6, 0x8,
10 0x0C, 0x0E, 0x12, 0x14, 0x16,
11 0x1A, 0x1C}
;
12 // конечная позиция
13 int dst[12]={ 0x0, 0x1, 0x4, 0x8, 0x0C,
14 0x10, 0x14, 0x18, 0x1A, 0x1C,
15 0x20, 0x22}
;
16 // длина престановки вычисляется как разница двух
17 // соседних позиций в таблице scr
18 // таблица подстановок она же разрешенный алфавит
19 // для ключа
20 char tabl[]="cdefghqrijka8blmn7opst0uv1wxyz234569";
21 // =================================
22
23 // промежуточные буфера для преобразований
24 char digi5[5];
25 char digi8[8];
26 char arr[232];
27
28 unsigned int lan1;
29 unsigned int lan2;
30 char key[47];
31 char key1[37];
32 char data[38];
33
34 // чей-то ключ .... использовался для пробы расшифровки ключа
35 char t[]="ahbatktktokuwktktkt8oeuktktkhtktktkatktktokabc";
36
37 int code(unsigned char ch)
38 // процедурка кодирования байта по таблице подстановок
39 // возвращает номер в кодовой таблице
40 {
41 char i;
42 for (i=0;i < 36;i++)
43 if (tabl[i]==ch) return (i);
44 return (-1);
45 }
46
47 char decode(int ch)
48 // это наоборот декодирует символ
49 {
50 if (ch!=-1) return (tabl[ch]);
51 else return (0);
52 }
53
54
55 void to5(int n)
56 // ну это преобразует 5 младших бит в текствое представление
57 {
58 int i;
59 int t;
60
61 for (i=0;i < 5;i++)
62 {
63 t=1 < < i;
64 if ( (n&t) > 0 ) digi5[i]='1';
65 else digi5[i]='0';
66 }
67 }
68
69 void to8(int n)
70 {
71 // ну это преобразует байт в текствое представление
72 int i;
73 int t;
74
75 for (i=0;i < 8;i++)
76 {
77 t=1 < < i;
78 if ( (n&t) > 0 ) digi8[i]='1';
79 else digi8[i]='0';
80 }
81 }
82
83 int from5(char *d5)
84 {
85 // из текстововых 5 бит получаем число
86 int i;
87 int t=0;
88
89 for (i=0;i < 5;i++)
90 if (*(d5+i)=='1') t=t+(1 < < i);
91 return (t);
92 }
93
94
95 int from8(char *d8)
96 {
97 // из текстововых 8 бит получаем число
98 int i;
99 int t=0;
100
101 for (i=0;i < 8;i++)
102 if (*(d8+i)=='1') t=t+(1 < < i);
103 return (t);
104 }
105
106
107 void expandkey()
108 {
109 // процедура преобразования 46 входных символов ключа
110 // в 36 байт данных
111 int i,i1;
112 int ch;
113 int len=0;
114
115
116 memset (arr,'0',232);
117
118 for (i=0;i < 46;i++)
119 {
120 ch=code(key[i]); // вначале декодируем по таблице
121 if (ch==-1) ch=0;
122 to5(ch);
123 for (i1=0;i1 < 5;i1++,len++)
124 arr[i*5+i1]=digi5[i1]; // заполняем промежуточный буффер
125 }
126
127 // а теперь по буферу востанавливаем значения
128 // байт данных
129 for (i=0;i < 36;i++)
130 key1[i]=from8(&arr[i*8]);
131 }
132
133 int checkkey()
134 // проверка ключа
135 // даже не знаю, зачем такой ненадежный алгоритм ?
136 // есть же CRC
137 {
138 int i;
139 int t=0;
140 unsigned int t1;
141
142 for (i=0;i < (30*8);i++)
143 {
144 t1=1 < < (i%8);
145 if ((key1[i > > 3]&t1)!=0) t++;
146 }
147 return (t);
148 }
149
150 void swap(char *ch1,char *ch2)
151 {
152 char t;
153 t=*ch1; *ch1=*ch2; *ch2=t;
154 }
155
156
157 void copy()
158 // процедурка пререстановок байт данных
159 {
160 int i,i1;
161 char tkey[37];
162
163 memset (tkey,0,36);
164 // первичное тасование байт
165 for (i=0;i < 11;i++)
166 memcpy (&tkey[dst[i]],&key1[src[i]],src[i+1]-src[i]);
167
168 memset (key1,0,36);
169
170 // а вот это зачем ?
171 // прям клас программирования :)
172 memcpy (&key1[4],&tkey[4],4);
173 memcpy (&key1[12],&tkey[12],4);
174 memcpy (&key1[20],&tkey[20],4);
175 memcpy (&key1[28],&tkey[28],4);
176
177 key1[0]=tkey[0];
178 key1[1]=tkey[1];
179
180 key1[8]=tkey[9];
181 key1[9]=tkey[8];
182
183 key1[16]=tkey[17];
184 key1[17]=tkey[16];
185
186 key1[24]=tkey[25];
187 key1[25]=tkey[24];
188
189 key1[26]=tkey[27];
190 key1[27]=tkey[26];
191
192 key1[32]=tkey[33];
193 key1[33]=tkey[32];
194 }
195
196 void copy2data()
197 // процеду обратная предыдущей
198 // зачем усложнять себе жизнь :)
199 {
200 int i,i1;
201
202 memset (data,0,38);
203
204 data[0]=key1[8];
205 data[1]=key1[9];
206 memcpy (&data[4],&key1[4],4);
207 memcpy (&data[8],&key1[12],4);
208 memcpy (&data[12],&key1[20],4);
209 memcpy (&data[16],&key1[28],4);
210 data[20]=key1[0];
211 data[24]=key1[1];
212
213 data[28]=key1[24];
214 data[29]=key1[25];
215
216 data[32]=key1[26];
217 data[33]=key1[27];
218
219 data[36]=key1[16];
220 data[37]=key1[17];
221 }
222
223
224 void getdatafromkey()
225 // собственно получение информации из ключа
226 // была написана, чисто в тестовых целях
227 // а вдруг мы чего не знаем ?
228 {
229 int i,i1;
230
231 expandkey(); // преобразование 46- > 36
232 for (i=0;i < 28;i++)
233 key1[i]=key1[i]^0xAA;
234 // в последнем байте используются не все биты
235 key1[28]=key1[28]^0x2A;
236
237 copy();
238 i=checkkey();
239 i1=(key1[33] < < 8)+key1[32];
240 // дальше этого в инсталяхе не идет !
241 if (i==i1) printf ("Check OK! \n");
242 else printf ("Check Error! (%04X/%04X) \n",i,i1);
243
244 copy2data(); // получаем информацию из ключа
245
246 printf ("App ID: %04X \n", (data[1] < < 8)+data[0]);
247 // тут или 1 или 3
248 printf ("Type : %04X \n", (data[0x15] < < 8)+data[0x14]);
249 // тут вроде бы кодируется язык ?
250 printf ("Count : %04X \n", (data[0x19] < < 8)+data[0x18]);
251 printf ("Left : %04X \n", (data[0x19] < < 8)+data[0x18]);
252 // количество запусков в данном случае проверяется
253 // не равенство 0
254 printf ("Exp.D.: %04X \n", (data[0x25] < < 8)+data[0x24]);
255 // дата конца (стандартная функция LocalTime
256 // количество дней с 1970 года
257 printf ("Lan ID: 0800 %04X %04X \n",
258 (data[0x21] < < 8)+data[0x20],(data[0x1D] < < 8)+data[0x1C]);
259 // а тут собственно LanID выдаваемый в программе инсталяции
260 }
261
262 void copy4data()
263 {
264 // процедура обратная получению информации из данных ключа
265 // заполняет массив ключевыми данными
266 int i,i1;
267
268 // for(i=0;i < 37;i++)
269 // key1[i]=rand();
270 memset (key1,0,37);
271
272 memcpy (&key1[4],&data[4],4);
273 memcpy (&key1[12],&data[8],4);
274 memcpy (&key1[20],&data[12],4);
275 memcpy (&key1[28],&data[16],4);
276
277 key1[8]=data[0];
278 key1[9]=data[1];
279
280 key1[0]=data[20];
281 key1[1]=data[24];
282
283 key1[24]=data[28];
284 key1[25]=data[29];
285
286 key1[26]=data[32];
287 key1[27]=data[33];
288
289 key1[16]=data[36];
290 key1[17]=data[37];
291 }
292
293 void copy1()
294 // функция обратного перемешивающего преобразования
295 // преставляет простой реверс исходного алгоритма
296 {
297 int i,i1;
298 char tkey[37];
299
300 memset (tkey,0,36);
301
302 memcpy (&tkey[28],&key1[28],4);
303 memcpy (&tkey[20],&key1[20],4);
304 memcpy (&tkey[12],&key1[12],4);
305 memcpy (&tkey[4],&key1[4],4);
306
307 tkey[0]=key1[0];
308 tkey[1]=key1[1];
309
310 tkey[9]=key1[8];
311 tkey[8]=key1[9];
312 tkey[17]=key1[16];
313 tkey[16]=key1[17];
314 tkey[25]=key1[24];
315 tkey[24]=key1[25];
316 tkey[27]=key1[26];
317 tkey[26]=key1[27];
318 tkey[32]=key1[32];
319 tkey[33]=key1[33];
320
321 memset (key1,0,36);
322
323 // образование перемешивающее преобразование
324 for (i=0;i < 11;i++)
325 memcpy (&key1[src[i]],&tkey[dst[i]],src[i+1]-src[i]);
326
327 }
328
329 void packkey()
330 // преобразование двоичных данных в текствую строку
331 {
332 int i,i1;
333 char ch;
334
335 memset (arr,'0',232);
336 // преобразовываем в двоичное представление
337 for (i=0;i < 29;i++)
338 {
339 to8(key1[i]);
340 for (i1=0;i1 < 8;i1++)
341 arr[i*8+i1]=digi8[i1];
342 }
343
344 memset (key,0,47);
345 // ну а теперь это двоичное представление преобразовываем
346 // к текстовому виду
347 for (i=0;i < 46;i++)
348 {
349 i1=from5(&arr[i*5]); // получем числовое значение 5 бит
350 ch=decode(i1); // кодируем по таблице
351 key[i]=ch;
352 }
353 }
354
355
356 void setdatatokey()
357 {
358 char lan[13];
359 unsigned int i;
360 // вот это выдает программа инсталяции
361 printf ("Enter LanID: ");
362 scanf ("%12s",lan);
363 lan[13]=0;
364 lan1=(int ) strtoul(&lan[7],NULL ,16);
365 lan[8]=0;
366 lan2=(int ) strtoul(&lan[4],NULL ,16);
367
368 memset (data,0x00,38);
369 // заполнение некоторыми значениями ключ
370 data[1]=0x00; data[0]=0x01; // App ID
371 data[0x15]=0; data[0x14]=0x1; // Type
372 data[0x19]=0; data[0x18]=0x1E; //Count
373 data[0x25]=0x00; data[0x24]=0x00; //Exp.D.
374 data[0x1D]=lan1 > > 8; data[0x1C]=lan1&0x0FF;
375 data[0x21]=lan2 > > 8; data[0x20]=lan2&0x0FF;
376
377 // открываем все системы !!!
378 for (i=4;i < 0x14;i++)
379 data[i]=0xFF;
380
381 // копируем данные для подготовки ключа
382 copy4data();
383 // вычисляем контрольную сумму и сохраняем ее
384 i=checkkey();
385 key1[32]=i > > 8;
386 key1[33]=i&0xFF;
387
388 // выполняем перестановки
389 copy1();
390 // это попытка спрятать данные :)
391 for (i=0;i < 28;i++)
392 key1[i]=key1[i]^0xAA;
393
394 key1[28]=key1[28]^0x2A;
395
396 // преобразование двоичных данных в текствую строку
397 packkey();
398 // выдача текста ключа :)
399 printf ("%s \n",key);
400 }
401
402 main()
403 {
404 memset (key,0,43);
405 // тестовый режим чтение информации из тестового ключа
406 // strcpy(key,t);
407 // getdatafromkey();
408
409 // создание нового ключа и его тестирование
410 setdatatokey();
411 getdatafromkey();
412 }
413