PDA

Просмотр полной версии : Пакеты (LS) Gracia Final (l2jRT)


alexmarch
17.08.2009, 11:23
Интересуют пакеты только Логин сервера
Есть ява сервер от РТ.
В клиенте, в l2.exe выставил хост 127.0.0.1
Я написал программу (не на дельфи) она слушает порт 2106 и все входящие пакеты редеректит на сервер.
Соответственно я могу их прослушивать.
Но я не могу их прочитать.
Меня в частности интересует передаваемый логи и пасс.
Вот дамп в хейксе
от клиента
0x0000 : 2A 00 69 DE 42 66 6E 4D CA F6 51 2F C8 D9 BB 30 *.iЮBfnMКцQ/ИЩ»0
0x0010 : 0F DB 51 2F C8 D9 BB 30 0F DB BF 32 18 FE 85 3C .ЫQ/ИЩ»0.Ыї2.ю…<
0x0020 : A3 F1 51 2F C8 D9 BB 30 0F DB ЈсQ/ИЩ»0.Ы
Длинна: 42
0x0000 : B2 00 4B BE 36 B1 BF 0C EE EF 56 22 13 F3 62 84 І.Kѕ6±ї.опV".уb„
0x0010 : C0 DB E0 B3 9E 00 78 5C F3 B1 AB 2D 8E 33 B7 33 АЫаіћ.x\у±«-Ћ3·3
0x0020 : A1 F8 1E E9 8A 1E 10 0A CF C7 01 D6 81 AB 1C 23 Ўш.йЉ...ПЗ.ЦЃ«.#
0x0030 : C2 5A DC 86 E7 54 CC 64 96 80 F3 05 63 5F DF 10 ВZЬ†зTМd–Ђу.c_Я.
0x0040 : C5 DA A1 01 FA 4A B3 FE 80 7D BE 23 24 C9 2D 96 ЕЪЎ.ъJіюЂ}ѕ#$Й-–
0x0050 : C2 D0 D2 1F 9E 71 68 AE DC A9 A8 BC 49 20 64 68 ВРТ.ћqh®Ь©ЁјI.dh
0x0060 : E4 32 2F C3 82 E5 CD 01 A8 7F 6D 06 59 17 AF 7B д2/Г‚еН.Ёm.Y.Ї{
0x0070 : 40 F2 93 EE 64 3E E9 C2 C2 DC F5 63 4C 3E BE D5 @т“оd>йВВЬхcL>ѕХ
0x0080 : A4 CA F9 55 6E 09 90 72 2C E0 51 2F C8 D9 BB 30 ¤КщUn.ђr,аQ/ИЩ»0
0x0090 : 0F DB EA 2C 3C 35 FC 19 F3 22 51 2F C8 D9 BB 30 .Ык,<5ь.у"Q/ИЩ»0
0x00A0 : 0F DB C8 8E 29 50 23 0E 70 A2 51 2F C8 D9 BB 30 .ЫИЋ)P#.pўQ/ИЩ»0
0x00B0 : 0F DB .Ы
Длинна: 178
0x0000 : 22 00 5E AD EA 83 CE AE 71 4D 21 C4 C5 9E 6E D5 ".^*кѓО®qM!ДЕћnХ
0x0010 : FD 3D 15 DA 63 4D BD 03 66 88 51 2F C8 D9 BB 30 э=.ЪcMЅ.f?Q/ИЩ»0
0x0020 : 0F DB .Ы
Длинна: 34
0x0000 : 22 00 27 49 64 C0 97 F1 13 03 B6 C1 CA 00 2A 0C ".'IdА—с..¶БК.*.
0x0010 : BD 5C 8B 12 A9 59 6E 20 D2 78 51 2F C8 D9 BB 30 Ѕ\‹.©Yn.ТxQ/ИЩ»0
0x0020 : 0F DB .Ы
Длинна: 34

