PDA

Просмотр полной версии : Чат-Клиент для java-сервера Lineage II


Tin-moon
06.02.2012, 22:53
Добрый день вот решил написать чат-клиент для сервера. Поскольку работать плотно с java-серверами л2 не приходилось, то возникла проблема такого характера: нужна помощь, подсказки по работе обмена данными между клиентом и сервером (пакеты входа в игру и сам чат). Кто может подсказать, что можно общего почитать на эту тему, лучше конкретно к л2. Или может, у кого есть какие наработки?
Нашел только пару статей по структуре пакетов, к сожелению там только С4 и С6. Кто может описать структуру к более новым хроникам? Возможно ли выдрать это из исходников сервера?
Буду благодарен за помощь.

supernewbie
06.02.2012, 23:48
смотри сорцы л2пх для гс и l2emu для лс

Tin-moon
06.02.2012, 23:59
смотри сорцы л2пх для гс и l2emu для лс
л2пх - тут же только перехват пакетов или я не прав
l2emu - где конкретно смотреть у них последнии сорцы (http://l2emu.googlecode.com/svn) под какой клиент (эпилог)?
Я пробовал смотреть l2jserver-a чет как-то запутано..
И непонятно структура (если она конечно не поменялась с http://fursoffers.narod.ru/Packets.htm) описания.

Kilatif
07.02.2012, 00:08
Я когда писал пользовался только l2emu и http://fursoffers.narod.ru/Packets.htm

Там есть все что тебе нужно

Tin-moon
07.02.2012, 00:24
Я когда писал пользовался только l2emu и http://fursoffers.narod.ru/Packets.htm

Там есть все что тебе нужно

А что ты писал если не секрет?

goodvin1709
07.02.2012, 16:48
Что именно ты хочешь сделать чтобы он сам заходил(типа ООГ) и сканил чат?
или просто прикручивался к даному клиенту и просто туда выводилось все?

Tin-moon
09.02.2012, 00:51
Что именно ты хочешь сделать чтобы он сам заходил(типа ООГ) и сканил чат?
или просто прикручивался к даному клиенту и просто туда выводилось все?
Да чтобы сам заходил.

Почитал тут http://coderx.ru/showthread.php?t=670 - там ести рабочий прмер но на делфи... ). В делфи 0. Мб что-нибудь похожее есть на яве или с++ ?

Добавлено через 23 часа 10 минут
Взял как и посоветовали l2emu сервер. Потихоньку разбираюсь что к чему. Там есть функции по чтению и записи (как понял частей пакета), например readD(), readH() ну и тп. Их как нибудь можно использовать? Если чесно немного не понял как с ними работать.
Вопрос по прмеру из той темы про которую отписывал раньше. В Delphi есть процедура procedure Move ( const SourcePointer; var DestinationPointer; CopyCount : Integer ) ; которую в примере часто используют. Есть ли замена на Яве? Ща пробовал ее реализовать сам но хз верно или нет, гляньте кто может подсказать:

private static int _4btoi(byte[] b, int offset){
int i = 0;
for (int t = 0; t < 4; ++t)
i |= (int)b[offset + t] << (8 * t);
return i;
}

private static void ito4b(int i, byte[] b, int offset){
for (int t = 0; t < 4; ++t){
b[offset+t] = (byte)(i & 0xFF);
i >>= 8;
}
}

Kilatif
09.02.2012, 01:32
Move - это аналогия copymem в cи

Tin-moon
09.02.2012, 01:38
Move - это аналогия copymem в cи
Это понятно, но ява напрямую к памяти не доступается к сожелению).
Еще появился вопрос, как это переписать : Move(buff[155],bf_key[1],16); ?

Kilatif
09.02.2012, 03:22
Move(buff[155], bf_key[1], 16) - копирует из buff, начиная с 155 ячейки в bf_key начиная с 1 ячейки 16 байт

Tin-moon
09.02.2012, 23:05
Возникла проблема вот с этим:

function RSAEncrypt(a,p,rsakey:string):string;
var
sD,sR,sM:string;
m,e,d,r:TFGInt;
begin
if length(a)>14 then setlength(a,14);
while length(a)<14 do a:=a+#0;
if length(p)>16 then setlength(p,16);
while length(p)<16 do p:=p+#0;
sD:=a+p+#0#0#0#0;
sM:=rsakey;
Base10StringToFGInt('65537',e);
Base256StringToFGInt(sD,d);
Base256StringToFGInt(sM,m);
FGIntMontgomeryModExp(d,e,m,r);
FGIntToBase256String(r,sR);
result:=sR;
end;

как переписать отделавшись легким испугом?? Лучше конечно использовать ява функции.

Тут получатся, что шифруется блок "логин+пароль", или отдельно каждое потом записываются в соответствующие места?

Kilatif
10.02.2012, 01:48
Наверное самое трудно переносимое из одного языка в другой =) Потому что используется тут большие числа и в каждом языке разные модули для этого. Конкретно что делает процедура:


function RSAEncrypt(a,p,rsakey:string):string;
var
sD,sR,sM:string;
m,e,d,r:TFGInt; //это переменные для работы с большими числами
begin
if length(a)>14 then setlength(a,14); //если логин > 14 символов обрезаем
while length(a)<14 do a:=a+#0; //доводим логин до 14 символов

if length(p)>16 then setlength(p,16); //если пароль > 16 символов, обрезаем
while length(p)<16 do p:=p+#0; //доводим пароль до 16 символов

sD:=a+p+#0#0#0#0; //записывается логин+пароль+4 нулевых байт для нужного размера
sM:=rsakey;
Base10StringToFGInt('65537',e); //инициализируем e числом 65537
Base256StringToFGInt(sD,d); //инициализируем d "числом" sD
Base256StringToFGInt(sM,m); //аналогично
FGIntMontgomeryModExp(d,e,m,r); //выполняется операция r = (d^e) mod m
FGIntToBase256String(r,sR); //переводится r в sR
result:=sR; //PROFIT
end;


т.е. получается что да, шифруется сразу блок логин + пароль.

Tin-moon
10.02.2012, 02:25
FGIntToBase256String(r,sR); //переводится r в sR

Переводится каким способом? Или просто копируется?

Kilatif
10.02.2012, 02:33
FGIntToBase256String(r,sR); //переводится r в sR

Переводится каким способом? Или просто копируется?

sR - массив байт
допустим r = 0xAABBCCDDEEFF11223344
тогда sR = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44} (порядок записи в массив может будет задом наперед, я точно не помню)

Tin-moon
10.02.2012, 14:55
Дошел до переписывания BlowFish.
Возникла проблема с типами данных...

Кто может подсказать BlowFish.pas и BlowfishEngine.java делают одно и тоже? Или придется еще чего дописывать? (во вложении 2 файла)

Возник вопрос, что можно позаимствовать у l2emu сразу их исходников, у них вроде есть много чего похожего, но сильно все запутано :)

Kilatif
10.02.2012, 16:18
Внешне вроде очень похоже ) Единственное что в BlowfishEngine.java не нашел аналогий функциям bfDecode и bfEncode Видимо их придется дописывать

Tin-moon
10.02.2012, 16:43
Внешне вроде очень похоже ) Единственное что в BlowfishEngine.java не нашел аналогий функциям bfDecode и bfEncode Видимо их придется дописывать

Они походу есть в других классах, аля логин_крипт, нью_логин_крипт, и бФ_кейген. Сори за русский английский спешил). Только опять же непонятно подойдут эти функции или нет.

Kilatif
10.02.2012, 19:34
Tin-moon, ты проверь. Если конечно хоть каплю знаешь Delphi. Проверь как работает то и то при одинаковых условиях и все тогда станет ясно

Tin-moon
11.02.2012, 14:14
Kilatif помоги понять что тут происходит? :)

MAX_PKT_SIZE=$FFFF;
FillChar(main_buff,Length(main_buff),0); // заполнить буфер 0
Len:=recv(RS_Sock,main_buff,MAX_PKT_SIZE,0); // я так понимаю пишем в буфер но зачем размер MAX_PKT_SIZE, но Len чему будет равно??
inc(RecvPktCount); // +1
LS_parser(main_buff,Len); // тут непонятно чему будет равна длина??


Первый приходящий пакет 186


procedure 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); // вот это критично.. что тут происходит
bf.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];
//Move(s[1],temp[0],Length(s));
end;
Move(temp[0],buff[2],Len-2);
end;

Пробую уже работать, пока валится наверно из-за Move

supernewbie
11.02.2012, 14:24
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx
насчёт move - аналог arraycopy в яве вроде

Tin-moon
11.02.2012, 14:34
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx
насчёт move - аналог arraycopy в яве вроде

Дакументацию я читал, там просто очень много вариантов...
arraycopy ща гляну. Проблема в том (покрайней мере для меня) что он все время перемещает разные типы данных, например:
Move(Len,send_buff[0],2);
Move(buff[0],send_buff[2],Len-2);
Move(data[0],xld,4);
Move(DBuff,data[i*8],8);
Move(data[i*8],DBuff,8);
...

Я просто думаю что цифра procedure Move(const Source; var Dest; Count: Integer); count это тип данных.

Можешь привети пример перевода используя arraycopy, ну хотябы для тех которые я написал?

Kilatif
11.02.2012, 15:24
Len:=recv(RS_Sock,main_buff,MAX_PKT_SIZE,0);
Len = кол-ву байт пакета, которое придет на сокет, поэтому использовать это значение не всегда правильно.
Правильно читать пакет нужно следующим образом:
1) Считываем первые 2 байта пакета с сокета (сервер в этих двух байтах присылает полный размер пакета)
2) Далее считываем данные с сокета до тех пор, пока мы не считаем столько, сколько было указано в тех самых двух байтах минус 2 байта
Например пакет:
0x07 0x00 0xAA 0xBB 0xCC 0xDD 0xFF

Полный размер пакета = 7 байт
Данные пакета = 5 байт
Сначала считываем первых 2 байта и получаем размер 7 байт
А потом считываем Данные пакета, т.е. 7 - 2 = 5 байт

насчёт move - аналог arraycopy в яве вроде
Ну не совсем мне кажется.. Вся фигня в том, что move - Работает непосредственно с памятью, поэтому если переводить из масива байт в массив интов, то он переведет не поэлементно, а по памяти (0xAA, 0xBB, 0xCC, 0xDD переведет в 0xAABBCCDD, а не в 0x000000AA, ... ...), а вот arraycopy переведет из массива байт в массив интов именно поэлементно

Move(Len,send_buff[0],2);
Move(buff[0],send_buff[2],Len-2);
Move(data[0],xld,4);
Move(DBuff,data[i*8],8);
Move(data[i*8],DBuff,8);

На яве примеры привести не смогу, приведу на C# (ИМХО самый близкий к яве)

Пусть есть такие данные:
byte[] buff = new byte[20];
byte[] data = new byte[20];
int Len;
int xld;
byte[] DBuff = new byte[20];

Тогда:
1) Move(Len,send_buff[0],2)
Array.Copy(BitConvert.GetBytes((Int16)Len), 0, send_buff, 0, 2);

byte[] BitConvert.GetBytes(Int16 value) - переводит 16-битное число value в массив байт
BitConvert.GetBytes((Int16)Len) - т.к. Len = 4 байт, мы приводим тип к Int16 (к двум байтам), потому что скопировать нам надо 2 байта

2) Move(buff[0],send_buff[2], Len-2)
Array.Copy(buff, 0, send_buff, 2, Len-2)

3) Move(data[0],xld,4);
xld = BitConvert.ToInt32(data, 0); // переводит из массива байт data в 32-битное число начиная со смещения 0

4) Move(DBuff,data[i*8],8);
Array.Copy(DBuff, 0, data, i*8, 8);

5) Move(data[i*8],DBuff,8);
Array.Copy(data, i*8, DBuff, 0, 8);

Я просто думаю что цифра procedure Move(const Source; var Dest; Count: Integer); count это тип данных.
Не совсем так
Count - количество байт, которое будет копироваться
Иногда оно совпадает с типом данных (Пример 3)
Иногда это просто скопировать из одного массива в другой несколько байт (Пример 2, 4, 5)
Иногда оно будет меньше чем тип, из которого мы копируем (Пример 1)

Т.к. в яве нет операция для манипуляций с памятью на прямую (коих в c# я тоже не нашел), то нужно использовать манипуляции с массивами, но для этого четко нужно представлять как они устроены в памяти и как работает процедура Move и иже с ними

Tin-moon
11.02.2012, 15:46
2) Move(buff[0],send_buff[2], Len-2)
Array.Copy(buff, 0, send_buff, 2, Len-2)

Иногда это просто скопировать из одного массива в другой несколько байт (Пример 2, 4, 5)


Получается тут копируется из buff начиная с 0 до Len-2 в send_buff начиная со 2??

Явовский делает вот такое:
char[] copyFrom = { '0', '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0', '0', '0' };
char[] copyTo = {'1','1','1','1','1','1','1'};

// копируем со 2 элемента - 6 штук в copyTo с 0
System.arraycopy(copyFrom, 2, copyTo, 0, 6);
System.out.println(new String(copyTo));

итог = 0000001

Чет я начал находить + в C# ) тут тебе и ансигн и прочее)

Kilatif
11.02.2012, 16:07
Получается тут копируется из buff начиная с 0 до Len-2 в send_buff начиная со 2??
Нет, не с 0 до Len-2, а c нуля Len-2 штук
Вот как в твоем примере, он начал со второго и скопировал 6 штук

Tin-moon
11.02.2012, 16:16
Нет, не с 0 до Len-2, а c нуля Len-2 штук
Вот как в твоем примере, он начал со второго и скопировал 6 штук

т.е. для 2 случая делается одинаково (java and C#)?
Слушай я тебя наверно уже достал, но не мог бы ты взять мои данные и прогнать на тех примерах которые ты написал, ну инт задай какой-нибудь. Если кончено не подтер уже :), а то еще С# устанавливать уже места нема)

Kilatif
11.02.2012, 17:48
т.е. для 2 случая делается одинаково (java and C#)?

Судя по описанию arraycopy() для ява, да)


Слушай я тебя наверно уже достал, но не мог бы ты взять мои данные и прогнать на тех примерах которые ты написал, ну инт задай какой-нибудь. Если кончено не подтер уже :), а то еще С# устанавливать уже места нема)
Какие данные?

Tin-moon
11.02.2012, 18:00
Какие данные?

char[] copyFrom = { '0', '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0', '0', '0' };
char[] copyTo = {'1','1','1','1','1','1','1'};

int len = 186;
И прогнать по тем примерам что ты написал, распечать (формат я думаю важен).
А я сравню с тем что ява выведет.

Возник еще мальнький вопросик, в яве нет unsigned.. а в делфи некоторые данные в unsigned, я вот думаю мне хватит впилить в sign формат? Смотрел в сервере там long почти не используют... предположу, что все в int.


to Kilatif :Видел тему где ты бота начинал писать, поидее были примерно такие же проблемы. Дописал до чего толькового или кинул?

Kilatif
11.02.2012, 22:38
char[] copyFrom = { '0', '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0', '0', '0' };
char[] copyTo = {'1','1','1','1','1','1','1'};

int len = 186;
И прогнать по тем примерам что ты написал, распечать (формат я думаю важен).
А я сравню с тем что ява выведет.


