PDA

Просмотр полной версии : wdb string 5.2.0 Build 16650


Konctantin
11.03.2013, 12:58
С выходом патча 5.2 в кеше появилсь новые типы строк.
В первых 2х байтах содержится длина строки (но не в чистом виде).

для получения длины строки клиент использует 2 функции:
unsigned int __thiscall CDataStore::GetStrLen(int this, int a2)
{
int v2; // edi@1
char v3; // cl@1
int v4; // ecx@2
unsigned int v5; // eax@2
unsigned int v6; // esi@3
int v7; // ecx@3
int v9; // [sp+Ah] [bp-6h]@0
unsigned __int8 v10; // [sp+Eh] [bp-2h]@3
unsigned __int8 v11; // [sp+Fh] [bp-1h]@2

v2 = this;
v3 = *(_BYTE *)(this + 5);
if ( v3 == 8 )
{
v4 = *(_DWORD *)v2;
v11 = 0;
CDataStore::GetInt8(v4, (int)&v11);
v5 = v11;
}
else
{
v6 = (unsigned int)*(_BYTE *)(v2 + 4) >> v3;
v7 = *(_DWORD *)v2;
v10 = 0;
CDataStore::GetInt8(v7, (int)&v10);
v5 = (v6 << *(_BYTE *)(v2 + 5)) | ((unsigned int)v10 >> (8 - *(_BYTE *)(v2 + 5)));
*(_BYTE *)(v2 + 4) = v10 << *(_BYTE *)(v2 + 5);
}
LOBYTE(v9) = 0;
return 16 * v5 | CDataStore::GetLoByte(v2, v9);
}

unsigned int __thiscall CDataStore::GetLoByte(int this, int a2)
{
int v2; // esi@1
unsigned __int8 v3; // cl@1
unsigned __int8 v4; // dl@2
unsigned int result; // eax@2
unsigned int v6; // edi@5
unsigned __int8 v7; // bl@5
char v8; // dl@5
unsigned int v9; // eax@5
char v10; // cl@5
unsigned __int8 v11; // [sp+7h] [bp-1h]@3

v2 = this;
v3 = *(_BYTE *)(this + 5);
if ( v3 > 4u )
{
v11 = 0;
if ( v3 == 8 )
{
CDataStore::GetInt8(*(_DWORD *)v2, (int)&v11);
result = (unsigned int)v11 >> 4;
*(_BYTE *)(v2 + 4) = 16 * v11;
*(_BYTE *)(v2 + 5) = 4;
}
else
{
v6 = (unsigned int)*(_BYTE *)(v2 + 4) >> v3;
CDataStore::GetInt8(*(_DWORD *)v2, (int)&v11);
v7 = v11;
v8 = *(_BYTE *)(v2 + 5) - 4;
v9 = (unsigned int)v11 >> (8 - v8);
v10 = *(_BYTE *)(v2 + 5) - 4;
*(_BYTE *)(v2 + 5) = v8;
result = (v6 << v10) | v9;
*(_BYTE *)(v2 + 4) = v7 << v10;
}
}
else
{
v4 = *(_BYTE *)(v2 + 4);
result = (unsigned int)v4 >> 4;
*(_BYTE *)(v2 + 4) = 16 * v4;
*(_BYTE *)(v2 + 5) = v3 + 4;
}
return result;
}
я попытался написать ридер таких строк, но увы - не получилось (видать где-то косячу), больше всего смущает такое:
v3 = *(_BYTE *)(this + 5);.
Собственно сам вопрос, от куда считается смещение, от начала потока DataStore или с текущей позиции, или что это вообще за оффсет?

TOM_RUS
11.03.2013, 17:42
Хоть бы адреса этих функций указали чтоли...

http://paste2.org/p/3115953
http://paste2.org/p/3116016

