L2PacketHackФорум программы L2PacketHack, всё что с ней связано находится тут.
Правила раздела!
Категорически запрещено:
* Просить пакеты/скрипты на шмот/адену/другие вещи;
* Просить (помочь) взломать/сломать сервак/аккаунт или раздеть/наказать кого-то на любом серваке;
* Просить научить работать с программой, если не понимаете элементарных вещей в отношениях клиент-сервер (так как, если вы их понимаете, то вопросов по основным возможностям программы быть недолжно);
* Все посты не удовлетворяющие этим запретам, а так же не относящиеся к теме будут удаляться при первой возможности.
* Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы.
* Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.
* Данные запреты неподлежат обсуждению.
Linux, для корректного переноса проекта на поддерживающие юникод делфи нужно также заменить PChar на PAnsiChar, Char на AnsiChar и в целом проанализировать использование строк и символов в проекте
__________________ Начало.
За это сообщение supernewbie нажился спасибкой от:
В методе LS_LoginOk есть запись двух ключей SessionKey1_1 и SessionKey1_2 в секцию пакета для RequestServerList().
SessionKey приходит от сервера и его же нужно отправлять серверу в следующем пакете без каких-либо изменений.
Главное чтобы BF-шифрование верно отрабатывало.
к верно посоветанному
Цитата:
Сообщение от supernewbie
нужно также заменить PChar на PAnsiChar, Char на AnsiChar
могу добавить: заменить "string" на "AnsiString" и "Chr" на "AnsiChar" (об этом многие забывают, что может приводить к ошибкам). Можно тупо прогнать полную замену без анализа (но с опцией "только целые слова"), должно заработать.
PS. По статьям: зайди к нам на сайт, там на главной странице ссылки есть.
PS. По статьям: зайди к нам на сайт, там на главной странице ссылки есть.
Хочется поблагодарить следующих людей: TechnoWiz@rd, за базовую информацию для понимания протокола Lineage, а также KyberPrizrak за доработку исходной статьи.
Т.е. лучше изучать по статье KyberPrizrak? Его статья более расширенная? На глаз пока сложно определить отличия
UPD1
Еще один момент смущает: статья KyberPrizrak исправляющая баги (со слов KyberPrizrak) статьи TechnoWiz@rd имеет последнее редактирование 06.07.2007, в то время как статья TechnoWiz@rd была отредактирована 23.11.2007
Какой же версии описания протокола стоит доверять больше?
Последний раз редактировалось Linux, 01.06.2016 в 15:54.
Т.е. лучше изучать по статье KyberPrizrak? Его статья более расширенная? На глаз пока сложно определить отличия
это очень давно было, но на сколько помню у KyberPrizrak более верный протокол описан (как и по последовательности пакетов, так и по их содержимому)
Цитата:
Какой же версии описания протокола стоит доверять больше?
доверять можно только самостоятельно проснифанному трафику, т.к. часть очень важных пакетов (RequestAuthLogin, NetPing, s:8D) могут меняться от сервера к серверу
Цитата:
Сообщение от Linux
По собранной статистике можно понять поведение двух разных подключений? Где в моем случае была допущена ошибка, из-за чего до Game-Server так и не доходила программа?
у тебя пакет RequestAuthLogin значительно меньше, чем в оригинальном клиенте, расшифровывай пакет, смотри что внутри, возможно поймешь, что нужно передавать
у тебя пакет RequestAuthLogin значительно меньше, чем в оригинальном клиенте, расшифровывай пакет, смотри что внутри, возможно поймешь, что нужно передавать
1.1) А не подскажете чем расшифровывать или по какому алгоритму?
В проекте идет метод BlowFish.pas (by xkor) с комплектом методов:
procedure AddCheckSumm(var data: array of byte; Len: Integer);
function RepairKey(key: String): String;
function RSAEncrypt(a,p,rsakey: String): String;
function AntiXOR(s: String): String;
Что из этого подойдет?
1.2) А зачем пакет расшифровывать если пакет идет на сервер?
2) Добавил сравнительную таблицу пакетов (compare_LS.png), учитывая что первые 2 байта это размер, с 3-го кодируются данные, как по размеру пакета понять какой это пакет: Init, RequestAuthLogin и т.д.??
1.1) А не подскажете чем расшифровывать или по какому алгоритму?
По умолчанию трафик в Ла2 шифруется с помощью BF (также для RequestAuthLogin используется RSA и для части пакетов еще какой-то xor). Ответить на вопрос "чем и как" в данном случае, к сожалению, не смогу, т.к. ответ потянет минимум на полновесную статью, а то и на главу какой-нить книги, к тому же не являюсь большим специалистом в этой области.
Цитата:
Что из этого подойдет?
Все из перечисленных функций как раз занимаются расшифровкой пакетов.
Цитата:
1.2) А зачем пакет расшифровывать если пакет идет на сервер?
Это как проход через часового: ты должен знать пароль для прохода и лучший вариант его узнать - подслушать пароль.
Цитата:
как по размеру пакета понять какой это пакет
никак, в данном случае можно догадаться по очередности пакетов, на сколько помню очередность такая:
1) сервер присылает Init
2) клиент отвечает AuthGameGuard
3) сервер GGAuth
4) клиент RequestAuthLogin
5) сервер LoginOk либо LoginFail
6) клиент RequestServerList
7) сервер ServerList
8) клиент RequestServerLogin
9) сервер PlayOk либо PlayFail
плюс в эти пакеты могут вмешиваться NetPing и 8D
PS. В очередности могу немного ошибиться, за подробностями обращайся к статьям KyberPrizrak.
const
MAX_PKT_SIZE = $FFFF;
var
BLOWFISH_KEY: String; { 6B60CB5B82CE90B1CC2B6C556C6C6C6C }
MainBuff: array[0..MAX_PKT_SIZE-1] of byte;
RecvPktCount: Integer;
DecodeBF: boolean;
L2BF: L2BlowFish;
L2BF_Key: String;
RSA_Key: String;
SessionID: Integer;
GGAuthResponse: Integer;
SessionKey1_1, SessionKey1_2: Integer;
SessionKey2_1, SessionKey2_2: Integer;
procedure TfrmMain.WMSOCK_RS_EVENT(var Msg: TMessage);
var
SocketError: Integer;
Len: Integer;
begin
SocketError := WSAGetSelectError(Msg.lParam);
if (SocketError<>0) then begin
if SocketError=10053 then
ToLog('[WMSOCK_RS_EVENT]: WSAECONNABORTED (#10053) - Software caused connection abort')
else
ToLog('[WMSOCK_RS_EVENT]: WS_ERROR (#number): '+IntToStr(SocketError));
ToLog('');
L2SocketClose(RS_Socket);
Exit;
end;
case WSAGetSelectEvent(Msg.lParam) of
FD_Read:
begin
FillChar(MainBuff, Length(MainBuff), 0);
Len := recv(RS_Socket, MainBuff, MAX_PKT_SIZE, 0);
inc(RecvPktCount);
LS_Parser(MainBuff, Len);
end;
FD_Close:
L2SocketClose(RS_Socket);
end;
end;
procedure TfrmMain.LS_Parser(buff: Array of Byte; Len: Integer);
var
temp: array [0..MAX_PKT_SIZE-1] of char;
s: string;
i: integer;
begin
if RecvPktCount=1 then
begin
if buff[2]=0 then
DecodeBF := False
else
DecodeBF := True;
end;
if DecodeBF then
begin
Move(buff[2],temp[0],Len-2);
L2BF.bfDecode(temp,Len-2);
if temp[0]=#0 then
begin
SetLength(s,Len-2);
for i:=0 to Len-3 do
s[i+1]:=temp[i];
s:=AntiXor(s);
for i:=0 to Len-3 do
temp[i]:=s[i+1];
end;
Move(temp[0],buff[2],Len-2);
end;
PacketView(buff,Len,True);
case buff[2] of
$00:
LS_Init(buff,Len);
$0B:
LS_GGAuth(buff,Len);
$01:
LS_LoginFail(buff,Len);
$03:
LS_LoginOk(buff,Len);
$04:
LS_ServerList(buff,Len);
$06:
LS_PlayFail(buff,Len);
$07:
LS_PlayOk(buff,Len);
end;
end;
Порядок авторизации на Login-Server:
1) Init().................................................. .[OK] { Server->Client } Оффтоп
Код:
procedure TfrmMain.LS_Init(buff: array of byte; Len: integer);
begin
if Len<8 then exit;
Move(buff[3], SessionID, 4);
if Len>=155 then
begin
SetLength(RSA_key,128);
Move(buff[11],RSA_key[1],128); { RSA Key changed }
end;
if Len>=171 then
begin
SetLength(L2BF_key,16);
Move(buff[155],L2BF_key[1],16); { BlowFish Key changed }
L2BF.Init(L2BF_key);
end;
end;
{ sending RequestGGAuth packet }
RequestGGAuth();
procedure TfrmMain.RequestGGAuth;
var
Data: array[0..39] of byte;
begin
FillChar(data, Length(data), 0);
data[0]:=7;
Move(SessionID, data[1], 4);
AddCheckSumm(data, 24);
PacketSend(data, 40);
end;
3) LS_GGAuth().........................................[OK] { Server->Client } сервер ответил, что авторизация на GG прошла успешно Оффтоп
Код:
procedure TfrmMain.LS_GGAuth(buff: array of byte; Len: integer);
begin
if Len>=7 then
Move(buff[3], GGAuthResponse, 4);
RequestAuthLogin(Login, Password);
end;
procedure TfrmMain.RequestAuthLogin(_login, _password: string);
var
data: array[0..175] of byte;
crypt_text: string;
begin
FillChar(data,Length(data),0);
crypt_text := RSAEncrypt(_login, _password, RepairKey(RSA_key));
Move(crypt_text[1], data[1], 128);
Move(GGAuthResponse, data[129], 4);
data[149]:=8;
AddCheckSumm(Data, 160);
PacketSend(Data, 176);
end;
5) LoginOK().............................................[OK] { Server->Client } проверка Логина и Пароля прошла успешно, +Session_Key_1 Оффтоп
Код:
procedure TfrmMain.LS_LoginOk(buff: array of byte; Len: integer);
begin
if Len<12 then exit;
ToLog('[LS_LoginOk]: Login Successful!');
ToLog('');
Move(buff[3],SessionKey1_1,4);
Move(buff[7],SessionKey1_2,4);
RequestServerList();
end;
Далее описывать код пока не буду - до тех пунктов даже не доходит программа
7) ServerList()..........................................[NoNe] { Server->Client } передается список рабочих серверов
8) RequestServerLogin()............................[NoNe] { Client->Server } запрос игры на выбранном сервере
9) PlayOK()..............................................[NoNe] { Server->Client } подключение к Game-Server разрешено, +Session_Key_2
Лог выполнения программы - L2Connect_Log.txt
Вопросы:
1) Ну раз программа прошла GGAuth и LoginOK значит с шифрованием все нормально: иначе бы в методе LS_Parser программа не смогла бы определить тип пакета ( [LS_Parser]: buff[2]=0x0B ) и не продвинулась бы дальше по цепочке. Что не так в пакете RequestServerList? в упор не пойму, где я ошибся
Последний раз редактировалось Linux, 07.06.2016 в 17:42.