1 Пример
byte[] copyFrom = new byte[13] { 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
byte[] copyTo = new byte[7] {1, 1, 1, 1, 1, 1, 1};

int len = 186; // 0x000000BA

Array.Copy(BitConverter.GetBytes((Int16)len), 0, copyTo, 0, 2);
//Результат:
//copyTo = {0xBA, 0x00, 1, 1, 1, 1, 1}

2 Пример
byte[] copyFrom = new byte[13] { 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
byte[] copyTo = new byte[7] {1, 1, 1, 1, 1, 1, 1};

int len = 3;

Array.Copy(copyFrom, 0, copyTo, 2, len)
//Результат:
//copyTo = {1, 1, 0, 0, 0, 1, 1}

3 Пример
byte[] copyFrom = new byte[13] { 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
byte[] copyTo = new byte[7] {1, 1, 1, 1, 1, 1, 1};

int xld;

xld = BitConvert.ToInt32(copyTo, 0); //Move(copyTo[0],xld,4);
//Результат:
//xld = 0x01010101
4 Пример аналогичен второму
5 Пример так же аналогичен второму


Возник еще мальнький вопросик, в яве нет unsigned.. а в делфи некоторые данные в unsigned, я вот думаю мне хватит впилить в sign формат? Смотрел в сервере там long почти не используют... предположу, что все в int.

signed, unsigned приставка никак не влияет на размер переменной, эта приставка влияет только на то, будет ли у переменной отрицательные значения . Например:
unsigned int x // размер 4 байт, но вмещает в себя от 0 до 4294967295
signed int x // размер 4 байт, но вмещает в себя от -2147483647 до -2147483647



to Kilatif :Видел тему где ты бота начинал писать, поидее были примерно такие же проблемы. Дописал до чего толькового или кинул?

Да, доходил до Enter World и забрасывал :D Дальше все легко получается. Вот сейчас пишу на C#, тоже дошел до Enter World и теперь парсирую нужные мне пакеты

Примеры напишу позже

Kilatif
12.02.2012, 19:54
Вот мой класс BlowFish На C#

Tin-moon
13.02.2012, 00:53
Вот мой класс BlowFish На C#

Спасибо, все-таки с С# переписывать удобнее :)

Падает на этой функции:

private long S(long x, byte i)
{
byte[] bts = new byte[4];

bts = BitConverter.GetBytes(x);
return SBoxes[i, bts[3-i]];
}

Проблема в чем: С# выдает {3, 169, 95, 79, 0, 0, 0, 0}, а ява {3, -87, 95, 79, 0,0,0,0}. Понятное дело что нет в массиве такого числа. Кто знает как эту проблему решить?


Вроде решил:

int j = 0;
if(bts[3-i] < 0){
j = HelpFunctions.UB2I(bts[3-i]);
}
else{
j = bts[3-i];
}
return SBoxes[i][j];

подменяю отрицательные.
Проблема теперь в другом:
Массивы Parray и SBoxes после Init содержат только 0. Хотя в отладке вроде заполняются.

Kilatif
13.02.2012, 01:22
Спасибо, все-таки с С# переписывать удобнее :)

Падает на этой функции:

private long S(long x, byte i)
{
byte[] bts = new byte[4];

bts = BitConverter.GetBytes(x);
return SBoxes[i, bts[3-i]];
}

Проблема в чем: С# выдает {3, 169, 95, 79, 0, 0, 0, 0}, а ява {3, -87, 95, 79, 0,0,0,0}. Понятное дело что нет в массиве такого числа. Кто знает как эту проблему решить?

число 169 и -87 в двоичном представлении (и в шестнадцатеричном) в первом байте одно и тоже (169 = 0x000000A9; -87 = 0xFFFFFFA9), отличается только знаком. Скорее всего вся проблема в том что элементы твоего массива размером больше чем 1 байт, поэтому при чтении пакета и работы с однобайтовыми элементами, добавляются FF. И если я не ошибаюсь, особо это не влияет на работу с пакетами. И мой тебе совет, просматривай числа в шестнадцатеричном режиме =)

Tin-moon
13.02.2012, 01:43
число 169 и -87 в двоичном представлении (и в шестнадцатеричном) в первом байте одно и тоже (169 = 0x000000A9; -87 = 0xFFFFFFA9), отличается только знаком. Скорее всего вся проблема в том что элементы твоего массива размером больше чем 1 байт, поэтому при чтении пакета и работы с однобайтовыми элементами, добавляются FF. И если я не ошибаюсь, особо это не влияет на работу с пакетами. И мой тебе совет, просматривай числа в шестнадцатеричном режиме =)

Проблема в том что реализация немного разная. Байт в C# 0..255, а в java -128..127. И еще один здоровенный гемор, то что порядок следования байт в C# {3, 169, 95, 79, 0, 0, 0, 0}, а в java {0,0,0,0, 79, 95, -87, 3}. И помоему это значительно портит мне жизнь). Походу в делфи тоже порядок {3, 169, 95, 79, 0, 0, 0, 0} и байт 0..255.

Kilatif
13.02.2012, 02:08
что касается последовательности байт, это где такая у тебя последовательность, я что то не понял? А что касается разных реализаций типа байт, я же говорю - смысл для байта в двоичном и шестнадцатеричном представлении от этого не меняется

Tin-moon
13.02.2012, 11:12
что касается последовательности байт, это где такая у тебя последовательность, я что то не понял? А что касается разных реализаций типа байт, я же говорю - смысл для байта в двоичном и шестнадцатеричном представлении от этого не меняется

private long S(long x, byte i)
{
byte[] bts = new byte[4];

bts = BitConverter.GetBytes(x);
return SBoxes[i, bts[3-i]];
}

Вот тут такая последовательность. Понимаешь тут смысл в чем, оно выбирает из bts числа (которые там получились) bts[3-i] - это число {3, 169, 95, 79, 0, 0, 0, 0}. И в массиве SBoxes выбирает число. Понятное дело что оно не может быть отрицательным. Ща попробую запилить в яве не в байт а в short и глянуть какие данные будут.
Кстати, чисто для сверки, выкинь полученные Parray и SBoxes из BlowFish.Init(key), ключ тоже подсунь.

Kilatif
13.02.2012, 13:59
private long S(long x, byte i)
{
byte[] bts = new byte[4];

bts = BitConverter.GetBytes(x);
return SBoxes[i, bts[3-i]];
}

Вот тут такая последовательность. Понимаешь тут смысл в чем, оно выбирает из bts числа (которые там получились) bts[3-i] - это число {3, 169, 95, 79, 0, 0, 0, 0}. И в массиве SBoxes выбирает число. Понятное дело что оно не может быть отрицательным. Ща попробую запилить в яве не в байт а в short и глянуть какие данные будут.
Кстати, чисто для сверки, выкинь полученные Parray и SBoxes из BlowFish.Init(key), ключ тоже подсунь.

для bts[3-i], 3-i - никогда и не будет отрицательным, потому что в моем классе значение i > 3 нигде не используется.

Что касается записи числа в массив.
Вообще, в процессорах Intel используется обратная запись числа, поэтому в пакетах тебе приходит массив с числами, которые записаны задом наперед. И видимо поэтому C# и Delphi переводит число в массив именно задом наперед. И то что ява переводит так число в массив действительно беда, но это уже врятли исправишь. Хотя.. Я яву не знаю, так что может просто есть другая функция для этого)

Tin-moon
13.02.2012, 14:05
для bts[3-i], 3-i - никогда и не будет отрицательным, потому что в моем классе значение i > 3 нигде не используется.

так верно i проходит от 0 до 3. Тут просто берется значение которые попало под этот индекс (3-i), а вот там уже с -)). В общем с блоу фишем вроде разобрался. сравнил с Делфой).

Проблема теперь в другом... пакет который приходит 186, но данные другие от делфи).

P.S. У меня еще столько IDE никогда не стояло)) QT, Java-ские, C#, Delphi 7 :confused:

Kilatif
13.02.2012, 14:44
Проблема теперь в другом... пакет который приходит 186, но данные другие от делфи).

Так он и будет приходить разный) Он будет приходить всегда разный, потому что каждый раз в нем приходят разные RSA-key, SessionID и BlowFishKey )

ErgoZ
13.02.2012, 16:13
У меня другая проблема)) я запутался немного.
Тоже пишу на яве чат-клиент. Так как я запутался, скажите правильно ли я думаю:

Подключаюсь к серверу и получаю примерно такой пакет:

02-13 10:34:04.991: I/System.out(472): BA00D139D82F2A4002CCFF622488E4B92F4D8C9FD87DFFA459 92F106EEE2E80ECB58A8545471CE687B6CDA41D9245B611BB0 2A17E29CC8FFE881B2921E48685738E3E933CD655849B8FCED 69150E4612BB2061BBB5C6C2E8DC2E406F714F6E5EEFD3B99C 66A6D72492A61832D4B574F8120156AE8175A46C14274B78F8 7AECB50C8FFD2CF4AEE6E63BE19F8C0F6F2E34907CAEC62768 AAB6D45DDF13D2DBC90B877D48CE68610756087308564ECDC5 1124174228D4EC14701414

Далее отсекаю у него размер пакета (ba00) и получившийся пакет без первых 2 байт я должен декодить по блоуфишу с начальным ключём, правильно?
Тогда я получаю:

02-13 10:34:05.021: I/System.out(472): 4580A1F93794E8BC6B523C3B95239FD1530F626B0574949395 E97080C912DBB2F872AE1847A8717CB6D5D882FFC7856363FB 8ECC3014FF634B639CE48622886AE51F15DF43DB777542FEA3 BBA1869AA055DEEFF1798BA6277B73F0D39F6894E02B474CDA 22436B8CA29D43218CF5AA6F34EC28497854E0E1D12601FAFA A01B328308722E1B10570299F03C51727BCDC451B69A894B99 1C8B0C145E9DD8D62B49F82B2D62EAD85F0CE4F6B78188BB45 44C5B149F46A39D21423EF


Дальше я по идее должен получить ключ для XOR, т.е. взять 178-181 байты (из оставшихся 184, т.к. отрезал 2 байта размера), или другие, если допустим не считать уже отрезанные 2 байта размера? Вот тут я не понимаю, запутался. Просто xkor тут такие значения писал http://coderx.ru/showpost.php?p=30849&postcount=53

Какие всё таки байты брать для ключа ксора?
Правильно ли я понимаю что ксорить надо будет по 4 байта начиная с первого и заканчивая размером пакета минус размер ксор ключа (т.е. 4 байта).

Ещё загвоздка в том, что не могу найти описание того как ксорить на яве, я так понял через символ ^, но он ругается на то что его нельзя использовать с типом byte, в котором у меня пакет и ключ. Где можно найти инфу по этому поводу? в исходниках серва не смог более менее путное найти.


Сильно не пинайти, кодить на яве начал неделю назад.

Kilatif
13.02.2012, 16:44
ErgoZ, что бы долго не писать, сразу пришлю код =) (C#)


public static byte[] AntiXor(byte[] s)
{
long key, b;
int i;
byte[] b_temp;

b_temp = new byte[4];

i = s.Length - 8;

key = BitConverter.ToInt32(s, i);
while (i >= 7)
{
i = i - 4;
b = BitConverter.ToInt32(s, i);
b = b ^ key;
key = key - b;

Array.Copy(BitConverter.GetBytes((Int32)b), 0, b_temp, 0, 4);
Array.Copy(b_temp, 0, s, i, 4);
}

return s;
}

ErgoZ
13.02.2012, 17:02
в эту ф-цию подставляем пакет с размером или без него? с типом пакета или без него?

Kilatif
13.02.2012, 17:10
ErgoZ, только без размера пакета.

ErgoZ
13.02.2012, 17:16
Спасибо большое, переписал под яву, ща буду пробовать :)

Winners
13.02.2012, 18:55
Если я правильно понял то ты хочешь программу на манер вот этой (http://lineage-cheats.3dn.ru/load/lineage_2/programmy_dlja_lineage_2/8-1-0-129) Увы это единственный ресурс где я смог ее найти пользовался ею оч давно еще под интерлюд. Позже она перестала обновлятся и так проект канул в летах. Не знаю есть ли возможность найти исходники или переделать эиу но вобщем посмотреть что за зверь можна.

ErgoZ
13.02.2012, 20:13
да, я пишу аналог этой софтины, но под явой. Чисто для себя под андроид. :)

Kilatif, странно работает антиксор который ты написал... особенно странно для меня:
key = key - b; - зачем из ключа вычитать весь пакет?
Array.Copy(BitConverter.GetBytes((Int32)b), 0, b_temp, 0, 4); тут тоже не совсем понятно что это делает, у нас ведь в итоге весь пакет получается 4 байтным в итоге, разве нет?

Или может я криво переписал это дело под андроид? просто на яве нет бит ковертера))) пришлось гуглить аналоги, нашёл пару функций:


public static int ToInt32(byte[] bytes, int offset) {
int ret = 0;
for (int i=0; i<4 && i+offset<bytes.length; i++) {
ret <<= 8;
ret |= (int)bytes[i] & 0xFF;
}
return ret;
}


public static byte[] toBytes(long val, boolean bigEndian)
{
byte[] res = new byte[8];
if (bigEndian)
{
res[0] = (byte)(val>>56&0xFF);
res[1] = (byte)(val>>48&0xFF);
res[2] = (byte)(val>>40&0xFF);
res[3] = (byte)(val>>32&0xFF);
res[4] = (byte)(val>>24&0xFF);
res[5] = (byte)(val>>16&0xFF);
res[6] = (byte)(val>>8&0xFF);
res[7] = (byte)(val&0xFF);
} else
{
res[7] = (byte)(val>>56&0xFF);
res[6] = (byte)(val>>48&0xFF);
res[5] = (byte)(val>>40&0xFF);
res[4] = (byte)(val>>32&0xFF);
res[3] = (byte)(val>>24&0xFF);
res[2] = (byte)(val>>16&0xFF);
res[1] = (byte)(val>>8&0xFF);
res[0] = (byte)(val&0xFF);
}
return res;
}


в итоге у меня на выводе после антиксора: [B@40538170
не понимаю где косяк :( а так хочется чат на андроиде иметь)))

Tin-moon
13.02.2012, 21:59
Если я правильно понял то ты хочешь программу на манер вот этой (http://lineage-cheats.3dn.ru/load/lineage_2/programmy_dlja_lineage_2/8-1-0-129) Увы это единственный ресурс где я смог ее найти пользовался ею оч давно еще под интерлюд. Позже она перестала обновлятся и так проект канул в летах. Не знаю есть ли возможность найти исходники или переделать эиу но вобщем посмотреть что за зверь можна.
Эта программа работает по другому принципу, там перехват API функций клиента, насколько я помню.

Добавлено через 1 минуту

Подключаюсь к серверу и получаю примерно такой пакет:

02-13 10:34:04.991: I/System.out(472): BA00D139D82F2A4002CCFF622488E4B92F4D8C9FD87DFFA459 92F106EEE2E80ECB58A8545471CE687B6CDA41D9245B611BB0 2A17E29CC8FFE881B2921E48685738E3E933CD655849B8FCED 69150E4612BB2061BBB5C6C2E8DC2E406F714F6E5EEFD3B99C 66A6D72492A61832D4B574F8120156AE8175A46C14274B78F8 7AECB50C8FFD2CF4AEE6E63BE19F8C0F6F2E34907CAEC62768 AAB6D45DDF13D2DBC90B877D48CE68610756087308564ECDC5 1124174228D4EC14701414


Как ты читаешь? Лучше код в студию)

ErgoZ
13.02.2012, 23:07
На сколько я помню, то нет. т.к. клиент не нужно запускать при той проге, поэтому о перехвате не может идти речи. Да и на делфях проще написать коннекты, чем перехватом заниматься.

читаю стандартными функциями явы и андроида, для примера:

la2_socket.connect(adr, 3000);
System.out.println("Connected to "+AddrAsIAddr+":"+_port);
byte buf[] = new byte[186];
int r = la2_socket.getInputStream().read(buf);