Konctantin
11.03.2013, 18:15
Сори, на работе сидел и колупал без IDA, исходя из текста
для полноты картины, вот функция чтения pagetextcache
int __thiscall sub_7ACBD0(void *this, int a2, int a3)
{
void *v3; // esi@1
int v4; // eax@1
int v5; // ST04_4@1
int v6; // eax@1
int v7; // ebx@1
int result; // eax@1
int v9; // [sp+10h] [bp-4h]@1

v3 = this;
v9 = 0;
CDataStore::GetInt32(&v9);
*(_DWORD *)v3 = v9;
a2 = 0;
CDataStore::GetInt32(&a2);
v4 = a2;
LOBYTE(a2) = 0;
v5 = a2;
*((_DWORD *)v3 + 1) = v4;
LOWORD(v9) = 2048;
v6 = sub_744280(v5);
v7 = v6;
*((_DWORD *)v3 + 2) = v6;
result = sub_410310((char *)v3 + 8, v6);
*((_BYTE *)v3 + v7 + 8) = 0;
return result;
}
а уже из нее вызывается функция получения длины строки:
int __thiscall sub_744280(int this, int a2)
{
int v2; // edi@1
char v3; // cl@1
unsigned int v4; // eax@2
unsigned int v5; // esi@3
int v7; // [sp+Ah] [bp-6h]@0
unsigned __int8 v8; // [sp+Eh] [bp-2h]@3
unsigned __int8 v9; // [sp+Fh] [bp-1h]@2

v2 = this;
v3 = *(_BYTE *)(this + 5);
if ( v3 == 8 )
{
v9 = 0;
CDataStore::GetInt8(&v9);
v4 = v9;
}
else
{
v5 = (unsigned int)*(_BYTE *)(v2 + 4) >> v3;
v8 = 0;
CDataStore::GetInt8(&v8);
v4 = (v5 << *(_BYTE *)(v2 + 5)) | ((unsigned int)v8 >> (8 - *(_BYTE *)(v2 + 5)));
*(_BYTE *)(v2 + 4) = v8 << *(_BYTE *)(v2 + 5);
}
LOBYTE(v7) = 0;
return 16 * v4 | sub_725A90(v7);
}
а та в свою очередь содержит еще часть
unsigned int __thiscall sub_725A90(int this, int a2)
{
int v2; // esi@1
unsigned __int8 v3; // cl@1
unsigned __int8 v4; // dl@2
unsigned int result; // eax@2
unsigned int v6; // edi@5
unsigned __int8 v7; // bl@5
char v8; // dl@5
unsigned int v9; // eax@5
char v10; // cl@5
unsigned __int8 v11; // [sp+7h] [bp-1h]@3

v2 = this;
v3 = *(_BYTE *)(this + 5);
if ( v3 > 4u )
{
v11 = 0;
if ( v3 == 8 )
{
CDataStore::GetInt8(&v11);
result = (unsigned int)v11 >> 4;
*(_BYTE *)(v2 + 4) = 16 * v11;
*(_BYTE *)(v2 + 5) = 4;
}
else
{
v6 = (unsigned int)*(_BYTE *)(v2 + 4) >> v3;
CDataStore::GetInt8(&v11);
v7 = v11;
v8 = *(_BYTE *)(v2 + 5) - 4;
v9 = (unsigned int)v11 >> (8 - v8);
v10 = *(_BYTE *)(v2 + 5) - 4;
*(_BYTE *)(v2 + 5) = v8;
result = (v6 << v10) | v9;
*(_BYTE *)(v2 + 4) = v7 << v10;
}
}
else
{
v4 = *(_BYTE *)(v2 + 4);
result = (unsigned int)v4 >> 4;
*(_BYTE *)(v2 + 4) = 16 * v4;
*(_BYTE *)(v2 + 5) = v3 + 4;
}
return result;
}

