Зравствуйте,
прошу подсказок и советов знающих людей по поводу криптоалгоритма Blowfish, используемого при шифровании пакетов la2.
Суть проблемы такова:
имею корректную реализацию этого алгоритма, причем ей правильно расшифровываются/шифруются тестовые вектора, приведенные на сайте разработчика алгоритма:
http://www.schneier.com/code/vectors.txt
Таким образом, я заключаю что имеющаяся реализация алгоритма работает корректно.
Есть некоторый сервер la2 high five, при помощи отладчика был вытащен пакет Init, имевший следующий вид [1]:
Код:
BA 00 B6 75 27 B6 F2 F6 88 FF F6 8A 3B 63 12 40
03 C0 8C C5 13 38 A3 C1 1F 85 E0 F6 08 56 AD 39
7E E9 16 96 38 C0 67 49 0F D1 CE 41 BB ED 2C D8
9B AB 8A F2 20 47 C9 84 68 87 36 D8 FC BE CC 03
D6 45 56 C3 37 11 FC E4 0F BF 08 15 4C 78 7F 86
A7 E9 32 8D C7 CA 92 86 80 57 39 0A FF 53 8F 08
D0 33 69 8B CC A0 C0 21 11 02 94 B7 0B 95 8C 66
5A 12 84 2B 89 4A 55 B9 E8 F4 01 B6 63 6F 26 65
F5 39 82 6F 1C C2 E9 E1 F1 C8 7A 59 57 9E 0F FD
39 32 99 F9 BB FA 2D 5E 86 AE 07 6D EC 6D B8 3D
A2 2C 6A 06 BB 4C AB D1 2A C2 3A 4A 9F 12 D9 12
09 92 E5 6C 00 E3 66 09 F2 3D
это сырые данные, пришедшие с логинсервера, первые два байта здесь это размер. Далее, после декрипта блоуфиша, пакет приобретает вид [2]:
Код:
BA 00 00 4D 13 D8 AA 16 E6 E6 8E C9 63 FE 8E 5D
32 FD 11 20 59 48 16 36 1A 21 7C 0C 98 D8 74 6D
4A 5D BE 37 EF 65 95 1D FD 31 94 DA 68 FC D7 E5
12 1F FA 36 E1 9A 75 05 BC 73 9D 8C C3 CF FE 4A
62 8E D3 53 BA EB F7 EC 2C 86 0A 2A 43 1A 9C 5C
45 41 82 91 0E F3 54 87 65 D4 F0 37 45 8B B8 6C
E7 67 70 77 B3 72 59 54 7F 47 38 2B 02 52 30 3A
09 20 3E 6D 9E D4 5C F2 11 AE 3B 8C 30 4E 37 93
5B 13 38 85 E0 F8 72 D5 C6 BD 4D 6A 35 DC BC DC
A1 06 7B 61 45 DF 34 CF 34 8D AD 38 F4 F0 7A 81
76 29 FE 95 4C 51 CD 75 41 14 24 6A CD DD 10 AD
00 32 E8 DE F2 65 40 FD 9B 1C
как видно, третий байт это у нас тип пакета, в соответствии с инфой из следующих источников:
раз
два
заключаю, что это и есть Init (id = 0x00)
этот же пакет после XORа [3]:
Код:
BA 00 00 4D 13 D8 24 21 C6 00 00 EB AD 8C 81 BD
7A C5 E3 F1 AC A8 3A 3A 92 F6 28 E1 AD 03 12 42
1F C1 2D C4 DD 74 01 37 65 DA 41 78 7A 09 81 2B
4C 95 57 34 5D 68 EE 81 83 40 03 35 5E 4E B1 F8
F7 66 C6 F0 96 91 F1 36 90 9F 96 E9 7F 25 E2 CC
BC 13 CE EA EA D8 04 96 58 5F 58 5B 24 10 48 82
4B 76 C7 C4 CF B1 71 73 81 6A C8 C2 0A B2 EA A8
74 73 72 7F 91 4A 8B 79 01 18 32 01 14 5D DF EF
3B 04 2A 56 DE 72 39 03 CC 99 21 4E 95 DD 29 FC
9C C3 77 20 B6 AD 97 F7 E0 BD 07 46 19 E8 EC EB
45 98 B5 DF 8D 5A D1 1F 72 2E D4 00 CD D3 F8 73
F2 57 E8 DE F2 65 40 FD 9B 1C
Здесь выделена версия протокола.
Напоминаю, что это у нас живые данные, выдранные из живой игры.
Анализ под отладчиком так же показал, что в качестве статического ключа используется стандартный:
Код:
6B 60 CB 5B 82 CE 90 B1 CC 2B 6C 55 6C 6C 6C 6C
т.е. однозначно определено, что данный ключ формируется из некоторого скрытого вида и используется для формирования некоторого блока данных, который в дальнейшем используется при шифровании/дешифровании.
Теперь я беру этот ключ, исходный пакет, полученный от сервера и имеющуюся корректную реализацию криптоалогиритма и расшифровываю, в итоге получаю:
Код:
b2 a0 10 d3 c0 f5 2f 86 f5 97 60 b4 3b b0 60 93
08 71 ae a9 fa 14 31 db fe 65 9c 71 df 69 d4 6b
73 35 e8 d9 bd 53 f5 fd 38 72 a4 fc b4 92 76 4d
3f f9 a5 b6 b8 ea 52 99 b2 c1 a8 2f 53 50 78 86
04 d0 06 0f cd d3 6e 0b 1c 95 81 8d b4 c6 15 f1
96 79 8d cb 56 ce 04 d5 ea 79 59 ae c4 71 cc a4
4b b2 ef 06 4e ef 5f dd 8b ed 1a 8f b9 ed 0d 2a
f9 14 0b 82 2d 0c ba 78 13 10 66 8c b0 bc 59 24
8d 4e 7e 05 d7 d9 35 f9 4c f3 19 3d 2e 13 87 ef
72 91 5c 05 b3 47 c3 c0 9a 11 8f 9b 8e b4 06 f9
e6 7c 00 80 b7 81 0b 90 3b 6d da 79 17 05 23 84
4a a1 34 9d d9 83 fe 4c
а должно быть:
Код:
00 4D 13 D8 AA 16 E6 E6 8E C9 63 FE 8E 5D 32 FD
11 20 59 48 16 36 1A 21 7C 0C 98 D8 74 6D 4A 5D
BE 37 EF 65 95 1D FD 31 94 DA 68 FC D7 E5 12 1F
FA 36 E1 9A 75 05 BC 73 9D 8C C3 CF FE 4A 62 8E
D3 53 BA EB F7 EC 2C 86 0A 2A 43 1A 9C 5C 45 41
82 91 0E F3 54 87 65 D4 F0 37 45 8B B8 6C E7 67
70 77 B3 72 59 54 7F 47 38 2B 02 52 30 3A 09 20
3E 6D 9E D4 5C F2 11 AE 3B 8C 30 4E 37 93 5B 13
38 85 E0 F8 72 D5 C6 BD 4D 6A 35 DC BC DC A1 06
7B 61 45 DF 34 CF 34 8D AD 38 F4 F0 7A 81 76 29
FE 95 4C 51 CD 75 41 14 24 6A CD DD 10 AD 00 32
E8 DE F2 65 40 FD 9B 1C
т.е. должно соответствовать вышеприведенному пакету [2] без учета первых двух байт исходного размера пакета.
Вопрос такой:
каким это образом?
Тут единственно возможный вариант это некая модификация алгоритма в самой игре, если допустить что я не ошибся с предположением о ключе, используемом в игре (возможно он где-то еще дополнительно модифицируется в глубинах кода на этапе расширения ключа алгоритма)
Возможно кто-то сможет указать на уже готовую реализацию алгоритма, корректно расшифровывающих данный пакет.
Upd:
еще одна замеченная особенность, это тот факт, что шифрование/дешифрование в игре проводится не стандартными функциями, которые доступны через экспорт из библиотеки core.dll, а некоторыми безымянными не экспортируемыми функциями из библиотеки engine.dll.