в переменную r записывается размер пакета, а в бафе хранится сам пакет.

Kilatif
14.02.2012, 01:09
key = key - b; - зачем из ключа вычитать весь пакет?
мы не вычитаем весь пакет, пакет же у тебя 184 байта, а значение b - 4 байта. какой же это весь пакет? Видимо действительно ты где-то ошибся..

Array.Copy(BitConverter.GetBytes((Int32)b), 0, b_temp, 0, 4);
BitConverter.GetBytes((Int32)b) - переводит число в массив
Array.Copy(mass_1, off_1, mass_2, off_2, count) - копирует из массива mass_1 начиная с off_1 в массив mass_2, начиная с off_2 количество значений = count. Посмотри пару страниц назад я кучу примеров по этому приводил

Tin-moon
14.02.2012, 01:20
To Kilatif :
Дошел до LS_init.

procedure 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);
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;

bf.Init(bf_key); - это новая инициализация? или переинициализация в начале ? И вообще с какой нужно работать дальше? или с обееми?

Kilatif
14.02.2012, 01:26
Tin-moon, первый пакет от логин-сервера приходит зашифрованный BlowFish-ем и Xor-ом. В нем приходит новый ключи BlowFish-а, которым будут шифроваться все следующие пакеты логин-сервера, при это Xor-ом шифроваться они не будут

Tin-moon
14.02.2012, 01:29
Tin-moon, первый пакет от логин-сервера приходит зашифрованный BlowFish-ем и Xor-ом. В нем приходит новый ключи BlowFish-а, которым будут шифроваться все следующие пакеты логин-сервера, при это Xor-ом шифроваться они не будут

Т.е. в дальнейшем мы будем пользоваться этим (который получим в LS_init) ?

Kilatif
14.02.2012, 01:36
Tin-moon, да

ErgoZ
14.02.2012, 01:45
нашёл пару косяков, переписал функции...

Вот функцию переписал с вышеуказанной:
public static byte[] AntiXor(byte[] s)
{
long key, b;
int i;
byte[] b_temp;

b_temp = new byte[4];

i = s.length - 8;

key = ToInt32(s, i);
while (i >= 7)
{
i = i - 4;
b = ToInt32(s, i);
b = b ^ key;
key = key - b;

System.arraycopy(toBytes(b, true), 0, b_temp, 0, 4);
System.arraycopy(b_temp, 0, s, i, 4);
}

return s;
}


Функция конверта из лонга в байты:
public static byte[] toBytes(long val, boolean bigEndian)
{
byte[] res = new byte[8];
if (bigEndian)
{
res[0] = (byte)(val>>56&0xFF);
res[1] = (byte)(val>>48&0xFF);
res[2] = (byte)(val>>40&0xFF);
res[3] = (byte)(val>>32&0xFF);
res[4] = (byte)(val>>24&0xFF);
res[5] = (byte)(val>>16&0xFF);
res[6] = (byte)(val>>8&0xFF);
res[7] = (byte)(val&0xFF);
} else
{
res[7] = (byte)(val>>56&0xFF);
res[6] = (byte)(val>>48&0xFF);
res[5] = (byte)(val>>40&0xFF);
res[4] = (byte)(val>>32&0xFF);
res[3] = (byte)(val>>24&0xFF);
res[2] = (byte)(val>>16&0xFF);
res[1] = (byte)(val>>8&0xFF);
res[0] = (byte)(val&0xFF);
}
return res;
}


из байта в лонг переделываю этой функцией:
public static int ToInt32(byte[] bytes, int offset) {
int ret = 0;
for (int i=0; i<4 && i+offset<bytes.length; i++) {
ret <<= 8;
ret |= (int)bytes[i] & 0xFF;
}
return ret;
}



Вот результат:

Пакет который приходит изначально от сервера - 02-13 20:32:09.911: I/System.out(1637): BA004511EBAFFAAAEB7F8AD5BC3F38CA9FD86156CC6D1DCB26 D5E7A5E497D87BADA3256418297DAAA0F2CA8593B92856517D 40C9D6A7462C9DBB73788F19AC9922A276C97674674D431937 51512DC07D32013B92622D2291AA98EE1AB649ABFEDC711A56 BC64061EA4537BC5088B1663B7B6CF2578AC926282F4645202 924C5B406B64C73B2CD35F1C01EC8091601F37E1297B1D79AE A1B44FFC2FC470AF431E213EB23C72E16484C99DF9200FC7E0 5EC44E94F072BE45B7620D

Пакет в котором я отсёк размер пакета - 02-13 20:32:09.921: I/System.out(1637): 4511EBAFFAAAEB7F8AD5BC3F38CA9FD86156CC6D1DCB26D5E7 A5E497D87BADA3256418297DAAA0F2CA8593B92856517D40C9 D6A7462C9DBB73788F19AC9922A276C97674674D4319375151 2DC07D32013B92622D2291AA98EE1AB649ABFEDC711A56BC64 061EA4537BC5088B1663B7B6CF2578AC926282F4645202924C 5B406B64C73B2CD35F1C01EC8091601F37E1297B1D79AEA1B4 4FFC2FC470AF431E213EB23C72E16484C99DF9200FC7E05EC4 4E94F072BE45B7620D0000

Пакет который я декодил по начальному ключу блоуфиша (кстати проверьте плиз у себя, ключ интерлюдовский, у вас так же получилось?) - 02-13 20:32:09.921: I/System.out(1637): D1A89279E77E010F60C4CD4FB62DFF6E471CBFE205CD45E5C4 C5FCC40712DC03054E2BC11165240ED0099D850EAED6F9B608 2972CC03CE72CDF36AEB32863EFD42016649D94D4BC26166CC AFF5A2411B4F851BB55B8C0807AA0B5C6DCFECC34941B048D2 18C7C8BFCD74DC9DF0388D59B5619158A6B4E216525B8C2A11 55AE866F2173015A2D22F4C629DFB78981337B83C74D68C5EC 5C9BC776C317482901612311B720B660F27D758A2ABE584032 B17DAE52B3DF01CF72FA1D

А это пакет который декодил антиксором, который опубликован выше - 02-13 20:32:09.932: I/System.out(1637): D1A89279E77E00000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000052B3DF01CF72FA1D


Где косяк??? я уже себе все мозги сломал, дальше инита продвинутся не могу... обидно... на пхп по моему и то проще это реализовать...

Kilatif
14.02.2012, 02:12
ErgoZ, я думаю с xor'ом для явы тебе поможет товарищ Tin-moon, который вроде как уже прошел пакет Init :)

ErgoZ
14.02.2012, 02:31
эх жаль делфей нет под андроид... ща вот качаю сяху, может на с++ с ндк получится что нибудь...

2 Tin-moon
Ты на яве смог пройти инит? Если на яве можешь помочь с функциями ксора и некоторыми другими? С меня пиво если поделишься немного кодом)))

supernewbie
14.02.2012, 10:05
а вы вообще в курсе что на большем кол-ве серверов доп. шифрация?

Tin-moon
14.02.2012, 13:15
To Kilatif:
Решил до конца пройтись по блоуфиш, нашел у тебя несколько различий, ты говарил что пишешь по другие пакеты вот решил уточнить.

public byte[] Decode(byte[] data)
{
int i, len;
byte[] DBuff = new byte[8];

len = data.Length; - тут в делфи - 2 (вернее мы вызываем декод передавая в длину - 2)

for (i = 0; i < len / 8; i ++)
{
Array.Copy(data, i * 8, DBuff, 0, 8);
DBuff = DecodeBlock(DBuff);

Array.Copy(DBuff, 0, data, i * 8, 8);
}

return data;
}
public byte[] Encode(byte[] data)
{
int i, len;
byte[] DBuff = new byte[8];

len = data.Length; - тут там тоже - 2

for (i = 0; i < len / 8; i++)
{
Array.Copy(data, i * 8, DBuff, 0, 8);
DBuff = EncodeBlock(DBuff);

Array.Copy(DBuff, 0, data, i * 8, 8);
}

return data;
}


Еще тут:

j = 0;
for (i = 0; i < 18; i++)
{
data = ((Key[j] & 0xFF) << 24) | ((Key[(j+1) % Size] & 0xFF) << 16) | ((Key[(j+2) % Size] & 0xFF) << 8) | (Key[(j+3) % Size] & 0xFF);
PArray = PArray[i] ^ data;
j = (j + 4) % Size;
}

datal = 0;
datar = 0;
for (i = 0; i < 9; i++)
{
Blowfish_encipher(ref datal, ref datar);
PArray[i*2] = datal;
PArray[i*2 + 1] = datar;
}

for (i = 0; i < 4; i++)
for (j = 0; j < 128; j++)
{
Blowfish_encipher(ref datal, ref datar);
SBoxes[i, j*2] = datal;
SBoxes[i, j*2 + 1] = datar;
}

// тот же кусок на делфи
for i:=0 to 17 do begin
data:=((key[j] and $FF)shl 24)or((key[(j+1) mod Size] and $FF)shl 16)or((key[(j+2) mod Size] and $FF)shl 8)or(key[(j+3) mod Size] and $FF);
PArray[i] := PArray[i] xor data ;
j := (j + 4) mod Size ;
end;
datal := 0 ;
datar := 0 ;
for i:=0 to 8 do begin
Blowfish_encipher (datal, datar) ;
PArray[i*2] := datal ;
PArray[i*2 + 1] := datar ;
end;
for i:=0 to 3 do
for j:=0 to 127 do begin
Blowfish_encipher (datal, datar) ;
SBoxes[i,j*2] := datal ;
SBoxes[i,j*2 + 1] := datar ;
end;

Или в делфи нумерация как-то по другому? (всмысле массива)

[I]Добавлено через 2 часа 24 минуты
To Kilatif:

Можно эту функцию: procedure AddCheckSumm(var data: array of byte; len: integer);

Kilatif
14.02.2012, 13:17
Tin-moon, в делфи цикл, например for j := 0 to 127 подразумевает то, что j будет идти от нуля до 127 включительно, а когда j станет 128, то цикл прервется

А цикл for (j = 0; j < 128; j++) говорит о том, что j будет увеличиваться на единицу, начиная с нуля до тех пор пока j < 128. Т.е. когда j = 128, то цикл прервется. Поэтому это одно и тоже

Tin-moon
14.02.2012, 15:54
Tin-moon, в делфи цикл, например for j := 0 to 127 подразумевает то, что j будет идти от нуля до 127 включительно, а когда j станет 128, то цикл прервется

А цикл for (j = 0; j < 128; j++) говорит о том, что j будет увеличиваться на единицу, начиная с нуля до тех пор пока j < 128. Т.е. когда j = 128, то цикл прервется. Поэтому это одно и тоже

Спасибо, понял. Функция уже не нужна(в прошлом посте);

Добавлено через 1 час 31 минуту
WARNING [14 Feb 13:51:10,121] net.l2emuproject.loginserver.network.L2LoginClient .decrypt(): Wrong checksum from client: [State: CONNECTED | IP: 127.0.0.1 ]
Вот вредина :) Все-таки нужна функция AddCheckSumm

ErgoZ
14.02.2012, 16:39
ты про этот чек сумм:
unsigned long checksum( unsigned char *packet, int count )
{
long chksum = 0L;
for( int i = 0; i < count; i += 4 ) chksum ^= *((unsigned long *)&raw[i]);
return chksum;
};

Tin-moon
14.02.2012, 23:41
To Kilatif:
Прикол, решил сравнить инициализацию блоуфиша:
Приходящий на 1 и тот же входящий пакет Init, получаются разные значения PArray.
Прикол в следующем:
Java и C# дают следующий результат (одинаковый):

* - PArray {long[18]} long[]
[0] -11504476527 long
[1] 818284978 long
[2] 5389473844 long
[3] 5277480315 long
[4] 2258027768 long
[5] 1971259599 long
[6] -10807336962 long
[7] 15922993650 long
[8] -1570502760 long
[9] -13871540854 long
[10] 7461419269 long
[11] 15931572012 long
[12] -4834315440 long
[13] 6949642799 long
[14] 13899931484 long
[15] 11387598665 long
[16] 14253408890 long
[17] 11324059052 long


а вот реализация на Delphi немного другой ( совпало только первые два):

(1380425361, 818284978, 3744654971, 1864113960, 3479827321, 2874253665, 3288700621, 2149712101, 776530621, 3122561990, 1920928410, 1485135872, 2882331372, 1270005868, 4088379872, 3643499899, 4185267842, 196570026)


Это нормально????

Kilatif
15.02.2012, 00:33
Tin-moon, так у тебя блоуфиш до сих пор не работает? Ты возьми в Delphi и в java объяви по блоуфишку, инициализируй их одинаковым ключем и посмотри как они кодируют и декодируют одинаковые данные (это необязательно должен быть пакет, любой свой массив).

Tin-moon
15.02.2012, 00:37
data:=((key[j] and $FF)shl 24) or
((key[(j+1) mod Size] and $FF)shl 16) or
((key[(j+2) mod Size] and $FF)shl 8) or
(key[(j+3) mod Size] and $FF);
мне кажется, что это неправильно переписали.. как работает key[(j+3) mod Size?

Добавлено через 2 минуты
Tin-moon, так у тебя блоуфиш до сих пор не работает? Ты возьми в Delphi и в java объяви по блоуфишку, инициализируй их одинаковым ключем и посмотри как они кодируют и декодируют одинаковые данные (это необязательно должен быть пакет, любой свой массив).

Понимаешь проблема не в кодировать декодировать а в самом ините, там уже разные данные получаются.
Например, после этого кода
for i:=0 to 17 do begin
data:=((key[j] and $FF)shl 24)or((key[(j+1) mod Size] and $FF)shl 16)or((key[(j+2) mod Size] and $FF)shl 8)or(key[(j+3) mod Size] and $FF);
PArray[i] := PArray[i] xor data ;
j := (j + 4) mod Size ;
end;

На яве совпало только то что с +
/*
(1331667411+, 124622946+, 3744654971, 1864113960+, 3479827321, 2874253665,
3288700621, 2149712101, 776530621+, 3122561990, 1920928410+, 1485135872+,
2882331372, 1270005868+, 4088379872, 3643499899, 4185267842, 196570026+)
*/

Сори малек затупил это часть верно (пора ложиться спать наверно:)), не верные данные вот от сюда:
datal := 0 ;
datar := 0 ;
for i:=0 to 8 do begin
Blowfish_encipher (datal, datar) ;
PArray[i*2] := datal ;
PArray[i*2 + 1] := datar ;
end;

Наверно мне нужно разобрать что я там с Blowfish_encipher натупил.

Kilatif
15.02.2012, 02:20
key[(j+3) mod Size] - нуу, берет из ключа key элемент (j+3) mod Size, где mod - Это операция для вычисления от деления на Size

Tin-moon
15.02.2012, 12:40
To Kilatif

Вроде отладил BlowFish. Нашел вроде где у меня ошибка.
if temp[0]=#0 then begin
SetLength(s,Len-2);
for i:=0 to Len-3 do s[i+1]:=temp[i];
for i:=0 to Len-3 do temp2[i+1]:=temp1[i];
s:=AntiXor(s);
for i:=0 to Len-3 do temp[i]:=s[i+1];
end;

Вот этот кусок проблемный. Там зачем-то перегнали в массив char, сняли хор и вернули. Конкретно проблема с правильной инициализацией s наверно. Выкинь прлз этот кусок(это в procedure LS_parser). Ну и чтобы наверняка и AntiXor(s); -- ее вроде проверил на куске байт переводит верно, но навсякий случай.