Konctantin
11.03.2013, 18:21
в creaturecahce еще по круче
unsigned int __thiscall sub_80E0B0(void *this, signed int a2, int a3)
{
signed int v3; // edi@1
void *v4; // esi@1
unsigned __int8 v5; // dl@2
unsigned int v7; // ecx@4
unsigned __int8 v8; // dl@4
char v9; // al@4
int v10; // ebx@4
unsigned int v11; // eax@7
char v12; // ST34_1@8
unsigned int v13; // ebx@8
unsigned int v14; // eax@10
bool v15; // zf@12
int v16; // ebx@13
int v17; // ebx@15
int v18; // ebx@17
int v19; // ebx@19
int v20; // ebx@21
char v21; // ST08_1@21
unsigned int v22; // ST04_4@21
unsigned int v23; // esi@21
unsigned int result; // eax@22
unsigned __int8 v25; // [sp+10h] [bp-20h]@4
int v26; // [sp+18h] [bp-18h]@0
int v27; // [sp+1Ch] [bp-14h]@0
signed int v28; // [sp+20h] [bp-10h]@4
signed int v29; // [sp+20h] [bp-10h]@15
signed int v30; // [sp+20h] [bp-10h]@17
signed int v31; // [sp+20h] [bp-10h]@19
int v32; // [sp+24h] [bp-Ch]@4
unsigned __int8 v33; // [sp+2Dh] [bp-3h]@11
unsigned __int8 v35; // [sp+2Fh] [bp-1h]@8

v3 = a2;
LOBYTE(a2) = 0;
v4 = this;
*((_DWORD *)v4 + 1) ^= (unsigned int)&unk_FFFFFF & (sub_710890(a2) ^ *((_DWORD *)v4 + 1));
LOBYTE(a2) = 0;
*((_DWORD *)v4 + 3) ^= (unsigned int)&unk_FFFFFF & (sub_710890(a2) ^ *((_DWORD *)v4 + 3));
LOBYTE(a2) = 0;
*((_DWORD *)v4 + 5) ^= (unsigned int)&unk_FFFFFF & (sub_70A5C0(a2) ^ *((_DWORD *)v4 + 5));
BYTE3(a2) = 0;
CDataStore::GetInt8((char *)&a2 + 3);
v5 = BYTE3(a2);
v7 = (unsigned int)v5 >> 7;
v8 = 2 * v5;
v9 = 1;
v10 = (int)((char *)v4 + 156);
v25 = v8;
*((_BYTE *)v4 + 52) = v7 != 0;
v32 = (int)((char *)v4 + 156);
v28 = 4;
while ( 1 )
{
if ( v9 == 8 )
{
BYTE3(a2) = 0;
CDataStore::GetInt8((char *)&a2 + 3);
v11 = BYTE3(a2);
}
else
{
v12 = v9;
v13 = (unsigned int)v8 >> v9;
v35 = 0;
CDataStore::GetInt8(&v35);
v11 = (v13 << v12) | ((unsigned int)v35 >> (8 - v12));
v10 = v32;
v25 = 2 * v35;
}
LOBYTE(v27) = 0;
*(_DWORD *)(v10 - 32) ^= (unsigned int)&unk_FFFFFF & ((sub_70A480(v27) | 8 * v11) ^ *(_DWORD *)(v10 - 32));
v33 = 0;
CDataStore::GetInt8(&v33);
v14 = 2 * ((unsigned int)v25 >> 1) | ((unsigned int)v33 >> 7);
v25 = 2 * v33;
LOBYTE(v26) = 0;
*(_DWORD *)v32 ^= (unsigned int)&unk_FFFFFF & ((sub_70A480(v26) | 8 * v14) ^ *(_DWORD *)v32);
v10 = v32 + 8;
v15 = v28-- == 1;
v32 += 8;
if ( v15 )
break;
v9 = 1;
v8 = v25;
}
v16 = (int)((char *)v4 + 120);
a2 = 4;
do
{
sub_BF2C70(v3, (unsigned int)&unk_FFFFFF & *(_DWORD *)(v16 + 4), a3);
sub_BF2C70(v3, (unsigned int)&unk_FFFFFF & *(_DWORD *)(v16 + 36), a3);
v16 += 8;
--a2;
}
while ( a2 );
v17 = (int)((char *)v4 + 88);
v29 = 2;
do
{
a2 = 0;
CDataStore::GetInt32(&a2);
*(_DWORD *)v17 = a2;
v17 += 4;
--v29;
}
while ( v29 );
a2 = 0;
CDataStore::GetInt32(&a2);
*((_DWORD *)v4 + 6) = a2;
a2 = 0;
CDataStore::GetInt32(&a2);
*((_DWORD *)v4 + 7) = a2;
a2 = 0;
CDataStore::GetInt32(&a2);
*((_DWORD *)v4 + 8) = a2;
v18 = (int)((char *)v4 + 96);
v30 = 2;
do
{
a2 = 0;
CDataStore::GetInt32(&a2);
*(_DWORD *)v18 = a2;
v18 += 4;
--v30;
}
while ( v30 );
v19 = (int)((char *)v4 + 104);
v31 = 4;
do
{
a2 = 0;
CDataStore::GetInt32(&a2);
*(_DWORD *)v19 = a2;
v19 += 4;
--v31;
}
while ( v31 );
a2 = 0;
CDataStore::GetFloat(&a2);
*((_DWORD *)v4 + 9) = a2;
a2 = 0;
CDataStore::GetFloat(&a2);
*((_DWORD *)v4 + 10) = a2;
a2 = 0;
CDataStore::GetFloat(&a2);
*((_DWORD *)v4 + 11) = a2;
a2 = 0;
CDataStore::GetFloat(&a2);
*((_DWORD *)v4 + 12) = a2;
a2 = 0;
CDataStore::GetInt32(&a2);
v20 = (int)((char *)v4 + 56);
sub_6B5570(a2);
a2 = 0;
CDataStore::GetInt32(&a2);
*((_DWORD *)v4 + 19) = a2;
a2 = 0;
CDataStore::GetInt32(&a2);
*((_DWORD *)v4 + 20) = a2;
a2 = 0;
CDataStore::GetInt32(&a2);
v21 = a3;
v22 = (unsigned int)&unk_FFFFFF & *((_DWORD *)v4 + 1);
*((_DWORD *)v4 + 21) = a2;
sub_BF2C70(v3, v22, v21);
sub_BF2C70(v3, (unsigned int)&unk_FFFFFF & *((_DWORD *)v4 + 3), a3);
sub_BF2C70(v3, (unsigned int)&unk_FFFFFF & *((_DWORD *)v4 + 5), a3);
v23 = 0;
while ( 1 )
{
result = *(_DWORD *)(v20 + 16);
if ( result == -1 )
result = *(_DWORD *)v20;
if ( v23 >= result )
break;
a3 = 0;
CDataStore::GetInt32(&a3);
if ( *(_DWORD *)(v20 + 16) == -1 )
*(_DWORD *)(*(_DWORD *)(v20 + 4) + 4 * v23++) = a3;
else
*(_DWORD *)(v20 + 4 * v23++) = a3;
}
return result;
}