alexmarch
17.08.2009, 12:43
Пакеты от сервера
0x0000 : BA 00 8E 1F F5 87 0A 54 13 82 D2 C6 7C 2B 7B 02 є.Ћ.х‡.T.‚ТЖ|+{.
0x0010 : 2C EB 0A CA 4E 60 E3 CD 58 A0 39 FD 00 36 71 48 ,л.КN`гНX 9э.6qH
0x0020 : 22 98 99 F4 C2 23 E0 37 85 4B 4E 8C 75 16 40 F4 "˜™фВ#а7…KNЊu.@ф
0x0030 : 80 CE 6C DD C1 70 3E FB 30 EA 1C B2 99 64 66 C3 ЂОlЭБp>ы0к.І™dfГ
0x0040 : 3A 3B 48 59 03 0F 93 81 4A E9 C9 5F E8 12 1E 99 :;HY..“ЃJйЙ_и..™
0x0050 : 90 E6 14 25 89 33 30 A9 6C 4A 9B 0B B4 88 1A E5 ђж.%‰30©lJ›.ґ?.е
0x0060 : 4D CB 28 89 9A E6 CD 51 E0 FF 92 89 0D 4B 9F 2B MЛ(‰љжНQа.’‰.Kџ+
0x0070 : FD A3 94 33 9F 65 A0 20 CC C6 4B 23 48 EB DC 38 эЈ”3џe .МЖK#HлЬ8
0x0080 : 1A 5E 57 40 AB 55 7E 10 82 6A 19 DD F6 77 5C E8 .^W@«U~.‚j.Эцw\и
0x0090 : E9 96 83 5D CD C7 42 E7 F9 14 F2 E3 16 5B 57 6F й–ѓ]НЗBзщ.тг.[Wo
0x00A0 : 2F F6 7D 3B C3 5D 3B 8D 85 DD 05 91 C6 4F E2 C7 /ц};Г];Ќ…Э.‘ЖOвЗ
0x00B0 : 31 BF 29 FB 7A BB 13 E5 59 10 1ї)ыz».еY.
Длинна: 186
0x0000 : 22 00 F3 EE 38 25 A0 0F 54 B7 51 2F C8 D9 BB 30 ".уо8% .T·Q/ИЩ»0
0x0010 : 0F DB 68 56 C1 63 1F 8D 94 E1 A6 35 90 D7 D8 D9 .ЫhVБc.Ќ”б¦5ђЧШЩ
0x0020 : B4 4C ґL
Длинна: 34
0x0000 : 3A 00 7B 79 55 6F 6E 3D A4 73 10 42 3C 32 16 97 :.{yUon=¤s.B<2.—
0x0010 : 21 47 DD B3 32 08 CC B5 90 DB 51 2F C8 D9 BB 30 !GЭі2.МµђЫQ/ИЩ»0
0x0020 : 0F DB 51 2F C8 D9 BB 30 0F DB 51 2F C8 D9 BB 30 .ЫQ/ИЩ»0.ЫQ/ИЩ»0
0x0030 : 0F DB 50 1D 2C 20 0E 9A C8 1C .ЫP.,..љИ.
Длинна: 58
0x0000 : 22 00 F7 38 F4 D3 AD 9D F0 66 4B 1A 76 E2 C2 B6 ".ч8фУ*ќрfK.vвВ¶
0x0010 : 2F C3 08 10 A1 6E 15 2E 66 56 9F 8B CE 5B A2 9C /Г..Ўn..fVџ‹О[ўњ
0x0020 : DE 5F Ю_
Длинна: 34
0x0000 : 12 00 BA 65 32 C0 31 39 0F 8A 3A 37 F0 C9 CC 5F ..єe2А19.Љ:7рЙМ_
0x0010 : B0 86 °†
Длинна: 18

Добавлено через 1 час 13 минут
Вот что удалось нарыть в исходниках

public final class Init extends L2LoginServerPacket
{

public Init(L2LoginClient client)
{
this(client.getScrambledModulus(), client.getBlowfishKey(), client.getSessionId());
}

public Init(byte publickey[], byte blowfishkey[], int sessionId)
{
_sessionId = sessionId;
_publicKey = publickey;
_blowfishKey = blowfishkey;
}

protected void write()
{
writeC(0);
writeD(_sessionId);
writeD(50721);
writeB(_publicKey);
writeD(0x29dd954e);
writeD(0x77c39cfc);
writeD(0x97adb620);
writeD(0x7bde0f7);
writeB(_blowfishKey);
writeC(0);
}

private int _sessionId;
private byte _publicKey[];
private byte _blowfishKey[];


Добавлено через 4 минуты
Какой алгоритм на прочтения никак немогу вкурить?

xkor
17.08.2009, 16:35
логин и пароль ты сможешь из пакета извлеч только если перед этим в пакете от сервера подправишь RSA ключ которым будут логин и пароль зашифрованы на свой к которому у тебя есть ключ для дешифровки, иначе логин и пароль сможет дешифровать только сервер
ЗЫ а вообще формат пакетов логин сервера в этом разделе уже не раз обсуждался, так что глаза в руки и вперёд...
ЗЗЫ не путать с "глаз на жопу"))

alexmarch
17.08.2009, 19:20
логин и пароль ты сможешь из пакета извлеч только если перед этим в пакете от сервера подправишь RSA ключ
Насколько мне известно RSA работает 1-key буличный 2-других приватные, причем приватные простые а следовательно Public_key полупростое число.
Исходя из той рекомендации что ты даешь мне выше, самый первый пакет Init содержит именно Public_key RSA Который в свою очередь получит клиент разделит своим Private_key и получит еще один Private_key и потом им же и зашифрует весь отправляемый пакет.
Я все правильно понимаю?
К счастью у меня есть все приватные ключи сервера. В таком случаи мне непридется делать подмену?

Добавлено через 48 минут
Думал в l2phx.3.5.15.126 увижу как расшифровываются пакеты (LS), к сожалению в этой версии пакеты тоже неверно пока не расшифровываются. Хотя в (GS) можно увидеть логин

xkor
17.08.2009, 20:24
alexmarch, эт что за сервак такой странный что у тебя его ключи есть??, ключи на явах и офах генерируются новые при каждом запуске сервера...

ЗЫ на самом деле клиенту передаётся не весь ключ а только модуль, експонента всегда равна 65537

alexmarch
17.08.2009, 21:50
Cори за нюбство.
Бегло смотрел исходники в декампиленной яве.
И судорожно пытался понять где же та самая процедура что формирует пакет
увил кусок кода
private static final int KS0[] = {
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7,
0x801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0xd95748f, 0x728eb658, и т.д.
Почему то подумал RSA ключи. Хотя логичней их динамически создавать.
Тогда получается они в клиенте зашиты? Подругому же быть неможет :)

Еще вот такую штуку нашел
private static final long serialVersionUID = 0x3837333536303635L;

xkor
17.08.2009, 23:13
Тогда получается они в клиенте зашиты? Подругому же быть неможетты моё предыдущее сообщение внимательно прочитал?..

Yegor
17.08.2009, 23:17
alexmarch, слушай что xkor пишет - расшифровать логин и пасс можно только подложив в первом пакете клиенту свой RSA публичный ключ, больше никак.

alexmarch
18.08.2009, 00:35
Вы конечно дядки матерые и авторитетные. Я бы вас не дергал глупыми вопросами если бы на дельфи писал.(дав фиг с ним писал, хотя бы читал) Я может и осилю функцию может две. На свене сидел два дня. Так и не нашел. Ответ на свой вопрос. Тыкните меня носам в эту процедуру.
Это:
http://www.la2kings.ru/la2bot/packets.html#ProtocolVersion
а так же вот это
http://fursoffers.narod.ru/Packets.htm#Init
и все ветки что схожие с этой темой я по многу раз перечитал,
перед тем как вылести сюда тупить :)
Нет точного описания. Оно и понятно зачем оно надо когда есть исходники скопи-пастел и все ок :)
Буду дальше читать...
На этом спасибо. :)

xkor
18.08.2009, 00:56
alexmarch, надо уметь читать любой язык программирования и уметь переписать на свой любимый)
к тому же дельфи один из самых простых языков по синтаксису, его читать очень легко)

Yegor
18.08.2009, 01:37
alexmarch, по этим 2м ссылкам что ты привел лучше по поводу логин сервера читать можешь только для ознакомления, там куча ошибок.

Найди лучше тут где то был исходник l2emu, там как раз реализован коннект к логин серверу (к грации парт2 подходит), по нему можно посмотреть и реализовать.

alexmarch
18.08.2009, 11:39
Yegor - обязательно гляну
Очень хочется внести ясность по авторизации распаковки и подмене RSA ключа (LS)
Ща накопипастю.

В общих чертах авторизация на HB-Gracia происходит так:
1. Пакет от сервера размером 186 байт зашифрованный по BlowFish начальным 16тибайтным ключем
(ключ как в интерлюдии, наизусть его не помню), после дешифровки BF надо ещё дешифровать по XOR,
ключ для него находиться на месте чексуммы пакета (178-181 байты),
алгоритм дешифрации могу выложить когда домой приду...

В этом пакете с ID=0 следующий формат данных:
4 байта - session id
4 байта - ревизия протокола ($c621 вроде)
128 байт - RSA ключ заскремблированный (как дешифровать в нормальный ключ тож могу выложить)
16 байт - какие то GameGuard значения неизвестного назначения
16 байт - новый BF ключ для следующих пакетов
остальное нули...

Сначало пакет расXORим
procedure LoginXORDecrypt(var xpck: TFixPck);
var
i,k: Integer;
begin
i:=xpck.size-8; // узнаем номер первого байта ключа (186-8=178)
k:=PInteger(@xpck.ch[i])^; // записываем ключ в 4х байтовую переменную
while i>=6 do begin // пока позиция больше или равна 6
PInteger(@xpck.ch[i])^:=PInteger(@xpck.ch[i])^ xor k; // ксорим очередные 4 байта на ключ
k:=k-PInteger(@xpck.ch[i])^; // вычитаем из ключа то что получилось
i:=i-4; // перемещаемся к предыдущим 4м байтам
end;
end; // усё

короче тут не по одному байту ксорим а по 4,
хотя в яве наверно ксорят по одному ибо там сложности с приведением типов.
>Тогда такой вопрос, возможно даже глупый:
>Есть последовательность из 4 байтов, которые являются ключом.
>И чтобы мне эту последовательность записать в переменную типа int,
>надо эти 4 байта ключа перевести в число? Или как?

>>бля переменная int это и есть 4 байта, тупо их туда пишеш и всё,
>>ты что с памятью работать не умеешь?


потом заскремблируем RSA ключ


procedure deScrambleRSAKey(var raw);
var
ab: array[0..127] of Byte absolute raw;
i: Word;
b: Byte;
begin
for i:=0 to $3f do ab[$40+i]:=ab[$40+i] xor ab[i];
for i:=0 to $03 do ab[$0d+i]:=ab[$0d+i] xor ab[$34+i];
for i:=0 to $3f do ab[i]:=ab[i] xor ab[$40+i];
for i:=0 to $03 do begin
b:=ab[i];
ab[i]:=ab[$4d+i];
ab[$4d+i]:=b;
end;
end;

PFixPck = ^TFixPck;
TFixPck = packed record case Integer of
0:(ch: array[Word] of Char);
1:(bt: array[Word] of Byte);
2:(size: Word;
id: Byte;
dbt: array[0..65532] of Byte);
end;

alexmarch
18.08.2009, 11:43
Потом нам потребуется это для подмены
то что с ним делать и куда пихать пока неясно
Public: 65537
Private: 75827556252429569206429305205270821606264223799087 52381910705950070334735560292334593794066616085030 70414129295371522610749439915326514062579521313612 37504618942129346038375997183108947428183572534428 01325482875503123628608572472135307672677104600014 56633091612949350154767360996381796453159422636430 2807993
Module: 36003119279254340919233191155819994462144015323631 08779636904555891904133626131121729142083197988586 95397600460992273254659755442517958067950982310586 20765559861865193839298972977890750546282107564404 12981786522769558694223846132879431073562031333845 00748037521085932758932558205060546167314940714992 79307243


Добавлено через 59 секунд
для чего нам потребуется вот такая процедура
procedure LS_init(buff: array of byte; Len: integer);
begin
ToLog('********* LS_init ************');
ToLog('');
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);
ToLog('RSA Key changed');
end;
if Len>=171 then begin
SetLength(bf_key,16);
Move(buff[155],bf_key[1],16);
bf.Init(bf_key);
ToLog('BlowFish key changed');
end;
//sending AuthGG packet
AuthGameGuard;
end;

Где ошибся? :)

Yegor
18.08.2009, 14:55
alexmarch,
процедура procedure deScrambleRSAKey(var raw); ключ дескремблируе, а для подкладки своего ключа нужно написать функцию которая работает наоборот.

procedure LS_init(buff: array of byte; Len: integer); написана для получения ключа от сервера, да этот пакет нужно обработать и ключ от сервера запмнить он потом пригодится. Вот только после этого тебе нужно в этом пакете на место ключа сервера положить заскребмлированный свой public ключ Public: 65537, потом добавить новую чексумму, заксорить, заблоуфишить и отправить на клиент/бот.

Jes
25.08.2009, 16:21
вот вам на растерзание - вроди за два года логин сервер не менялси
int analyse(unsigned char*in,int size,bool direct,char *sender)
{
if (DEBUG)
printf("direction %s server\n",direct?"FROM":"TO");
if (DEBUG)
dump(in,size);
if (size==0xAB&&in[0]==0xAB&&!in[1]&&!in[2])
{
in[0]=0xBA;
size=0xBA;
in[7]=0x21;
in[8]=0xC6;
in[9]=0;
in[10]=0;
//const unsigned char code[]={0x4E,0x95,0xDD,0x29,0xFC,0x9C,0xC3,0x77,0x20,0xB 6,0xAD,0x97,0xF7,0xE0,0xBD,0x07};
if (RSA)
{
memcpy(serv_mod,in+11,128);
un_scrambleMod(serv_mod);
//ServRsa->setmod((char*)serv_mod,128,65537);
mpi_read_binary(&serv_rsa.N,serv_mod,128);
memcpy(in+11,my_mod,128);
}
encXORPass(in,2,0xBA,23545);
encode(in+2,0xBA-2,&keyIt_st);
if (DEBUG)
dump(in,size);
}
else
if(size==0x17&&in[0]==0x17&&!in[1]&&in[2]==0x0b)
{
size=0x22;
in[0]=0x22;
memset(in+0x17,0,0x22-0x17);
Checksum(in+2,size-2,true);
//dump(in,size);
encode(in+2,size-2,&keyIt);
if (DEBUG)
dump(in,size);
}
else
if(size==0x27&&in[0]==0x27&&!in[1]&&in[2]==0x03)
{
size=0x3A;
in[0]=0x3A;
memset(in+0x27,0,size-0x27);
Checksum(in+2,size-2,true);
//dump(in,size);
encode(in+2,size-2,&keyIt);
if (DEBUG)
dump(in,size);
}
else
if(size==0xB2&&in[0]==0xB2&&!in[1])
{
decode(in+2,size-2,&keyIt);
if (DEBUG)
dump(in,size);
if (RSA)
{
char paswd[128],pass[32],login[32];
memset(pass,0,sizeof(pass));
memset(login,0,sizeof(login));
//MyRsa->decrypt((char*)in+3,128,paswd,128);
// int len=128;
// rsa_pkcs1_decrypt( &my_rsa, RSA_PRIVATE, &len,in+3, (unsigned char*)paswd );
rsa_private(&my_rsa,in+3, (unsigned char*)paswd);
memcpy(login,paswd+0x5E,14);
memcpy(pass,paswd+0x6C,16);
logins[login]++; // -)
for(int i=0;pass[i];pass[i++]='*');
print_time();
autoban[sender]=0;
printf("login :%s password:%s logins=%d\n",login,pass,logins.size());
append_log(login,sender);
store_info();
if (DEBUG)
dump((unsigned char*)paswd,128);

//ServRsa->encrypt(paswd,128,(char*)in+3,128);
//rsa_pkcs1_encrypt(&serv_rsa,RSA_PUBLIC,128,(unsigned char*)paswd,in+3 );
rsa_public(&serv_rsa,(unsigned char*)paswd,in+3 );
Checksum(in+2,size-2-12,true);
if (DEBUG)
dump(in,size);
}
encode(in+2,size-2,&keyIt);
if (DEBUG)
dump(in,size);

}
else
if(DEBUG)
{
unsigned char dmp[2048];
memcpy(dmp,in,size);
decode(dmp+2,size-2,&keyIt);
dump(dmp,size);
}

return size;
}

Jes
25.08.2009, 16:28
остальное тут http://lt.rv.ua/phpbb3/viewtopic.php?f=5&t=112