Kilatif
15.02.2012, 13:06
Tin-moon, у меня это сделано в другом классе вот таким образом:
private byte[] DecryptLoginServer(byte[] packet, int packetSize)
{
byte[] result = (byte[])Funcs.DeepClone(packet);

result = blowfish.Decode(packet);
if (packet[0] == 0)
{
result = Funcs.AntiXor(result);
}

return result;
}


AntiXor я кидал страницами ранее

Tin-moon
15.02.2012, 13:10
Как ты заполняешь byte[] packet ?? Из того пакета который пришел.
Tin-moon, у меня это сделано в другом классе вот таким образом:
private byte[] DecryptLoginServer(byte[] packet, int packetSize)
{
byte[] result = (byte[])Funcs.DeepClone(packet);

result = blowfish.Decode(packet);
if (packet[0] == 0)
{
result = Funcs.AntiXor(result);
}

return result;
}



AntiXor я кидал страницами ранее

Kilatif
15.02.2012, 19:07
Tin-moon, packet - это пакет, который только-только пришел от сервера и с убранными двумя байтами размера

Tin-moon
15.02.2012, 22:29
Нашел свою ошибку) ппц я просто ржал немог. Создал клон входящих данных работал с ним, а итог записал не туда и возвращал не те данные :confused: . Успешно получил LS_GGAuth. Ща попробую дальше.

To Kilatif
Можешь выложить функции RepairKey и RSAEncrypt ?

ErgoZ
16.02.2012, 00:49
Tin, не поделишься ф-циями по блоуфишу и антиксору для явы, а то у меня бред получается (((

Kilatif
16.02.2012, 01:31
Tin-moon
Во вложении 2 файла, те ф-ции, которые ты просил + левый скачанный с инета класс по работе с большими числами, который я использовал в RSAEncrypt.

Tin-moon
16.02.2012, 09:58
FGIntMontgomeryModExp(d,e,m,r); //выполняется операция r = (d^e) mod m



r = (d возводим в степень e) берем по модулю m ?

у меня почему-то m отрицательное получается....

Kilatif
16.02.2012, 13:35
Tin-moon, значение m ты задаешь сам. Как оно у тебя отрицательное получиться оО?

Tin-moon
16.02.2012, 17:41
Tin-moon, значение m ты задаешь сам. Как оно у тебя отрицательное получиться оО?

Возникла проблема. Отправляю пакет RequestAuthLogin. Сервер не ругается, создает новый акаунт, но имя просто бредовое. В чем может быть проблема?

Нашел ошибку не дописал 1 байт.
Полоностью переписал функционал того что было на делфи.

Что теперь делать?? ;)

Kilatif
16.02.2012, 19:46
Tin-moon, тебе в конечном итоге должен был придти пакет PlayOk. Когда он пришел, берешь оттуда нужные данные, закрываешь соединение с логин сервером и открываешь соединение с GameServer-ом, к которому тебе нужно подключиться. IP и порты GameServer-ов тебе приходили в пакете ServerList. Какие пакеты тебе нужно отсылать и принимать после установки соединения, можешь посмотреть, зайдя в игру с включенным l2phx. Нужные тебе пакеты для входа в мир начинаются с ProtocolVersion и заканчиваются EnterWorld.

Что касается шифрации.
Первые 2 пакета не шифруются (ProtocolVersion(Client->GS) и KeyInit(GS->Client)).
Пакеты после KeyInit шифруются xor-шифрованием со сменой ключа. Первый ключ берется в пакете KeyInit, остальные берутся из следующих пакетов.
Во вложении класс для работы с этим xor-шифрованием

ErgoZ
17.02.2012, 03:59
Ребят, помогите плиз.
Есть такой пакет:

BA00B7E270A314DAB19B1CCBE15C22E35AF2438045B46F40DB 4A756BF36A3EB15E04930CA14D91DCACB6A24DFD43D90D04F7 8E1654B2AD65D465A29361595DEB6A9251E4A6CC1094130153 F5D40DFDD78272C3599A58E3F37B95427A70C55B9A36BC4494 0D9CB55758129F7DFA76B2499DC2D90CB095E0E5BB7B4B2B97 3E3C1846B6312A5D98A335CBD2FB062EFD0F23F353C2635A0A D90013EFA501C4AB2BF722F88E39D45CB8AF248E205D535FAB 6796D6F5D7BD34B627606F

Можете выложить пакет который получается после блоуфиша? и после ксора? и рса ключ? а то не могу понять правильно ли я его продекодил в плане блоуфиша.

Чтоб не быть голословным, у меня результат после обработки блоуфиша такой:
BA0000B8EEC4115B240C09BA250D17FB84379854F1BF0EFA35 8A43EB1FB630F204CA3968F13194D55F70E845A57E1A5CB403 20A45053EFA18ADE3EF0E955B0EDE68EE1E64BA4F660265231 88544C57A49E8B9CCA09D9615561ED11C151AD83B2CBAE56DB B8BAEF5AD04D1A36F93B4F63918599D2F3E643976242C6A214 75D4A7FA908F305FD924DA0AD1719D05A8FC33B1FA3BD0554B 74102419ED19CDFCEA3C2F2E01232416F807393DD74C1D63A9 CFDD58143EDA74385F1A97

Правильно ли у меня получилось?

И какой тогда тут будет ксор ключ? 385F1A97? или 143EDA74?

Kilatif
17.02.2012, 12:16
ErgoZ, судя по тому, что первый байт (без учета размера) пакета равен нулю (тип пакета Init), блоуфишем ты расшифровал правильно. Ключом будет 143EDA74. А вообще ф-ю AntiXor я приводил ранее.

ErgoZ
17.02.2012, 14:41
Походу дела получилось, в итоге после ксора у меня такой вот пакетик:
BA0000B8EEC41821C60000E1A1226F506A8492FE03C633AD23 38B3DAE403E7E5551BB53D54BE4C68FDF20E66097FFA3F04CD 753AD66ACD11D2734EAD4CDC6FC8A1D28B799675C7E8EDE900 D4C5C933ED66A3FDE128FA9015B077904C6A0BB11B6C14B39D 088105AF388B592988BE262E5E18D84792A481C991280AFA71 05ADB74F586B155588EB5EF146DD4E95DD29FC9CC37720B6AD 97F7E0BD071D242D151EF33FA9DCECEA2F4C3A208000CF2BBD F1072C143EDA74385F1A97

особенно радуют 5 и 6 байты без учёта байт размера - 21c6 )))

Добавлено через 35 минут
Вот такой вот итог работы за 2 дня :)

02-17 09:36:33.949: I/System.out(1518): Try connect to /127.0.0.1:2106

02-17 09:36:34.102: I/System.out(1518): Connected to 127.0.0.1/127.0.0.1:2106

02-17 09:36:34.173: I/System.out(1518) Starting packet: BA00C8457ADCC06D468FE117AF6AFE3D078271A1104D7CB75F 38DA8D320AF78F77E28000DDC4E09026D4DF9ABCB8183925BB A89EEC6FADB5D575748AAD6F75E5D4C9114C0BF5E2E12A49EF 8164E641C4C7FF92B57F017C234A8ABF92DE4267248FF4B507 81967D82A7DFC13CC5E3D831EDFFD0E58D7D485ACC4F577B0D A6204713EA386ADA4FB582F466AB60A65001874AF601461A48 3EABCCF42672865CF1E0F88CE8795FE942778F525E281A0DD5 20E1428540490A461B0D63

02-17 09:36:34.179: I/System.out(1518) Blowfish decrypted packet: BA000086149F073BE6F6281A200E28470CFD8316502FFD08EC AE45DE043C611FFF37CF149BAF38B655F44910CCF5A1EA8AA3 12A937073194FD4D00A72E7E46033588DD1A5513D1A678D340 01B1066BFBCBD1C6B74091BA2623D85A8BA1497CAA5563DF49 E6021C5735D26F7A0BA49025A797D2171BB2062B592BFB494F 3CFA9B5C17CD194E9D67E963C038945956F22AF58C25D7A950 7E19E006F712014B10BEBD2CD2D09A8BCF26FFFA7296C793C8 BE322D836B158BA1771982

02-17 09:36:34.179: W/System.err(1518): Xor Key: 836B158B

02-17 09:36:34.179: I/System.out(1518): DeXored packet: 0086149F2F21C60000A1D34C574EDCDFFEEE43864039EF8264 D7EBCAA00B88601781563CF159EE38D6F6B99453825BA1DD22 FB3231CD183CC2A725067BE59F7A72BF7D3C915928D6A929FA 29D569745F8C925F29FC5142108E2EF4D655120862DB7AD530 8D92C371FF5F6AD042D0B3F928F123A70F6210CF7D22832E3F 7C698A143FADA24F65546E8A4E95DD29FC9CC37720B6AD97F7 E0BD07B39268BE0ED7551F321C5D21B33C974A002A774BD527 A6836B158BA1771982

02-17 09:36:34.179: W/System.err(1518): Protocol: 21C6

02-17 09:36:34.189: W/System.err(1518): SessionID: 86149F2F

02-17 09:36:34.189: W/System.err(1518): RSAKey: A1D34C574EDCDFFEEE43864039EF8264D7EBCAA00B88601781 563CF159EE38D6F6B99453825BA1DD22FB3231CD183CC2A725 067BE59F7A72BF7D3C915928D6A929FA29D569745F8C925F29 FC5142108E2EF4D655120862DB7AD5308D92C371FF5F6AD042 D0B3F928F123A70F6210CF7D22832E3F7C698A143FADA24F65 546E8A

02-17 09:36:34.199: W/System.err(1518): NewBFKey: B39268BE0ED7551F321C5D21B33C974A

Tin-moon
17.02.2012, 23:08
закрываешь соединение с логин сервером и открываешь соединение с GameServer-ом, к которому тебе нужно подключиться.

Возник вопрос по реализации логики открытия и закрытия сокетов.
Суть:
Написал абстрактный класс для работы с сокетом (с общей логикой) унаследованный от потока. Создал 2 класса для реализации Логики работы с логин сервером и для работы с гейм сервером. Логин часть отрабатывает, а запустить гейм часть не получается.... Или ошибки или закрывается полностью приложение....
Мб какой совет есть (по структуре приложения).

И ще возник вопрос:
ProtocolVersion - пакет такой

07 01 // Длина
00 // Тип
XX XX XX XX // ProtocolVersion
[далее идет массив-константа, который хз от чего зависит, у меня он такой:]
09 07 54 56 03 09 0B 01 07 02 54 54 56 07 00 02
55 56 00 51 00 53 57 04 07 55 08 54 01 07 01 53
00 56 55 56 01 06 05 04 51 03 08 51 08 51 56 04
54 06 55 08 02 09 51 56 01 53 06 55 04 53 00 56
56 53 01 09 02 09 01 51 54 51 09 55 56 09 03 04
07 05 55 04 06 55 04 06 09 04 51 01 08 08 06 05
52 06 04 01 07 54 03 06 52 55 06 55 55 51 01 02
04 54 03 55 54 01 57 51 55 05 52 05 54 07 51 51
55 07 02 53 53 00 52 05 52 07 01 54 00 03 05 05
08 06 05 05 06 03 00 0D 08 01 07 09 03 51 03 07
53 09 51 06 07 54 0A 50 56 02 52 04 05 55 51 02
53 00 08 54 04 52 56 06 02 09 00 08 03 53 56 01
05 00 55 06 08 56 04 0D 06 07 52 06 07 04 0A 06
01 04 54 04 00 05 02 04 54 00 09 52 53 05 04 01
04 05 05 01 52 51 52 0D 06 51 08 09 54 53 00 0D
01 02 03 54 53 01 05 03 08 56 54 07 02 54 0B 06

или

Назначение: передает версию протокола используемого клиентом серверу
Формат:
00
XX XX XX XX // Версия протокола

ErgoZ
18.02.2012, 01:47
tin-moon а ты на яве пишешь? или на другом языке?

Kilatif
18.02.2012, 03:42
Tin-moon, у меня с сокетами тоже не все впорядке, поэтому врятли тебе в этом помогу) Что касается ProtocolVersion. Я посылаю первый вариант, т.е. с константой, просто потому что так делает клиент, хотя прокатывает и второй.

Tin-moon
19.02.2012, 12:09
tin-moon а ты на яве пишешь? или на другом языке?
Java

Добавлено через 10 часов 8 минут
Tin-moon, у меня с сокетами тоже не все впорядке, поэтому врятли тебе в этом помогу) Что касается ProtocolVersion. Я посылаю первый вариант, т.е. с константой, просто потому что так делает клиент, хотя прокатывает и второй.

Странно получил данные отрубился от логина подрубился к гейм, отправил ProtocolVersion без констант - реакции никакой. Отправил с константами реакции никакой). Возник вопрос константы как формируются?? А длина пакета с константами 267 байт? Без констант я так предпологаю что длина 5 байт? Или я ошибся где-то?

Пихаю гейм серверу пакеты, а реакции нету. В чем может быть проблема?

Добавлено через 15 часов 25 минут

Что касается шифрации.
Первые 2 пакета не шифруются (ProtocolVersion(Client->GS) и KeyInit(GS->Client)).
Пакеты после KeyInit шифруются xor-шифрованием со сменой ключа. Первый ключ берется в пакете KeyInit, остальные берутся из следующих пакетов.
Во вложении класс для работы с этим xor-шифрованием

Наконец получилось отправить ProtocolVersion. Незнаю что было, отправлял одно и тоже (заработало с константами). Вопрос по существу:
Получил KeyInit, переписал xor-шифрованием под яву, возник вопрос зачем public void InitKey(long keyInit) - что ты туда подпихиваешь (это ключ который пришел в KeyInit?) и самое интересное, зачем keyConst?

public CryptXor()
{
isInit = true;
}
public void InitKey(long keyInit)
{
byte[] keyConst = new byte[8] {0xC8, 0x27, 0x93, 0x01, 0xA1, 0x6C, 0x31, 0x97};

this.keyLength = 15;
Array.Copy(BitConverter.GetBytes(keyInit), 0, GKeyS, 0, 8);
Array.Copy(keyConst, 0, GKeyS, 8, 8);
Array.Copy(GKeyS, 0, GKeyR, 0, 16);

this.isInit = true;
}

xkor
19.02.2012, 13:57
Tin-moon, keyConst это константная часть ключа. Зачем она - вопрос к разработчикам алгоритма, ну вот захотелось им что бы половина ключа приходила от серва а половина была константой...
ЗЫ в чем смысл передавать keyInit в метод в виде числа и преобразовывать там в массив, если эти байты ты получаешь из пакета в виде массива, смысл их в число превращать а потом обратно, только лишнее место для возможной ошибки делаешь

Tin-moon
19.02.2012, 14:09
Tin-moon, keyConst это константная часть ключа. Зачем она - вопрос к разработчикам алгоритма, ну вот захотелось им что бы половина ключа приходила от серва а половина была константой...
ЗЫ в чем смысл передавать keyInit в метод в виде числа и преобразовывать там в массив, если эти байты ты получаешь из пакета в виде массива, смысл их в число превращать а потом обратно, только лишнее место для возможной ошибки делаешь

Понял. Пришел keyInit вот такой:

/*
* 0x19, 0x00,
* 0x2e, 0x01,
* 0x70, 0x5e, 0x4c, 0x79, 0x4d, 0x85, 0xf2, 0x44, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
* 0x01, 0x00, 0x00, 0x00,
* 0x00
*/


По описанию нужно 16 байт брать (красным)? или 8??
И еще где посмотреть какие пакеты дальше? В описаниях нету таких которые перехватывает l2phx.3.5.9.113.

Kilatif
19.02.2012, 15:27
xkor, где-то ты и прав. Ну.. у меня эта функция переписана (кстати с исходников корректора =) ) и я решил ничего не трогать. А вообще лично мне с числами работать приятнее и удобнее.