Fabian
19.03.2013, 08:36
My current structs with the bitpacking:

https://github.com/Arctium/Arctium/blob/master/WorldServer/Game/Packets/PacketHandler/CacheHandler.cs

Astromancer
29.08.2013, 22:13
Сори, на работе сидел и колупал без IDA, исходя из текста
для полноты картины, вот функция чтения pagetextcache
int __thiscall sub_7ACBD0(void *this, int a2, int a3)
{
void *v3; // esi@1
int v4; // eax@1
int v5; // ST04_4@1
int v6; // eax@1
int v7; // ebx@1
int result; // eax@1
int v9; // [sp+10h] [bp-4h]@1

v3 = this;
v9 = 0;
CDataStore::GetInt32(&v9);
*(_DWORD *)v3 = v9;
a2 = 0;
CDataStore::GetInt32(&a2);
v4 = a2;
LOBYTE(a2) = 0;
v5 = a2;
*((_DWORD *)v3 + 1) = v4;
LOWORD(v9) = 2048;
v6 = sub_744280(v5);
v7 = v6;
*((_DWORD *)v3 + 2) = v6;
result = sub_410310((char *)v3 + 8, v6);
*((_BYTE *)v3 + v7 + 8) = 0;
return result;
}
а уже из нее вызывается функция получения длины строки:
int __thiscall sub_744280(int this, int a2)
{
int v2; // edi@1
char v3; // cl@1
unsigned int v4; // eax@2
unsigned int v5; // esi@3
int v7; // [sp+Ah] [bp-6h]@0
unsigned __int8 v8; // [sp+Eh] [bp-2h]@3
unsigned __int8 v9; // [sp+Fh] [bp-1h]@2

v2 = this;
v3 = *(_BYTE *)(this + 5);
if ( v3 == 8 )
{
v9 = 0;
CDataStore::GetInt8(&v9);
v4 = v9;
}
else
{
v5 = (unsigned int)*(_BYTE *)(v2 + 4) >> v3;
v8 = 0;
CDataStore::GetInt8(&v8);
v4 = (v5 << *(_BYTE *)(v2 + 5)) | ((unsigned int)v8 >> (8 - *(_BYTE *)(v2 + 5)));
*(_BYTE *)(v2 + 4) = v8 << *(_BYTE *)(v2 + 5);
}
LOBYTE(v7) = 0;
return 16 * v4 | sub_725A90(v7);
}
а та в свою очередь содержит еще часть
unsigned int __thiscall sub_725A90(int this, int a2)
{
int v2; // esi@1
unsigned __int8 v3; // cl@1
unsigned __int8 v4; // dl@2
unsigned int result; // eax@2
unsigned int v6; // edi@5
unsigned __int8 v7; // bl@5
char v8; // dl@5
unsigned int v9; // eax@5
char v10; // cl@5
unsigned __int8 v11; // [sp+7h] [bp-1h]@3

v2 = this;
v3 = *(_BYTE *)(this + 5);
if ( v3 > 4u )
{
v11 = 0;
if ( v3 == 8 )
{
CDataStore::GetInt8(&v11);
result = (unsigned int)v11 >> 4;
*(_BYTE *)(v2 + 4) = 16 * v11;
*(_BYTE *)(v2 + 5) = 4;
}
else
{
v6 = (unsigned int)*(_BYTE *)(v2 + 4) >> v3;
CDataStore::GetInt8(&v11);
v7 = v11;
v8 = *(_BYTE *)(v2 + 5) - 4;
v9 = (unsigned int)v11 >> (8 - v8);
v10 = *(_BYTE *)(v2 + 5) - 4;
*(_BYTE *)(v2 + 5) = v8;
result = (v6 << v10) | v9;
*(_BYTE *)(v2 + 4) = v7 << v10;
}
}
else
{
v4 = *(_BYTE *)(v2 + 4);
result = (unsigned int)v4 >> 4;
*(_BYTE *)(v2 + 4) = 16 * v4;
*(_BYTE *)(v2 + 5) = v3 + 4;
}
return result;
}
Вот мне, как человеку далекому от всего этого(ассемблер то знаю, но вот с реверсингом никогда не приходилось иметь дело) интересно, как вы определяете через эти сабы, где какая функция. Интуитивно чтоль?

Sid
30.08.2013, 06:04
IDA сама же именует :) Она и определяет.

Astromancer
30.08.2013, 11:54
IDA сама же именует :) Она и определяет.
Но как она именует? sub_xxxxxx? Как вы понимаете какой из этих сабов отвечает за обработку пакета какого-нибудь.

Amaru
30.08.2013, 12:03
xxxxxx это адрес. Читабельное имя проставляется ручками

Astromancer
30.08.2013, 12:08
xxxxxx это адрес. Читабельное имя проставляется ручками
Ну я в курсе что адрес, вопрос как понять что находится по этому адресу? Я сейчас на работе, так что никаких адекватных данных для примера врядли привести смогу, но как я понял, когда мы получаем пакет по сети то там в хедере мы и видим этот адрес? Или я вообще не понимаю процесса?

Amaru
30.08.2013, 14:14
в хедере мы видим число, которое определяет пакет.
http://ru-mangos.ru/showthread.php?t=95&highlight=%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80+%D0 %BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2

Astromancer
30.08.2013, 18:29
в хедере мы видим число, которое определяет пакет.
http://ru-mangos.ru/showthread.php?t=95&highlight=%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80+%D0 %BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2
Статья хорошая, но устарела давно, я там уже давно отписывался, один из первых постов.