PDA

Просмотр полной версии : Интересует алгоритм Opcode Obfuscator-а трафика L2


Yegor
22.08.2012, 15:37
Кто то в курсе, алгоритм построения таблицы для обфускатора в клиенте одинаков для разных хроник? У меня периодически проскакивает ошибка, тоесть обфускатор на сервере не правильно декодирует значение при id == 0xD0

private void prepare(int obfKey)
{
_obfKey = obfKey;
int l = 0;
m_decodeTable1 = new int[0xD0 + 1];
m_decodeTable2 = new int[0x83 + 1];
for (int i = 0; i <= 0xD0; ++i)
m_decodeTable1[i] = i;
for (int i = 0; i <= 0x83; ++i)
m_decodeTable2[i] = i;
pseudo_rand_seed(obfKey);
for (int i = 1; i <= 0xD0; ++i)
{
int k = pseudo_rand() % (i + 1);
int j = m_decodeTable1[k];
m_decodeTable1[k] = m_decodeTable1[i];
m_decodeTable1[i] = j;
}
for (int i = 1; i <= 0x83; ++i)
{
int k = pseudo_rand() % (i + 1);
int j = m_decodeTable2[k];
m_decodeTable2[k] = m_decodeTable2[i];
m_decodeTable2[i] = j;
}
for (l = 0; m_decodeTable1[l] != 0x12; l++);
int j = m_decodeTable1[0x12];
m_decodeTable1[0x12] = 0x12;
m_decodeTable1[l] = j;
for (l = 0; m_decodeTable1[l] != 0xB1; l++);
int d = m_decodeTable1[0xB1];
m_decodeTable1[0xB1] = 0xB1;
m_decodeTable1[l] = d;
m_decodeTable1[0xD0] = 0xD0;
m_decodeTable1[0x11] = 0x11;
m_enabled = true;
}

Смущают строки вроде:
m_decodeTable1[0xD0] = 0xD0;

Но если их закомментировать все равно в таблице остается неверное значение.

Где бы почитать про алгоритм обфускации в клиенте, можно ли его там изменит на свой, какая dll и функция за это отвечает?

Elecktron
21.09.2012, 17:51
сейчас тоже столкнулся с этим, только я чтото не могу понять как получается таблица ID..

Yegor
21.09.2012, 18:40
Как в клиенте получается я сам не могу найти, а на сервере там в ядре функция генерации таблицы есть.

Elecktron
21.09.2012, 20:07
клиент подставляет новый ID в send.
где происходит инициализация не искал.
где посмотреть серверную функцию генерации ?

Yegor
21.09.2012, 21:50
В фениксе в классе gameserver.network.OpcodeObfuscator

Функция
public static init_tables(int obfKey)

Elecktron
22.09.2012, 16:54
у некоторых пакетов ID не меняется. например NetPing.
если верить этому коду, то у пакетов с ID D0 он тоже остается неизменным, а это не верно.
хорошо просматривается в пакетхаке со снятой галкой "Gracia Off-like"
"осилю" код обфускатора "на повторить" буду разбираться что к чему, пока только догадки...
p.s. спасибо за наводку на исходник :)

Yegor
22.09.2012, 18:22
Elecktron, у меня именно с этим пакетом и проблема. Не могу сделать как надо так как не знаю алгоритма по которому стпроит таблицу клиент.

Elecktron
22.09.2012, 18:31
вот на мой взгляд более корректная инфа:
http://code.google.com/p/l2packets/source/browse/trunk/src/pcode_obfuscator/L2PCodeObfuscator.cpp
и тут еще немного есть:
http://forum.zone-game.info/showthread.php?p=156785

а я не могу понять как формируется ключ для построения таблицы опкодов..
ключик есть и в KeyPacket и в CharSelected, а как формируется конечный не ясно..

Yegor
22.09.2012, 19:01
Самый первый ключ присылает сервер в пакете KeyPacket, он вроде его рандомно генерирует.

Elecktron
23.09.2012, 01:12
а что в пакетхаке с D0 пакетами?
и что делать со вторым ключиком (из CharSelected)?

действительно с D0 пакетами какая-то фигня...
брал код из пакетхака, программка отправляет D0
с CF тоже глюки..
при этом не D0 кодирует нормально..

Elecktron
24.09.2012, 01:39
вот так у меня все заработало:



unit Opcode;

interface

var
_1_byte_table: string;
_2_byte_table: string;
_seed: integer;


procedure _init_tables();
function _encode_1ID(_ID: char):char;
function _encode_2ID(_ID: char):char;


implementation


function _pseudo_rand: integer;
var
a : integer;
begin

a := (Int64(_seed) * $343fd + $269EC3) and $FFFFFFFF;
_seed := a;
result := (_seed shr $10) and $7FFF;

end;


procedure _init_tables();
var
i : integer;
x : Char;
x2: Word;
rand_pos : integer;
cur_pos : integer;
begin

_1_byte_table := '';
_2_byte_table := '';


for i := 0 to $D0 do begin
_1_byte_table := _1_byte_table + chr(i);
end;
for i := 0 to $66 do begin
_2_byte_table := _2_byte_table + chr(i) + #$0;
end;

for i := 2 to $D1 do begin
rand_pos := (_pseudo_rand mod i) + 1;
x := _1_byte_table[rand_pos];
_1_byte_table[rand_pos] := _1_byte_table[i];
_1_byte_table[i] := x;
end;

cur_pos := 3;
for i := 2 to $67 do begin
rand_pos := _pseudo_rand mod i;
x2 := PWord(@_2_byte_table[rand_pos * 2 + 1])^;
PWord(@_2_byte_table[rand_pos * 2 + 1])^:=PWord(@_2_byte_table[cur_pos])^;
PWord(@_2_byte_table[cur_pos])^:=x2;
cur_pos := cur_pos + 2;
end;

cur_pos := Pos(#$12, _1_byte_table);
x := _1_byte_table[$13];
_1_byte_table[$13] := #$12;
_1_byte_table[cur_pos]:=x;

cur_pos := Pos(#$B1, _1_byte_table);
x := _1_byte_table[$B2];
_1_byte_table[$B2] := #$B1;
_1_byte_table[cur_pos]:=x;
end;

function _encode_1ID(_ID: char):char;
var
p: integer;
begin
p := pos(_ID, _1_byte_table);
_ID:=Char(p-1);
result:= _ID;
end;

function _encode_2ID(_ID: char):char;
var
p: integer;
begin
p:= pos(_ID, _2_byte_table);
_ID:=Char(((p + 1) shr 1) - 1);
result:= _ID;
end;

end.

приходит пакет KeyInit - берем последние 4 байта, копируем в _seed, вызываем _init_tables();
приходит пакет CharSelected, повторяем действия - берем последние 4 байта, копируем в _seed, вызываем _init_tables();

для кодирования ID пакетов - одноайдишные - _encode_1ID,
двух айдишные - для первого ID - _encode_1ID, для второго _encode_2ID.
работает на птске.

Be3geBJIa3
10.04.2013, 12:01
Elecktron, не совсем правильно. Почему _2_byte_size выбран = 66? этот параметр переменный от версии протокола, не хватает 2 перестановок, возможно и больше. Я сам не могу полностью настроить для хроник больше Таути.

Есть у кого реализация алгоритма для хроник СТ31+?

Кое что нашел, оказывается таблицы 3, а не 2.

Elecktron
13.04.2013, 10:46
Я сам не могу полностью настроить для хроник больше Таути.

это писалось для грации финал.