вот мой пакет KeyInit

2E 01 - тип
BE AA E1 05 28 10 97 D9 C8 27 93 01 A1 6C 31 97 - ключ
01 00 00 00 00 00 00 00 00 00 00 00 00 - константа

Жирным выделена та самая константа, которую ты выделил в функции
Вообще эта константа должна быть всегда в KeyInit. Но у тебя я ее не наблюдаю, отсюда следует вывод: либо эта константа для тебя только лишняя, потому что у тебя KeyInit какой-то другой, либо KeyInit ты мне показал не правильный.

Добавлено через 1 минуту
Tin-moon, Да и вообще, в конце-то концов пора узнать, для каких хроник ты пишешь чат-клиент? )

Tin-moon
19.02.2012, 15:31
xkor, где-то ты и прав. Ну.. у меня эта функция переписана (кстати с исходников корректора =) ) и я решил ничего не трогать. А вообще лично мне с числами работать приятнее и удобнее.

вот мой пакет KeyInit

2E 01 - размер
BE AA E1 05 28 10 97 D9 C8 27 93 01 A1 6C 31 97 - ключ
01 00 00 00 00 00 00 00 00 00 00 00 00 - константа

Жирным выделена та самая константа, которую ты выделил в функции
Вообще эта константа должна быть всегда в KeyInit. Но у тебя я ее не наблюдаю, отсюда следует вывод: либо эта константа для тебя только лишняя, потому что у тебя KeyInit какой-то другой, либо KeyInit ты мне показал не правильный.

Добавлено через 1 минуту
Tin-moon, Да и вообще, в конце-то концов пора узнать, для каких хроник ты пишешь чат-клиент? )

У меня почему-то повторяется.


0x19, 0x00, - размер пакета
0x2e, 0x01, - тип
0x70, 0x5e, 0x4c, 0x79, 0x4d, 0x85, 0xf2, 0x44, - я предполагаю, что это ключ
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00- непонятные.. в описании 2 раза только повторились.

Меня интересует следующий пакет в l2px(0x82)т.е. второй пакет который мы отправляем к серверу

Kilatif
19.02.2012, 15:48
Следующий пакет RequestAuthLogin (0x2B)

Tип: 0x2B (ReqAuthLogin)
Pазмер: 57+2
0002 s LoginName
001A d PlayKey2
001E d PlayKey1
0022 d LoginKey1
0026 d LoginKey2
002A d : 1

Tin-moon
19.02.2012, 15:53
Следующий пакет RequestAuthLogin (0x2B)

Tип: 0x2B (ReqAuthLogin)
Pазмер: 57+2
0002 s LoginName
001A d PlayKey2
001E d PlayKey1
0022 d LoginKey1
0026 d LoginKey2
002A d : 1

Типа такой? С данными которые получил у логина?

XX XX // Длина
08 // Тип
XX XX ... 00 00 // Login (Unicode строка)
XX XX XX XX // SessionKey2_SecondPart
XX XX XX XX // SessionKey2_FistPart
XX XX XX XX // SessionKey1_FistPart
XX XX XX XX // SessionKey1_SecondPart
01 00 00 00


Это не странно?
http://rghost.ru/36597131/image.png

Kilatif
19.02.2012, 16:59
Tin-moon, да, такой по структуре, но тип 0x2B для Gracia и выше

Tin-moon
19.02.2012, 17:23
Tin-moon, да, такой по структуре, но тип 0x2B для Gracia и выше

каковы размеры каждого блока?
0002 s LoginName - 14 байт
001A d PlayKey2 - 4 байт
001E d PlayKey1 - 4 байт
0022 d LoginKey1 - 4 байт
0026 d LoginKey2 - 4 байт
002A d : 1

и этот кусок хорим той функцией которые ты давал?

Добавлено через 21 минуту

Это не странно?
http://rghost.ru/36597131/image.png

Оно реально отправляет EnterWorld.... (51 байт). тестирую на l2emu HF. Ты вкурсе как обработать пакет?

Kilatif
19.02.2012, 17:32
и этот кусок хорим той функцией которые ты давал?
все пакеты после KeyInit ксорятся той функцией которую я давал

Это не странно?
Странно, очень даже странно...

Tin-moon
19.02.2012, 17:39
и этот кусок хорим той функцией которые ты давал?
все пакеты после KeyInit ксорятся той функцией которую я давал

Это не странно?
Странно, очень даже странно...

Почему "Pазмер: 57+2" (Tип: 0x2B (ReqAuthLogin)) ?? распиши как туда впихнуть, а то у меня ничего не приходит.
Хорим полностью, что добавляем, а потом к схореному вешаем длину (по полученному)??
Вот это все хорим??:
0002 s LoginName - 14 байт
001A d PlayKey2 - 4 байт
001E d PlayKey1 - 4 байт
0022 d LoginKey1 - 4 байт
0026 d LoginKey2 - 4 байт
002A d : 1

Kilatif
19.02.2012, 17:46
Размер этого пакета может быть разный, потому что LoginName у каждого разного размера будет.
Ксорить нужно пакет без размера, размер добавлять после ксора.

Tin-moon
19.02.2012, 17:48
Размер этого пакета может быть разный, потому что LoginName у каждого разного размера будет.
Ксорить нужно пакет без размера, размер добавлять после ксора.

А почему логин нейм будет разный?? мы же его до 14 символов даводим в когда в логин авторизуемся? или это другой LoginName?

Kilatif
19.02.2012, 17:52
Tin-moon, это нам тогда нужно было его доводить до 14 символов, сейчас это просто логин нейм в формате WideString

Tin-moon
19.02.2012, 17:52
Я тут немного подумал, что лишнее хорю

0002 s LoginName - 14 байт
001A d PlayKey2 - 4 байт
001E d PlayKey1 - 4 байт
0022 d LoginKey1 - 4 байт
0026 d LoginKey2 - 4 байт
002A d : 1 - не хорим?

Создаем массив в который пихаем то что красным, его хорим а потом дописываем тип пакета в начало, вставляем отхореный блок и добавляем 002A d : 1, после оборачиваем размером и отправлям?

Kilatif
19.02.2012, 17:56
Tin-moon, единица это константа, но она входит в пакет. Ее ксорить надо тоже

Tin-moon
19.02.2012, 17:58
Tin-moon, единица это константа, но она входит в пакет. Ее ксорить надо тоже

Понял, пробую...

Не выходит... По поводу получения ключа никто коментариев не дал, там верно?
Опишите как создать пакет RequestAuthLogin().


Формат:
XX XX // Длина
08 // Тип
XX XX ... 00 00 // Login (Unicode строка) ---- что значат эти нули?
XX XX XX XX // SessionKey2_SecondPart
XX XX XX XX // SessionKey2_FistPart
XX XX XX XX // SessionKey1_FistPart
XX XX XX XX // SessionKey1_SecondPart
01 00 00 00


На какой позиции в массиве находится?

Kilatif
19.02.2012, 20:10
что значат эти нули?
эти нуля обозначают окончание строки. А специальное обозначение окончания строки нужно, что бы точно определить размер строки, т.к. строки могут быть разные

Tin-moon
19.02.2012, 20:33
что значат эти нули?
эти нуля обозначают окончание строки. А специальное обозначение окончания строки нужно, что бы точно определить размер строки, т.к. строки могут быть разные

У тебя там есть функция login = Funcs.StringToWideString(login);
Какие байты у тебя получаются ну например если строка "123456789" ?? Возможно я неправильно строку обрабатываю

Kilatif
19.02.2012, 20:59
Tin-moon, "1\02\03\04\05\06\07\08\09\0\0\0"

Tin-moon
19.02.2012, 21:11
Tin-moon, "1\02\03\04\05\06\07\08\09\0\0\0"
Специально добавил? А функции по xor ты сам писал (всмысле для конкретного сервера) или это общее?

sko
19.02.2012, 23:09
Специально добавил?
Если тип данных WideString, то нолики сами добавятся.

В хелпе по этому поводу пишут, что WideString не хранит своего размера и единственный способ понять, где она кончается - найти терминирующий символ. Так как все символы у нас 2-х байтные, то этот символ будет \0\0. Вроде так :)

A wide string is a contiguous sequence of wide characters terminated by and including the first null wide character.

Tin-moon
19.02.2012, 23:28
Решил попробовать l2px поновее (там вроде появилась поддержка HF). Скачал l2phx.3.5.34.175 , l2phx.3.5.34.174 -- не хотят отлавливать пакеты. И в списке процессов вообще ничего не отображается....

Вроде удалось пропадчить.. Как просматреть обмен пакетами? Так как в старом не отображает сразу....

NLObP
19.02.2012, 23:31
Tin-moon, в новых версиях в порты пишем порты геймсервера, т.е. те порты, которые перехватываем.

Tin-moon
20.02.2012, 12:24
Поработал с l2ph. Получил следующий результат по полученным данным из l2ph.
Если из пакета keyInit читать 16 байт то после функции хор совпадает следующее: (данные на выходе с полученные в l2ph)^

90 FE 92 0C 69 C0 13 DF 17 02 91 A1 00 59 68 FF
44 97 4F D1 3D DE 09 51 2F 0D F3 C1 9A CE 8D 51
D5 88 E4 4F 2A CA 18 E5 2D 0A 99 98 39 55 64 F3 48

Если из пакета keyInit прочитать 8 байт и добавить константу предложенную Kilatif в выложенных функциях, то совпадет следующее:

90 FE 92 0C 69 C0 13 DF 17 02 91 A1 00 59 68 FF
44 97 4F D1 3D DE 09 51 2F 0D F3 C1 9A CE 8D 51
D5 88 E4 4F 2A CA 18 E5 2D 0A 99 98 39 55 64 F3 48

Предположение что неверно инициализирую хор. Кто может подсказать???


Пакет keyInit (l2ph) такой:

2E 01 BB 5C 6C AB 65 9C D3 FD 01 00 00 00 01 00 00 00 01 00 00 00 00

0003 q KeyL: -156609601546199877
000B q KeyH: 4294967297

Это расшифорованный l2ph пакет ReqAuthLogin, что за данные выделенные красным?? Откуда их брать?

2B 32 00 35 00 35 00 31 00 32 00 31 00 35 00 00
00 8F B4 35 89 7F 04 A5 B6 05 6D 33 FA 38 72 4B
3F 01 00 00 00 7C 01 00 00 00 00 00 00 00 00 00 00

Rzone
20.02.2012, 15:50
Писал бота на BlitzBasic если кто знает такой:) Первого написал года 4 назад получился тормозной но рабочий, недавно переписал на BlitzMax - летает) Начинал кстати с той же статьи http://fursoffers.narod.ru/Packets.htm и смотрел теже исходники. Если надо, могу дать исходники на бейсике они должны попонятнее быть всяких си++:) С ксором и блоуфишем был тот же гемор, ксор я кое-как переписал с найденных в нете то-ли сишных то-ли паскалевских, а с блоуфишем не мучался - нашел исходники для делфи, собрал ддлку на экспорт 3 функции инит и крипт/декрипт. Ява поддерживает вызов функций с длл?

ErgoZ
20.02.2012, 19:36
в моём случае это не прокатит :) Я пишу под андроид))) немного забросил проект так как на мед обследовании, позже вернусь к проекту :) прошёл первый пакет)) дальше на этапе отправки 1 пакета от клиента серверу остановился)))

Tin-moon
21.02.2012, 00:21
Получил нужные данные на выходе. Отправляю на сервер, ничего не приходит. Кто может подсказать по этому пакету??

Rzone
21.02.2012, 05:40
Проснифай что твой бот отправляет, на какой порт итд. WPEpro очень хороший сниффер. Возможно, что и ответ от сервера приходит. Сравни логи WPEpro и клиента.

Tin-moon
21.02.2012, 11:40
Проснифай что твой бот отправляет, на какой порт итд. WPEpro очень хороший сниффер. Возможно, что и ответ от сервера приходит. Сравни логи WPEpro и клиента.

Поснифал. Ничего. Да и сам сервер не реагирует (паставил режим отладки на нем. Пишет только что протокол - ОК. и на этом все..)

Rzone
21.02.2012, 16:15
В смысле ничего? Вообще ни одного пакета не отправляет? После установления tcp соединения сервер должен отправить пакет init, если он не приходит - значит соединения нет.

Kilatif
21.02.2012, 17:38
Rzone, он уже прошел LoginServer и работает с GameServer'ом

Rzone
21.02.2012, 19:35
Тогда лог сниффера выложи.

Tin-moon
21.02.2012, 22:16
Смысл их выкладывать? Если не приходит ответа)

Сделал так, врубил l2ph запустил нормальный клиент отловил все пакеты. Скопировал эти пакеты. Запускаю свой клиент, подсовывая полученные пакеты из первой части (куда нужно для инициализации всех данных). Все норм инициализировало. Дохожу до нужного места (где происходит хор зашифровка). сравниваю данные с теми которые получил в l2ph, 1 ко 1. В чем проблема????:o Народ помогите или подскажить а то я уже :confused:

Demion
21.02.2012, 22:49
На каком пакете проблема?

Tin-moon
21.02.2012, 22:52
На каком пакете проблема?

RequestAuthLogin() на гейм сервер

Demion
21.02.2012, 22:59
Если сервер ничего не отвечает, скорее всего на правильно шифруешь пакет. Вот часть исходников моего старого бота, может поможет.
VOID XorEncrypt(BYTE *data, DWORD len, BYTE *Key)
{
int temp = 0;

for( unsigned int i = 0; i < len; i++) {
int temp2 = data[i] & 0xff;
data[i] = (temp2 ^ (Key[i & 15] & 0xff) ^ temp);
temp = data[i];
};

int old = Key[8] & 0xff;
old |= (Key[9] << 0x08) & 0xff00;
old |= (Key[10] << 0x10) & 0xff0000;
old |= (Key[11] << 0x18) & 0xff000000;

old += len;

Key[8] = old &0xff;
Key[9] = (old >> 0x08) & 0xff;
Key[10] = (old >> 0x10) & 0xff;
Key[11] = (old >> 0x18) & 0xff;
}

INT SendPacket(BYTE* buf, WORD size, SOCKET conn, DWORD EncodeType, DWORD EncodeData, DWORD TimeOut)
{
BYTE pbuf[65535];

memcpy(pbuf+2, buf, size);
size+=2;
memcpy(pbuf, &size, sizeof(WORD));
memcpy(buf, pbuf, size);
if (EncodeType == 1)
Blowfish_EncodeBlock((BLOWFISH_CTX*)EncodeData, pbuf+2, size-2);
if (EncodeType == 2)
XorEncrypt(pbuf+2, size-2, (BYTE*)EncodeData);
return SendNonBlock(conn, (CHAR*)pbuf, size, 0, TimeOut);
}

VOID GSCryptInit(BYTE *buf, DWORD size, BYTE *XorKeyEnc, BYTE *XorKeyDec)
{
BYTE KeyConst[8] = {0xC8, 0x27, 0x93, 0x01, 0xA1, 0x6C, 0x31, 0x97};

memcpy(XorKeyEnc, buf+4, 8);
memcpy(XorKeyDec, buf+4, 8);
memcpy(XorKeyEnc+8, KeyConst, 8);
memcpy(XorKeyDec+8, KeyConst, 8);
}

