Во первых сразу замечу что существует две ревизии протокола использующиеся на данный момент(может и больше но мне о них не известно) - c621 и 785a.
Отличие их в том что в c621 используется дополнительное шифрование и авторизация GameGuard. Пакеты Init и RequestAuthLogin также отличаются.
Определить версию можно по размеру пакета Init, для ревизии 785a он составляет 11 байт, для c621 – 170.
1. Сразу после установки соединения сервер отправляет клиенту пакет Init
2. В ответ на него клиент отправляет пакет RequestGGAuth(в ревизии протокола 785a этот пакет не высылается)
3. Сервер отвечает на него пакетом GGAuth (в ревизии протокола 785a этот пакет не высылается)
4. Если сервер ответил, что авторизация прошла успешно, то клиент высылает пакет RequestAuthLogin, содержащий логин и пароль.
5. Проверка логина и пароля, в случае неудачи, сервер высылает пакет LoginFail содержащий причину неудачи, инатче высылается пакет LoginOk, содержащий session key #1.
6. Далее клиент запрашивает список серверов пакетом RequestServerList
7. В ответ на этот пакет сервер высылает клиенту ServerList, в нем содержиться список серверов и их IP адреса с номерами портов.
8. После выбора game-сервера, и нажатия на ОК, клиент отсылает пакет RequestServerLogin
9. Сервер авторизации выполняет проверки на максимальное количество игроков, доступность сервера и т.п., если все проверки пройдены, то высылает пакет PlayOk,содержащий session key #2, этот ключь генерируется из текущего времени системы в мс, номера сокета и еще всякой лабуды. После этого клиент отключается от логин сервера и подключается к гейм серверу.
Подключаюсь к серверу авторизации. Сервер мне выдает 11 байт:
Код:
0B 00 00 BC 19 4C 77 5A 78 00 00
в которых видно, что ревизия 785a
т.е. 2 и 3 пункты нам не нужны.
далее я формирую и отправляю пакет RequestAuthLogin с реальными данными.
Но сервер меня дисконектит...
Согласно вот этого (взято с вышеуказанного сайта):
Цитата:
RequestAuthLogin
Назначение: запрашивает авторизацию на логин сервере
Формат для ревизии 0x785a:
Код:
00
XX XX XX XX 00 // строка содержащая логин. Имеет длинну 14 байт и храниться в формате ASCII а не UNICODE !!!
XX XX XX XX 00 // строка содержащая пароль. Имеет длинну 16 байт и храниться в формате ASCII а не UNICODE !!!
08 // маркер конца секции логин/пароль
00 00 00 00 // не используется
00 00 00 00 // не используется
Делаю так :
Код:
...
type TRequestAuthLogin = packed record
s1:byte;
login:packed array[1..14] of char;
pass:packed array[1..16] of char;
s2:byte;
s3:cardinal;
s4:cardinal;
end;
...
var
login:string='реальный логин';
password:string='реальный пароль';
...
procedure ... // процедура формирования и отправки пакета RequestAuthLogin
var
str:TRequestAuthLogin;
i: integer;
begin
str.s1:=0;
str.s2:=8;
str.s3:=0;
str.s4:=0;
for i:=1 to 14 do
if i>length(login)
then str.login[i]:=chr(0)
else str.login[i]:=login[i];
for i:=1 to 16 do
if i>length(password)
then str.pass[i]:=chr(0)
else str.pass[i]:=password[i];
..... // Здесь отправляю сформированный пакет...
end;
...
Когда смотрю снифером, что отправляется на сервер при авторизации стандартным клиентом, то все равно не вижу там ничего похожего на свой логин и пароль в ASCII.
Что я неправильно делаю или что я неправильно понял в описании протокола?
Добавлено через 46 минут
Поискал еще информацию.
Понял что забыл передавать размер пакета вначале, ну и как оказалось нужно все шифровать в Blowfish
У кого есть исходники Blowfish на Delphi ?
Последний раз редактировалось glukmaker, 11.10.2011 в 20:18.
Причина: Добавлено сообщение
За ссылки - спасибо.
Но все равно пока я ничего не добился...
Делал все так:
В модуле Blowfish исправил:
Код:
...
L2BlowFish = class
...
далее делаю так:
Код:
type TRequestAuthLogin = packed record
length:word;
case byte of
0:(
s1:byte;
login:packed array[1..14] of char;
pass:packed array[1..16] of char;
s2:byte;
s3:cardinal;
s4:cardinal;
checksum:cardinal;
s5:cardinal;
);
1: (
buf:packed array[1..48] of byte; // для удобства криптования
);
2: (
fch:packed array[1..12] of cardinal; // для удобства вычисления сhecksum
)
end;
...
var
...
login:string='testlogin';
password:string='testpass';
const
Token:string=#$5F#$3B#$35#$2E#$5D#$39#$34#$2D#$33#$31#$3D#$3D#$2D#$25#$78#$54#$21#$5E#$5B#$24#$00;
...
function CheckSum(data:array of cardinal):cardinal;
var
i:integer;
begin
result:=0;
for i:=low(data) to high(data) do Result:=result xor data[i];
end;
procedure TForm1.Button3Click(Sender: TObject);
var
str:TRequestAuthLogin;
var i: integer;
begin
str.length:=SIZEOF(str);
str.s1:=0;
str.s2:=8;
str.s3:=0;
str.s4:=0;
for i:=1 to 14 do
if i>length(login)
then str.login[i]:=chr(0)
else str.login[i]:=login[i];
for i:=1 to 16 do
if i>length(password)
then str.pass[i]:=chr(0)
else str.pass[i]:=password[i];
str.checksum:=0;
str.s5:=0;
showdata(str, sizeof(str));
str.checksum:=CheckSum(str.fch);
showdata(str, sizeof(str));
With L2BlowFish.Create do
try
Init(Token,length(Token));
bfEncode(str.buf,length(str.buf));
finally
free;
end;
showdata(str, sizeof(str)); // отображение пакета в мемо
ClientSocket1.Socket.SendBuf(str,sizeof(str));
end;
Как видно, пакеты от меня и от клиента отличаются.
Похоже, я снова делаю что-то неправильно...
так как впервые я заинтересовался протоколом ла2 (со вчерашнего дня) , то не знаю даже в чем проблема.
Помогите, кто может...
Добавлено через 9 минут
Вобщем скорее всего тут одно из двух:
1. Я неправильно криптую пакет.
2. Я неправильно вычисляю контрольную сумму.
Насчет контрольной суммы, делаю так, как прочитал на одном из форумов:
Цитата:
До этапа шифрования в исходящие пакеты добавляется чексумма:
Из данных поочерёдно отделяются 32-битные слова. Первое XOR'ится со вторым. Результат этой операции XOR'ится со следующим словом и так далее.
Последний раз редактировалось glukmaker, 12.10.2011 в 12:19.
Причина: Добавлено сообщение
пробовал узнать токен с помощью EngExt_ME.exe - получаю Unknown ENGINE.DLL format.
Можно было бы спросить у местных ботоводов, но навряд-ли кто-то признается в том, что он ботами пользуется...
А у меня вобще-то конечная цель - получить доступ к альянсовому чату.
Добавлено через 1 час 13 минут
Все. Проблема была в токене.
Скачал Walker Patcher, правда он мне аж 5 токенов выдал.
Но методом расшифровки пакета, посылаемого клиентом я нашел из них нужный.
Вобщем с отсылкой пакета RequestAuthLogin уже все ясно... Теперь пошел читать описание протокола и пытаться по нему лезть дальше.
что на самом деле правильно?
И что подразумевается под ProtocolVersion? Значение, которое мы получили в пакете Init от логин-сервера? Или что-то другое?
Последний раз редактировалось glukmaker, 13.10.2011 в 18:24.
Причина: Добавлено сообщение
я так понимаю это исходящий пакет?
попробуй вытащить планку памяти, или добавь жесткий диск, или отключить сидиром, а лучше все вместе и посмотри на эту константу. я думаю она изменится
Похоже, что этот непонятный массив у меня совпадает с тем, который приводил в примере неизвестный мне человек.
Некоторые говорят, что можно вообще нули отправить и сервер это нормально примет.
Но остается вопрос насчет ProtocolVersion. Из дампа видно что это: 90 02 00 00 (если в десятичную систему перевести то получается 656).
Объясните физический смысл этого параметра?