VOID GSAuthLogin(BYTE *buf, CHAR* Login, DWORD *SessionKey1, DWORD *SessionKey2, DWORD *SessionKey3, DWORD *SessionKey4, SOCKET s, BYTE *XorKeyEnc)
{
WCHAR ULogin[15];
swprintf(ULogin, 15, L"%hs", Login);
memset(buf, 0, 65535);
buf[0] = 0x2B;
memcpy(buf+1, ULogin, wcslen(ULogin)*2+2);
memcpy(buf+wcslen(ULogin)*2+3, SessionKey4, sizeof(DWORD));
memcpy(buf+wcslen(ULogin)*2+7, SessionKey3, sizeof(DWORD));
memcpy(buf+wcslen(ULogin)*2+11, SessionKey1, sizeof(DWORD));
memcpy(buf+wcslen(ULogin)*2+15, SessionKey2, sizeof(DWORD));
buf[wcslen(ULogin)*2+19]=0x08;
buf[wcslen(ULogin)*2+23]=0x7A;
buf[wcslen(ULogin)*2+24]=0x03;
buf[wcslen(ULogin)*2+31]=0x01;
SendPacket(buf, wcslen(ULogin)*2+35, s, 2, (DWORD)XorKeyEnc, 90);
}

Rzone
21.02.2012, 23:00
Смысл их выкладывать? Если не приходит ответа)

Сделал так, врубил l2ph запустил нормальный клиент отловил все пакеты. Скопировал эти пакеты. Запускаю свой клиент, подсовывая полученные пакеты из первой части (куда нужно для инициализации всех данных). Все норм инициализировало. Дохожу до нужного места (где происходит хор зашифровка). сравниваю данные с теми которые получил в l2ph, 1 ко 1. В чем проблема????:o Народ помогите или подскажить а то я уже :confused:

Проблема в том, что сервер присылает тебе ключ ксор шифрования, каждый раз ключ генерируется рандомно, а ты отсылаешь пакеты зашифрованные старым, нелигитным ключом. Мой совет - не спеши, делай по нормальному. Пакеты сам собирай из той информации которую тебе сервер пересылает. Проходи поэтапно, по пакетику. Снифери сравнивай правильно ли собрал пакет и дальше.

Tin-moon
21.02.2012, 23:13
Проблема в том, что сервер присылает тебе ключ ксор шифрования, каждый раз ключ генерируется рандомно, а ты отсылаешь пакеты зашифрованные старым, нелигитным ключом. Мой совет - не спеши, делай по нормальному. Пакеты сам собирай из той информации которую тебе сервер пересылает. Проходи поэтапно, по пакетику. Снифери сравнивай правильно ли собрал пакет и дальше.
И причем тут ключ? Он пришел в предыдущем пакете. Этим ключом шифрую этот? Что ты имеешь ввиду под старым ключом?? Где я этот старый получил?

То что я написал в предыдущем посте говорит о том что алгоритмы работают верно (ну судя по полученным результатом).

Добавлено через 2 минуты
Если сервер ничего не отвечает, скорее всего на правильно шифруешь пакет. Вот часть исходников моего старого бота, может поможет.

Спасибо ща покурю код.


VOID GSAuthLogin(BYTE *buf, CHAR* Login, DWORD *SessionKey1, DWORD *SessionKey2, DWORD *SessionKey3, DWORD *SessionKey4, SOCKET s, BYTE *XorKeyEnc)
{
WCHAR ULogin[15];
swprintf(ULogin, 15, L"%hs", Login);
memset(buf, 0, 65535);
buf[0] = 0x2B;
memcpy(buf+1, ULogin, wcslen(ULogin)*2+2);
memcpy(buf+wcslen(ULogin)*2+3, SessionKey4, sizeof(DWORD));
memcpy(buf+wcslen(ULogin)*2+7, SessionKey3, sizeof(DWORD));
memcpy(buf+wcslen(ULogin)*2+11, SessionKey1, sizeof(DWORD));
memcpy(buf+wcslen(ULogin)*2+15, SessionKey2, sizeof(DWORD));
buf[wcslen(ULogin)*2+19]=0x08;
buf[wcslen(ULogin)*2+23]=0x7A;
buf[wcslen(ULogin)*2+24]=0x03;
buf[wcslen(ULogin)*2+31]=0x01;
SendPacket(buf, wcslen(ULogin)*2+35, s, 2, (DWORD)XorKeyEnc, 90);
}

а эти данные откуда?

Demion
21.02.2012, 23:20
Честно говоря, не помню. Судя по всему это какие-то константные данные. В любом случае бот работал на офф сервере. Сравни с тем, что шлет твой клиент.

Tin-moon
22.02.2012, 11:45
Честно говоря, не помню. Судя по всему это какие-то константные данные. В любом случае бот работал на офф сервере. Сравни с тем, что шлет твой клиент.
Ну если по тому что расшифровывает l2ph у меня тоже константа но другая. Какие хроники у тебя?

XorEncrypt - чот невтыкаю как она шифрут данные... (+)
Разобрался, результат такой же как и у меня....

Что возвращает?

memcpy(buf+1, ULogin, wcslen(ULogin)*2+2);
memcpy(buf+wcslen(ULogin)*2+3, SessionKey4, sizeof(DWORD));


Добавлено через 12 часов 3 минуты
Возникла идея, кто может подсказать где на сервере(l2jserver или l2emu HF, можно любой другой где открытые исходники) сделать вывод того что отправляется на клиент (конкретно это сесионные ключи)? Лучше то место где еще не шифруется.

Все проверил, вроде верно. Есть предположение что не правильно получаю SessionKey2_1 и SessionKey2_2. Первые два скорее всего верно так как там потом с помощью их получам список серверов.
Это верно?:

// 0x07
public void LS_PlayOk(byte[] buff, int len){
if (len < 11){
return;
}
System.arraycopy(buff, 3, SK2_1, 0, 4);
System.arraycopy(buff, 7, SK2_2, 0, 4);
System.out.println("Авторизация на логин-сервере прошла успешно");
}

Demion
22.02.2012, 20:16
BYTE LSLogin(BYTE *buf, DWORD size, DWORD *SessionKey1, DWORD *SessionKey2, BLOWFISH_CTX *BlowFish)
{
if (size >= 10)
{
memcpy(SessionKey1, buf+3, sizeof(DWORD));
memcpy(SessionKey2, buf+7, sizeof(DWORD));
}
return buf[2];
}

BYTE LSPlay(BYTE *buf, DWORD size, DWORD *SessionKey3, DWORD *SessionKey4, BLOWFISH_CTX *BlowFish)
{
if (size >= 10)
{
memcpy(SessionKey3, buf+3, sizeof(DWORD));
memcpy(SessionKey4, buf+7, sizeof(DWORD));
}
return buf[2];
}

У меня так. А отправляется потом на ГС в таком порядке 4 3 1 2 (видно из предыдущих исходников)

---

wcslen - кол-во символов в юникод строке
wcslen*2+2 - длина строки в байтах
+1 - это смещение (ИД)

Tin-moon
23.02.2012, 12:17
Поставил отпечатку на сервере. Итог, данные которые отправляет читаю верно (сесионные ключи, пакет KeyPacket - 8 байт ключа). Отправляю данные на сервер после хор, он их пытается читать но .... Видимо все -таки неправильно отправляю.
Вот код:

byte[] temp = HelpFunctions.FillZero(100);
byte[] login = HelpFunctions.StringToWideString(gs.getData().getL OGIN());
int len = login.length;

temp[0] = 0x2b;
System.arraycopy(login, 0, temp, 1, len);

System.arraycopy(gs.getData().getSessionKey2_1b(), 0, temp, len, 4);
System.arraycopy(gs.getData().getSessionKey2_2b(), 0, temp, len, 4);
System.arraycopy(gs.getData().getSessionKey1_1b(), 0, temp, len, 4);
System.arraycopy(gs.getData().getSessionKey1_2b(), 0, temp, len, 4);

// блок 01 00 00 00
temp[len+17] = 1;

int to_copy = len+con.length;

byte[] send = HelpFunctions.FillZero(to_copy);
System.arraycopy(temp, 0, send, 0, to_copy);
gs.SendPKT(send, 1);

Demion
23.02.2012, 19:55
System.arraycopy(login, 0, temp, 1, len);

у тебя копирует с нуль символом? Если это string, то, на сколько я помню, оно возвращает кол-во символов. А юникод строка занимает по 2 байта на символ + 2 байта на нуль символ.

---

Не углядел, что там масив, а не стринг. Тогда скорее всего проблема в шифровке. Позже посмотрю твой код

Tin-moon
24.02.2012, 12:36
в моём случае это не прокатит :) Я пишу под андроид))) немного забросил проект так как на мед обследовании, позже вернусь к проекту :) прошёл первый пакет)) дальше на этапе отправки 1 пакета от клиента серверу остановился)))

Как продвижение??

Tin-moon
24.02.2012, 22:57
Вот лог игрового сервера при подключении к нему с моего клиента:

Добавлено через 1 час 9 минут
Нашел совершенно случайно причину. Продолжаю дальше. Спасибо всем кто откликнулся на предыдущие вопросы. Возможно будут новые :spiteful::D

Demion
25.02.2012, 00:11
Обычно принято писать решение ошибки, может кому то пригодится ;)

Tin-moon
25.02.2012, 23:53
Дописал. Чат работает. Остались мелочи...:good:

Заметил что есть проблемы с кодировкой при чтении. Неправильная интерпретация некоторых символов. немогу подобрать кодировку. Что за она?

Добавлено через 6 часов 6 минут
Поискал ошибку, оказалась что проблема не в кодировке. Почему-то портятся некоторые байты.. Предположение на ХОР.

Это получаю в l2ph

4A E1 07 01 10 00 00 00 00
50 00 50 00 5A 00 00 00
FF FF FF FF
3F 04 40 04 38 04 32 04 35 04 42 04 00 00

Это получаю в своим

4a e1 07 01 10 00 00 00 34
57 00 50 00 5a 00 00 00
ff ff ff ff
3f 04 40 30 3f 04 32 04 35 04 42 04 00 00

Что это может быть?

Добавлено через 47 минут
http://rghost.ru/36707795/image.png
Кто може подсказать? После отправки пакета CharSelected приходят 2 пакета от гейм сервера. И после отправляем 2 пакета от клиента. Так вот у меня почему-то после CharSelected приходит только 1 пакет.. и на этом висит, если не отправить следующие 2 ничего не будет.
Таже история и после 2 пакетов Request.....
Я вот думаю, что возможно поэтому возникает проблема с чатом.

NLObP
26.02.2012, 00:04
Tin-moon, обнови пакетхак, будет показывать названия пакетов.

Tin-moon
26.02.2012, 00:07
Tin-moon, обнови пакетхак, будет показывать названия пакетов.
Названия не так важно ), а где обновить? Это - l2phx.3.5.34.175. Все нашел обновил.


Ого тут совсем другие данные. NLObP спасибо.

NLObP
26.02.2012, 00:10
Tin-moon, тута (http://l2ph.coderx.ru/arhive/).

Tin-moon
26.02.2012, 14:38
http://rghost.ru/36708625/image.png
Вопрос тот же, но с уточнением. За что отвечает пакет ActionFailed? Раз это ошибка то он не обязательно будет?

Последил за изменением ХОР ключа:
-126 -103 -72 -67 26 -76 62 -46 18 -116 -109 1 -95 108 49 -105
То что красным меняется не верно... что это может быть?

Добавлено через 14 часов 1 минуту
Количество зашифрованных Хор пакетов на севере должно совпадать с количеством расшифрованных клиентом??? У меня например клиент расшифровал 7, а сервер зашифровал уже 106....

ErgoZ
26.02.2012, 19:35
Tin-moon, помоги плиз, поделись функцией добавления чексуммы под яву, а то никак не могу отправить с клиента пакеты, сервер говорит что чексумма не правильная.

Заранее спасибо.

п.с. полностью произвёл рефакторинг приложения, переписал классами и раскидал по папкам, любо дорого смотреть)))

Tin-moon
27.02.2012, 11:30
Tin-moon, помоги плиз, поделись функцией добавления чексуммы под яву

public static void AddCheckSumm(byte[] Data, int len) {
if(Data.length < len + 4){
return null;
}

byte[] t = new byte[4];

int chksum = 0;
int ecx = 0;
int i = 0;

while (i < len){
t[0] = Data[i];
t[1] = Data[i+1];
t[2] = Data[i+2];
t[3] = Data[i+3];
try {
ecx = HelpFunctions.toInt(t, 0);
chksum ^= ecx;
i += 4;
} catch (Exception ex) {
Logger.getLogger(Functions.class.getName()).log(Le vel.SEVERE, null, ex);
}
}
System.arraycopy(BitConverter.getBytes(chksum)), 0, t, 0, 4);
Data[len] = t[0];
Data[len+1] = t[1];
Data[len+2] = t[2];
Data[len+3] = t[3];
}

ErgoZ
27.02.2012, 12:21
Странно, он у меня из такого пакета:
07 3D 49 52 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Сделал такой:
00 00 00 00 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00


Что нужно передавать в твою функцию? Я так понимаю Data - это тот пакет, к которому будем добавлять чексумму, а вот что такое len я так и не понял, это вроде должно быть размером пакета, или оффсет? Честно говоря вот этот момент не смог разобрать, подскажи плиз.

Tin-moon
27.02.2012, 12:39
Что нужно передавать в твою функцию? Я так понимаю Data - это тот пакет, к которому будем добавлять чексумму, а вот что такое len я так и не понял, это вроде должно быть размером пакета, или оффсет? Честно говоря вот этот момент не смог разобрать, подскажи плиз.

Да дата это пакет. Длина - это помоему что-то на подобии оффсета(потому что передаем не все). Чесно проблем с переписыванием этой функции небыло поэтому не загонялся.

ErgoZ
27.02.2012, 12:44
Хм... странно.. ладно, приеду в офис гляну внимательнее... но всё же с этим "оффсетом" не могу никак сообразить.. надо исходники глянуть будет л2пх

Tin-moon
27.02.2012, 12:51
Хм... странно.. ладно, приеду в офис гляну внимательнее... но всё же с этим "оффсетом" не могу никак сообразить.. надо исходники глянуть будет л2пх
Не разу не смотрел) может тебе и поможет.
По поводу оффсета:

procedure LS_RequestServerLogin;
var
Data: array[0..31] of byte;
begin
FillChar(Data,Length(Data),0);
Data[0]:=2;
Move(SessionKey1_1,Data[1],4);
Move(SessionKey1_2,Data[5],4);
Data[9]:=GS_ID;
AddCheckSumm(Data,16);
SendPkt(Data,32);
end;

ErgoZ
27.02.2012, 13:27
Странно, вроде смог победить чексумм, но вылезла новая проблема....

Вот это отправляет клиент:
2A 00 07 C4 F8 36 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1E C4 F8 36 00 00 00 00 00 00 00 00 00 00 00 00
или
2A 00 07 47 B9 AE 4B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4C 47 B9 AE 00 00 00 00 00 00 00 00 00 00 00 00



Это отправляю я:
2A 00 07 3A 97 AF 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 3A 97 AF 00 00 00 00 00 00 00 00 00 00 00 00
или
2A 00 07 28 B6 C1 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 28 B6 C1 00 00 00 00 00 00 00 00 00 00 00 00

Вроде всё должно быть нормально и правильно, но сервер отвечает на мой пакет:
Wrong checksum from client: [127.0.0.1]
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Unknown Source)
at com.l2j.netcore.MMOConnection.close(MMOConnection. java:293)
at com.l2j.netcore.MMOConnection.close(MMOConnection. java:260)
at com.l2j.loginserver.L2LoginClient.decrypt(L2LoginC lient.java:130)
at com.l2j.netcore.SelectorThread.parseClientPacket(S electorThread.java:433)
at com.l2j.netcore.SelectorThread.tryReadPacket(Selec torThread.java:379)
at com.l2j.netcore.SelectorThread.readPacket(Selector Thread.java:309)
at com.l2j.netcore.SelectorThread.run(SelectorThread. java:179)
DISCONNECTED: [127.0.0.1]

А на эмулятор клиента не ругается, всё норм (la2_client_emu, тут его в этой теме вроде выкладывали).

Tin-moon
27.02.2012, 13:45
Wrong checksum from client: [127.0.0.1]
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Unknown Source)
at com.l2j.netcore.MMOConnection.close(MMOConnection. java:293)
at com.l2j.netcore.MMOConnection.close(MMOConnection. java:260)
at com.l2j.loginserver.L2LoginClient.decrypt(L2LoginC lient.java:130)
at com.l2j.netcore.SelectorThread.parseClientPacket(S electorThread.java:433)
at com.l2j.netcore.SelectorThread.tryReadPacket(Selec torThread.java:379)
at com.l2j.netcore.SelectorThread.readPacket(Selector Thread.java:309)
at com.l2j.netcore.SelectorThread.run(SelectorThread. java:179)
DISCONNECTED: [127.0.0.1]

Сервер уверен :pleasantry: что чек сумма неверная, значит что-то не так. Но по крайней мере уже похоже на правду....

ErgoZ
27.02.2012, 23:01
Да в том то и дело что похоже на правду, но сервер меня посылает далеко, и явно не на хутор))

Я не могу понять где у меня косяк. Тин, если не трудно, возьми мои пакеты, покажи какая чексумма должна быть, мне кажется у меня где-то расчёт идёт не правильно, может это из-за андроида, хз, но затык именно тут.

Сессия 1 - 3A 97 AF 4E
Сессия 2 - 28 B6 C1 26

Добавлено через 4 часа 2 минуты
только что отловил сессию из la2_client_emu, подставил сессию в свою функцию, всё сходится, пакеты полностью одинаковы получаются... возможно я не правильно беру сессию, может не те байты... может ли из-за этого быть ошибочный чексумм? сервер проверяет сессию в пакете и ту сессию что он отправлял? вообще очень странно..

Добавлено через 1 час 45 минут
проверил получение ID сессии.. всё норм.. не пойму где проблема...

Пакет с моей софтины: 2A 00 07 4E 72 6D 0E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 4E 72 6D 00 00 00 00 00 00 00 00 00 00 00 00

Пакет с la2_client_emu: 2A 00 07 4E 72 6D 0E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 4E 72 6D 00 00 00 00 00 00 00 00 00 00 00 00

Чё за бред... и пишет что не правильная чек сумма, однако при отправке через клиент эму - ошибок не выдаёт, а через андроид - сразу на чек сумму ругается...

Добавлено через 2 часа 7 минут
нашёл косяк, спасибо wpepro! я отправлял на сервер пакет ГГ не закриптованный по блоуфишу!!! Т.е. как сформировал его сразу отправлял, а его перед отправкой нужно криптануть по ключу, как я понял из инита. )))

Tin-moon
27.02.2012, 23:32
ErgoZ Как ты организуешь архитектуру клиента. Как обрабатываешь данные из сокета (всмысле как работаешь с сокетом)? Выделяешь в поток или как?
Просто это я к чему, у меня ща проблема в том что сервер отправляет пакеты а мой клиент почему-то их не обрабатывает. А начинает через определенное время... немогу понять в чем дело...

ErgoZ
28.02.2012, 00:17
В данный момент продвинулся до RequestAuthLogin... пытаюсь сформировать пакет... на сколько понимаю первые 128 байт это логин+пароль, потом нули, и это нужно будет ещё обработать ключём рса, который мы получаем из инита и дескрамблируем, после этого некодированные 14 байт логина и 16 байт пароля? И вопрос, нужно ли это блоуфишить, если да, то каким ключём, с инита? вроде в ггаус от сервера ключа небыло, или я ошибаюсь?

Добавлено через 14 минут
Тин, учитывая что это, по сути, моя первая софтина на яве, я сделал отдельный класс, в нём создал функцию коннекта, получения пакета и отправки.

Короче вот код, думаю ты сможешь понять:

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;

public class L2Socket {

static Socket la2_socket = new Socket();
static InetAddress AddrAsIAddr = null;

public static void connect(){
try {
AddrAsIAddr = InetAddress.getByName(Constants.hostname);
} catch (Exception e) {
System.err.println("Could not get IP-address");
};

try {
SocketAddress adr = new InetSocketAddress(AddrAsIAddr,Constants.port_ls);
System.out.println("Socket configured");
la2_socket.connect(adr, 3000);
System.out.println("Connected to "+AddrAsIAddr+":"+Constants.port_ls);
}
catch (SocketTimeoutException e) {
System.err.println(e);
}
catch (IOException e) {
System.err.println(e);
}
catch (Exception e) {
System.err.println(e+" | Could not establish socket!");
};
}

public static byte[] recivePKG(int size){
byte[] buf = new byte[size];
if(la2_socket.isConnected()) {
//System.out.println("la2_socket is Connected");
try {
la2_socket.getInputStream().read(buf);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return buf;
}

public static void SendPKG(byte[] buf){
try {
la2_socket.getOutputStream().write(buf);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void close(){
try {
la2_socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


}


Потом после SendPKG я сразу запускаю recivePKG. Но это на этапе логин сервера. В геймсервере планирую сделать архитектуру, где будет что-то типа:

// Цикл до тех пор, пока есть поступающие сообщения
while (la2_socket.isConnected()) { //пока сокет подключен
//Отображаем полученное сообщение
System.out.println("Server: " + recivePKG(тут я придумаю расчёт размера));
}

Ну и внутри этого цикла сделать обработку по типу пакета, что мол если пакет типа Say или Say2 (не помню что за чат отвечает), то работать с пакетом, если нет то не обращать внимания.

Я понимаю что код нубский, не судите строго.

ErgoZ
28.02.2012, 00:22
Кстати решил зашарить код, который я написал для удобства определения типа пакета по его направлению и типу и вывод это в println

package com.ergoz.mychat.functions;

public class LogPKG {

public static void log_LS_CS(byte[] buf) { //пакет клиент -> лс
byte dst = buf[0];

switch(dst) {
case (byte) 0x00: System.out.println("RequestAuthLogin"); break;
case (byte) 0x02: System.out.println("RequestServerLogin"); break;
case (byte) 0x05: System.out.println("RequestServerList"); break;
case (byte) 0x07: System.out.println("RequestGGAuth"); break;
default: System.out.println ("Отправлен неопределённый пакет.");
}
//System.out.println (dst[0]+dst[1]);
}

public static void log_LS_SC(byte[] buf) { //пакет лс-> клиент
byte dst = buf[0];

switch(dst) {
case (byte) 0x00: System.out.println("Init"); break;
case (byte) 0x01: System.out.println("LoginFail"); break;
case (byte) 0x02: System.out.println("AccountKicked"); break;
case (byte) 0x03: System.out.println("LoginOk"); break;
case (byte) 0x04: System.out.println("ServerList"); break;
case (byte) 0x06: System.out.println("PlayFail"); break;
case (byte) 0x07: System.out.println("PlayOk"); break;
case (byte) 0x0B: System.out.println("GGAuth"); break;
default: System.out.println ("Получен неопределённый пакет.");
}
}


public static void log_GS_CS(byte[] buf) { //пакет клиент -> гс
byte dst = buf[0];

switch(dst) {
case (byte) 0x00: System.out.println("ProtocolVersion"); break;
case (byte) 0x01: System.out.println("MoveBackwardToLocation"); break;
case (byte) 0x02: System.out.println("Say"); break;
case (byte) 0x03: System.out.println("EnterWorld"); break;
case (byte) 0x04: System.out.println("Action"); break;
case (byte) 0x08: System.out.println("AuthRequest"); break;
case (byte) 0x09: System.out.println("Logout"); break;
case (byte) 0x0A: System.out.println("AttackRequest"); break;
case (byte) 0x0B: System.out.println("CharacterCreate"); break;
case (byte) 0x0C: System.out.println("CharacterDelete"); break;
case (byte) 0x0D: System.out.println("CharacterSelected"); break;
case (byte) 0x0F: System.out.println("RequestItemList"); break;
case (byte) 0x11: System.out.println("RequestUnEquipItem"); break;
case (byte) 0x12: System.out.println("RequestDropItem"); break;
case (byte) 0x14: System.out.println("UseItem"); break;
case (byte) 0x15: System.out.println("TradeRequest"); break;
case (byte) 0x16: System.out.println("AddTradeItem"); break;
case (byte) 0x17: System.out.println("TradeDone"); break;
case (byte) 0x1B: System.out.println("RequestSocialAction"); break;
case (byte) 0x1C: System.out.println("ChangeMoveType - устарел"); break;
case (byte) 0x1D: System.out.println("ChangeWaitType - устарел"); break;
case (byte) 0x1E: System.out.println("RequestSellItem"); break;
case (byte) 0x1F: System.out.println("RequestBuyItem"); break;
case (byte) 0x21: System.out.println("RequestBypassToServer"); break;
case (byte) 0x24: System.out.println("RequestJoinPledge"); break;
case (byte) 0x25: System.out.println("RequestAnswerJoinPledge"); break;
case (byte) 0x26: System.out.println("RequestWithdrawalPledge"); break;
case (byte) 0x27: System.out.println("RequestOustPledgeMember"); break;
case (byte) 0x29: System.out.println("RequestJoinParty"); break;
case (byte) 0x2A: System.out.println("RequestAnswerJoinParty"); break;
case (byte) 0x2B: System.out.println("RequestWithDrawalParty"); break;
case (byte) 0x2C: System.out.println("RequestOustPartyMember"); break;
case (byte) 0x2F: System.out.println("RequestMagicSkillUse"); break;
case (byte) 0x30: System.out.println("Appearing"); break;
case (byte) 0x33: System.out.println("RequestShortCutReg"); break;
case (byte) 0x35: System.out.println("RequestShortCutDel"); break;
case (byte) 0x37: System.out.println("RequestTargetCanceld"); break;
case (byte) 0x38: System.out.println("Say2"); break;
case (byte) 0x3C: System.out.println("RequestPledgeMemberList"); break;
case (byte) 0x3F: System.out.println("RequestSkillList"); break;
case (byte) 0x40: System.out.println("AnswerTradeRequest"); break;
case (byte) 0x45: System.out.println("RequestActionUse"); break;
case (byte) 0x46: System.out.println("RequestRestart"); break;
case (byte) 0x48: System.out.println("ValidatePosition"); break;
case (byte) 0x4A: System.out.println("StartRotating"); break;
case (byte) 0x4B: System.out.println("FinishRotating"); break;
case (byte) 0x4D: System.out.println("RequestStartPledgeWar"); break;
case (byte) 0x4F: System.out.println("RequestStopPledgeWar"); break;
case (byte) 0x55: System.out.println("RequestGiveNickName"); break;
case (byte) 0x58: System.out.println("RequestEnchantItem"); break;
case (byte) 0x59: System.out.println("RequestDestroyItem"); break;
case (byte) 0x5E: System.out.println("RequestFriendInvite"); break;
case (byte) 0x5F: System.out.println("RequestAnswerFriendInvite"); break;
case (byte) 0x60: System.out.println("RequestFriendList"); break;
case (byte) 0x61: System.out.println("RequestFriendDel"); break;
case (byte) 0x62: System.out.println("CharacterRestore"); break;
case (byte) 0x63: System.out.println("RequestQuestList"); break;
case (byte) 0x64: System.out.println("RequestQuestAbort"); break;
case (byte) 0x66: System.out.println("RequestPledgeInfo"); break;
case (byte) 0x68: System.out.println("RequestPledgeCrest"); break;
case (byte) 0x6A: System.out.println("RequestRide"); break;
case (byte) 0x6B: System.out.println("RequestAquireSkillInfo"); break;
case (byte) 0x6C: System.out.println("RequestAquireSkill"); break;
case (byte) 0x6D: System.out.println("RequestRestartPoint"); break;
case (byte) 0x6E: System.out.println("RequestGMCommand"); break;
case (byte) 0x6F: System.out.println("RequestPartyMatchConfig"); break;
case (byte) 0x70: System.out.println("RequestPartyMatchList"); break;
case (byte) 0x71: System.out.println("RequestPartyMatchDetail"); break;
case (byte) 0x72: System.out.println("RequestCrystallizeItem"); break;
case (byte) 0x77: System.out.println("SetPrivateStoreMsgSell"); break;
case (byte) 0x81: System.out.println("RequestGmList"); break;
case (byte) 0x82: System.out.println("RequestJoinAlly"); break;
case (byte) 0x83: System.out.println("RequestAnswerJoinAlly"); break;
case (byte) 0x84: System.out.println("AllyLeave"); break;
case (byte) 0x85: System.out.println("AllyDismiss"); break;
case (byte) 0x88: System.out.println("RequestAllyCrest"); break;
case (byte) 0x89: System.out.println("RequestChangePetName"); break;
case (byte) 0x8A: System.out.println("RequestPetUseItem"); break;
case (byte) 0x8B: System.out.println("RequestGiveItemToPet"); break;
case (byte) 0x8C: System.out.println("RequestGetItemFromPet"); break;
case (byte) 0x8E: System.out.println("RequestAllyInfo"); break;
case (byte) 0x8F: System.out.println("RequestPetGetItem"); break;
case (byte) 0x94: System.out.println("SetPrivateStoreMsgBuy"); break;
case (byte) 0x98: System.out.println("RequestStartAllianceWar"); break;
case (byte) 0x9A: System.out.println("RequestStopAllianceWar"); break;
case (byte) 0xA0: System.out.println("RequestBlock"); break;
case (byte) 0xA2: System.out.println("RequestSiegeAttackerList"); break;
case (byte) 0xA4: System.out.println("RequestJoinSiege"); break;
case (byte) 0xA8: System.out.println("NetPing"); break;
case (byte) 0xAC: System.out.println("RequestRecipeBookOpen"); break;
case (byte) 0xB9: System.out.println("RequestEvaluate"); break;
case (byte) 0xBA: System.out.println("RequestHennaList"); break;
case (byte) 0xBB: System.out.println("RequestHennaItemInfo"); break;
case (byte) 0xBC: System.out.println("RequestHennaEquip"); break;
case (byte) 0xC1: System.out.println("RequestMakeMacro"); break;
case (byte) 0xC2: System.out.println("RequestDeleteMacro"); break;
case (byte) 0xCF: System.out.println("RequestAutoSoulShot"); break; //тут надо ещё D0 пакет над вставить но лень
case (byte) 0xEE: System.out.println("RequestChangePartyLeader"); break;
default: System.out.println ("Получен неопределённый пакет.");
}
}

public static void log_GS_SC(byte[] buf) { //пакет гс -> клиент
byte dst = buf[0];

switch(dst) {
case (byte) 0x00: System.out.println("CryptInit"); break;
case (byte) 0x01: System.out.println("MoveToLocation"); break;
case (byte) 0x04: System.out.println("UserInfo"); break;
case (byte) 0x0E: System.out.println("StatusUpdate"); break;
case (byte) 0x13: System.out.println("CharList"); break;
case (byte) 0x14: System.out.println("AuthLoginFail"); break;
case (byte) 0x19: System.out.println("CharCreateOk"); break;
case (byte) 0x1A: System.out.println("CharCreateFail"); break;
case (byte) 0x23: System.out.println("CharDeleteOk"); break;
case (byte) 0x24: System.out.println("CharDeleteFail"); break;
case (byte) 0x25: System.out.println("ActionFailed"); break;
case (byte) 0x2F: System.out.println("ChangeWaitType"); break;
case (byte) 0x38: System.out.println("TeleportToLocation"); break;
case (byte) 0x3E: System.out.println("ChangeMoveType"); break;
case (byte) 0x7E: System.out.println("LogoutOK"); break;
case (byte) 0x80: System.out.println("QuestList"); break;
case (byte) 0xD3: System.out.println("NetPingRequest"); break;
case (byte) 0xAF: System.out.println("ServerSocketClose"); break;
case (byte) 0xE1: System.out.println("ChairSit"); break;
case (byte) 0xFE: System.out.println("ExSendManorList"); break;
default: System.out.println ("Получен неопределённый пакет.");
}
}


}



Опять же напоминаю, я нуб в яве, я веб прогер)))

ErgoZ
28.02.2012, 05:22
Тин, не поделишься формированием пакета RequestAuthLogin, а то немного запутался в нём...

Добавлено через 53 минуты
не совсем понял как его шифровать, как перегнать в аски формат логин и пароль, в общем этот пакет я так и не понял вообще :(

Добавлено через 2 часа 46 минут
в общем я застрял на этапе РСА шифрования логина и пароля, поделитесь под яву, плиз, а то всё какой то бред получается... в итоге не могу отправить этот пакет :(

Добавлено через 1 час 19 минут
мой рса кодер почему то выдаёт такую хрень:

02-28 00:19:20.517: E/AndroidRuntime(1654): java.lang.ArithmeticException: BigInteger: modulus not positive

Ошибка вот тут: r = d.modPow(exp, m);
Я так понимаю что это из-за того что m становится 0 или меньше 0... но

Вот мой рсаэнкодер и репейр кей (я так понимаю это и есть унскрамблер):

public static byte[] RepairKey(byte[] key)
{
byte[] k = new byte[128];
int i;
byte temp;

if (key.length != 128) return null;
System.arraycopy(key, 0, k, 0, 128);

for (i = 0; i < 0x40; i++)
k[0x40 + i] = (byte)(k[0x40 + i] ^ k[i]);

for (i = 0; i < 4; i++)
k[0x0d + i] = (byte)(k[0x0d + i] ^ k[0x34 + i]);

for (i = 0; i < 0x40; i++)
k[i] = (byte)(k[i] ^ k[0x40 + i]);

for (i = 0; i < 4; i++)
{
temp = k[0x00 + i];
k[0x00 + i] = k[0x4d + i];
k[0x4d + i] = temp;
}

return k;
}

public static byte[] RSAEncrypt(String a, String p, byte[] rsakey)
{
String sD;
byte[] sD_temp, sM_temp;
int len;

BigInteger m, exp, d, r;

while (a.length() < 14) a = a + (byte)0x00;
while (p.length() < 16) p = p + (byte)0x00;

sD = a + p + (byte)0x00 + (byte)0x00 + (byte)0x00 + (byte)0x00;
System.out.println(sD);
sM_temp = rsakey;
sD_temp = new byte[37];
sD_temp[0] = 0x24;
System.arraycopy(sD.getBytes(), 0, sD_temp, 3, 34);

len = sD_temp.length;
d = new BigInteger(sD_temp);
m = new BigInteger(sM_temp);
exp = BigInteger.valueOf(65537);

r = d.modPow(exp, m);

byte [] sR = new byte[128];

System.arraycopy(r.toByteArray(), 0, sR, 0, r.toByteArray().length);

return sR;
}

Tin-moon
28.02.2012, 13:02
Нашел в чем проблема. Кто может объяснить?
Ситуация следующая:
Когда сканю пакеты в l2ph там видно что их приходит много. Общий размер после EnterWord до того как клиент начинает отправлять новые пакет = 4930 байт. Мой клиент также после EnterWord получает 4930 байт, но эти 4930 байт не целой кучей пакетов а всего 2... как решить эту проблему??

ErgoZ
28.02.2012, 13:14
Выложи свою софтину скомпиленную, попробую соснифать, может коллективным разумом решим эту проблему

Tin-moon
28.02.2012, 14:20
Решил поснифать трафик. Вывод нормальному клиенту приходит тоже 2 здоровых пакета. Как его потом разбирать? Всмысле брать разбивать на куски? Тогда как следить за размером? И "Хорить" нужно эти 2 большие или те которые разбили??

Пробовал найти решение в исходниках l2ph, что-то не увидел...

ErgoZ
28.02.2012, 14:22
может оно бьётся по MAX_PKT_SIZE или как там переменная зовётся, уже не помню, видел в исходниках, вроде... думаю ксорится по отдельности как самостоятельные пакеты, вообще надо смотреть исходники сервера, наверное, на предмет того как формируются пакеты.

sko
28.02.2012, 15:00
Чтобы не гонять много мелких пакетов по сети, они склеиваются в один побольше.

Расклеить их просто. С самого начала идут 2 не зашифрованных байта, это размер первого пакета. Сдвигаемся на этот размер, там опять 2 байта, это размер второго пакета и т.д.

Ксорить надо мелкие.

Aries
28.02.2012, 22:11
Ребят вы бы азы хоть немного подучили)))
Нигде ничего не склеивается в какие-то пакеты "побольше".
TCP/IP - это потоковый протокол. Все данные передаются тупо в едином потоке.
Ну а как сказал sko, уже для разделения пакетов на программном уровне, перед началом передаваемой структуры пишется ее размер.

И да, сразу совет. Не считывайте все данные из сокета, как те только туда пришли, т.к. может быть ситуация, что пришла только часть пакета.

Поэтому логика правильного разбора пакетов должна быть такая:
считывается размер пакета из потока. Далее проверяется сколько байт доступно в потоке. Если байт не достаточно, то необходимо ждать, пока придет остальная часть. Далее считывается столько байт, какой размер указан вначале, а опять же не все данные из сокета. Ну и т.д. повторяется...

Tin-moon
29.02.2012, 00:48
Все теперь работает как надо:victory:

sko
29.02.2012, 13:08
Aries, спасибо за дополнение. Вот тут есть пример (http://svn.assembla.com/svn/L2jOfficial/branches/L2_Gracia_Final_T2.3/lin2srv/java/net/sf/l2j/gameserver/LoginServerThread.java) разбора входящего потока на пакеты.


while (true){
lengthLo = _in.read();
lengthHi = _in.read();
length = lengthHi * 256 + lengthLo;

if (lengthHi < 0)
{
_log.finer("LoginServerThread: Login terminated the connection.");
break;
}

byte[] incoming = new byte[length];
incoming[0] = (byte) lengthLo;
incoming[1] = (byte) lengthHi;

int receivedBytes = 0;
int newBytes = 0;
while (newBytes != -1 && receivedBytes < length - 2)
{
newBytes = _in.read(incoming, 2, length - 2);
receivedBytes = receivedBytes + newBytes;
}

if (receivedBytes != length - 2)
{
_log.warning("Incomplete Packet is sent to the server, closing connection.(LS)");
break;
}
}

ErgoZ
29.02.2012, 14:04
ребят, выручите плиз, скиньте функции дешифровки РСА ключа (дескрамбл), и саму функцию РСА шифрования, плиз. И вообще нужно ли на интерлюде делать дескрамбл рса ключа из пакета инит, или используем инитовский ключ как есть? в исходниках сервера вроде нету ничего связанного с кодированием рсашки

Вообще проблемка с РСА, у меня иногда рса ключ имеет отрицательное значение (если перевести его в бигинтегер), и из-за этого вылетает ошибка:
java.lang.ArithmeticException: BigInteger: modulus not positive

а если ошибка не вылетает (т.е. рса положительный), то в консоли логин сервера пишет такое:
Created new account : я┐╜p--"#я┐╜╤Зя┐╜▐Юя┐╜ on IP : 127.0.0.1

Я не могу понять, это проблема в РСА, в дескрамбле, или потому что кодировку неправильную выбрал для логина и пароля... и как исправить ошибку modulus not positive

glukmaker
29.02.2012, 15:17
И да, сразу совет. Не считывайте все данные из сокета, как те только туда пришли, т.к. может быть ситуация, что пришла только часть пакета.


Правда гуру почему-то советуют все же считывать все данные с сокета в буфер и уже в буфере разбирать их по пакетам...

Вот, когда-то интересовался подобным вопросом.
http://delphimaster.ru/cgi-bin/forum.pl?id=1319485327&n=4

пришлось вместо первоначального варианта:
type TPacket: packed record
case boolean of
true: (buf: array[0..8191] of byte;);
false: (len:word;
typepack:byte;);
end;

var
Packet:TPacket;

...
begin
while true do
begin
if recv(FSocket,Packet,2,MSG_PEEK)<2 then Exit;
if recv(FSocket,Packet,Packet.len,MSG_PEEK)<packet.len then Exit;
recv(FSocket,Packet,Packet.len,0);
Obrabotka(Packet); // функция обработки пакета
end;
end;



переписать приблизительно так (ну это мой вариант на тот момент, сейчас он уже еще доработан, но исходники не при мне):

...
private
FBuffer: packed array[0..8191] of byte;
FStartBuffer:integer;
FEndBuffer:integer;
...

procedure TMyClass.ReceivePackets;
var
s:Integer;
begin
s:=recv(FSocket,FBuffer[FEndBuffer],length(FBuffer)-FEndBuffer,0);

// тут нужно обработать возможные ошибки.

inc(FEndBuffer,s);
while true do
begin
if FEndBuffer-FStartBuffer<2 then Break;
move(FBuffer[FStartBuffer],Fpacket,2);
if FPacket.len>sizeof(FPacket) then
begin
// Тут нужно закрыть сокет, и сгенерировать исключение
// так как прием таких пакетов не планируется
Exit;
end;
if FEndBuffer-FStartBuffer<Fpacket.len then Break;
move(FBuffer[FStartBuffer],FPacket,Fpacket.len);
inc(FstartBuffer,Fpacket.len); // увеличиваем значение стартовой позиции буфера на величину забранных данных
if FGame then ProcessingGame else ProcessingAuth; // обработка выделенного пакета
end;

// Оптимизация буфера (чтобы обойтись без постоянных сдвигов буфера
// сдвигать будем только при крайней необходимости)

// Если буфер пустой, устанавливаем позиции начала и конца на 0
if FStartBuffer>=FEndBuffer then
begin
FStartBuffer:=0;
FEndBuffer:=0;
end;
// Оцениваем длину свободного хвоста буфера, если он менее 2 кб, то сдвигаем данные к началу буфера
if length(FBuffer)-FEndBuffer<2048 then
begin
move(FBuffer[FStartBuffer],FBuffer[0], FEndBuffer-FStartBuffer);
FEndBuffer:=FEndBuffer-FStartBuffer;
FStartBuffer:=0;
end;
end;

Aries
29.02.2012, 15:45
Правда гуру почему-то советуют все же считывать все данные с сокета в буфер и уже в буфере разбирать их по пакетам...


ну собственная буферизация имеет смысл только в том случае если обработка данных слишком долгая, и возможно переполнение буфера сокета.

ErgoZ
01.03.2012, 23:35
Ребят. помогите плиз. Вопрос в этом сообщении http://coderx.ru/showpost.php?p=181717&postcount=154

Demion
02.03.2012, 05:01
VOID unscrambleRSAKey(BYTE *n)
{
INT i;

for(i=0; i<0x40; i++)
n[0x40 + i] = (BYTE)(n[0x40 + i] ^ n[i]);

for(i=0; i<4; i++)
n[0x0d + i] = (BYTE)(n[0x0d + i] ^ n[0x34 + i]);

for(i=0; i<0x40; i++)
n[i] = (BYTE)(n[i] ^ n[0x40 + i]);

for(i=0; i<4; i++)
{
BYTE temp = n[0x00 + i];
n[0x00 + i] = n[0x4d + i];
n[0x4d + i] = temp;
}
}

Sherman
02.03.2012, 14:18
ну собственная буферизация имеет смысл только в том случае если обработка данных слишком долгая, и возможно переполнение буфера сокета.

Несогласен, т.к. своя буферизация еще и избавляет от проблем связанных с приемом данных из разных фреймов. Если пришел не полный пакет, отпадает необходимость ожидания дочитывания остатка, а такое по моему опыту бывает часто, когда прилетает нецелое количество пакетов. Можно спокойно отпустить сокет для приема дальше, и заняться обработкой имеющихся полных пакетов. Ассинхронное использование сокета короче.

ErgoZ
02.03.2012, 14:53
Demion, проблема в том, что этот код пробовал использовать, я ему скармливаю свой рса ключ, а в ответ он отдаёт его же, т.е. ничего не изменив... может у меня рса не закодирован???

Добавлено через 6 минут
и проблема в том что вышибает постоянно вот эта ошибка (через раз) :

java.lang.ArithmeticException: BigInteger: modulus not positive

Я понимаю что это потому что после перевода ключа в биг интегер оно может иметь отрицательное значение и при использовании функции:
r = d.modPow(exp, m);
Оно вылетает (в переменную m записан биг интегер, полученный из РСА)

cvillian
08.12.2015, 18:37
Вот мой класс BlowFish На C#

Tin-moon
Во вложении 2 файла, те ф-ции, которые ты просил + левый скачанный с инета класс по работе с большими числами, который я использовал в RSAEncrypt.

не компилится :( говорит что в классе Funcs нет методов DeepClone и toByteArray

cvillian
14.12.2015, 06:10
Может поделится кто конектом к логин серверу на с# ? :sorry:

cvillian
16.12.2015, 21:33
запхал дельфийский L2Emu в длл и вызываю её из с# :)
на логин сервер захожу

теперь разобраться бы с кодированием пакетов на с#

Добавлено через 3 часа 8 минут
нашёл что-то, но не похоже что работает:

public static byte[] encrypt(byte[] raw, ref byte[] _key)
{
uint temp = 0;
for (int i = 0; i < raw.Length; i++)
{
uint temp2 = raw & (uint)0xff;
temp = (temp2 ^ _key[i & 15] ^ temp);
raw[i] = (byte)temp;
}

uint old = ((uint)_key[8]) & (uint)0xff;
old |= (uint)(((uint)_key[9]) << 8 & (uint)0xff00);
old |= (uint)(((uint)_key[10] << 0x10) & (uint)0xff0000);
old |= (uint)(((uint)_key[11] << 0x18) & (uint)0xff000000);

old += (uint)raw.Length;

_key[8] = (byte)(old & 0xff);
_key[9] = (byte)(old >> 0x08 & 0xff);
_key[10] = (byte)(old >> 0x10 & 0xff);
_key[11] = (byte)(old >> 0x18 & 0xff);
return raw;
}

[I]Добавлено через 1 час 25 минут
07000A05000000

ЛогинФэйл с кодом 5, что это может быть....

SeregaZ
17.12.2015, 02:19
видимо "за вами уже выехало фсб на черных джыпах" :) я вот без понятия, но ты держись! хоть никто ничо не подсказывает - ты не опускай руки. я вот всегда захожу почитать. так как тема интересная :) сам мечтаю каданить засесть и запилить свою мини-ладву на 2-3 игрока. л2пх это ж практически готовый сервер :) надо то всего пару плюшек в виде глобальных переменных для скриптов и потоки может быть... и это точно будет шедевр :)

cvillian
17.12.2015, 03:11
видимо "за вами уже выехало фсб на черных джыпах" :) я вот без понятия, но ты держись! хоть никто ничо не подсказывает - ты не опускай руки. я вот всегда захожу почитать. так как тема интересная :)
:D

А я решил траблу :)
Стандартный метод int.ToString("X8") - даёт хекс-строку в восемь символов длиной. Но оказалось что эту грёбаную строку нужно перевернуть прежде чем пхать в пакет. Так что логин у меня получился.
Теперь надо парсинг пакетов делать.

А вообще занимаюсь этим потому что изучаю си-шарп, а ничё более путного для тренировки не придумал :)