-
Автор темы
- #1
Всем привет,
Нужна помощь в реверсе псевдокода из IDA, вроде как всё нашел. Переписывание кода в C# ничему не приводит. Данные на выходе получаются неверными
//некоторые переменные я переименовал для ориентации по коду
//дешифрование
- Приём пакета, BitRotate расшифрован и с ним нет проблем осталось только то что используется в Opcode 3/4
- Сам DecryptUDP
- GetKey
- Шифрованный пакет
//шифрование
- Передача пакета
- Сам EncryptUDP
! GetKey точно такой же как на Decrypt
- Ну и сам пакет который я получил (скипнув это шифрование патчем exe) тут явно не хватает пару байт
Нужна любая помощь или подсказки. Уже с этим копаюсь почти 6 месяцев а головы так и не хватило. Пока что нужно именно что выше т.е UDP. По TCP есть похожее но это позже (там волосы дыбом встали когда увидел ключ long)
Дополнительно. Шифрованные данные начинаются с 25 байта (40 00 00 00 в нешифрованном пакете и 41 16 40 EB шифрованном) так же последние 9 байт пакета так же не шифруются.
Так же по BitRotate, простой битовый сдвиг который идёт до шифрования выше. Но так же не затрагивает первые 25 байт пакета и последние 9
- Реализация BitRotate
- И сам код
Нужна помощь в реверсе псевдокода из IDA, вроде как всё нашел. Переписывание кода в C# ничему не приводит. Данные на выходе получаются неверными
//некоторые переменные я переименовал для ориентации по коду
//дешифрование
- Приём пакета, BitRotate расшифрован и с ним нет проблем осталось только то что используется в Opcode 3/4
C++:
int __thiscall RecivePacket(int this)
{
int Data; // esi
int RecivedSize; // edi
unsigned int Opcode; // eax
unsigned __int8 *v6; // ebx
signed int DecryptedSize; // eax
__int16 v8; // di
int fromlen; // [esp+Ch] [ebp-1FA8h] BYREF
char TempBuffer[8096]; // [esp+10h] [ebp-1FA4h] BYREF
fromlen = 16;
Data = this + 28;
RecivedSize = recvfrom(*(this + 8), (this + 28), 8096, 0, (this + 12), &fromlen);
if ( (BitRotateDecryptor_1(Data, RecivedSize) & 0x8000u) != 0 )
return -1;
Opcode = *Data & 0x7F;
if ( Opcode >= 3 && Opcode <= 4 )
{
j_memset(TempBuffer, 0, sizeof(TempBuffer));
v6 = (this + 45);
DecryptedSize = DecryptUDP(v6, *(Data + 7) - 25, TempBuffer, 8096u, Data + 2, 4u, Data + 13, 4u);
v8 = DecryptedSize;
if ( DecryptedSize <= 0 )
return -1;
j_memcpy(v6, TempBuffer, DecryptedSize);
*(Data + 7) = v8 + 25;
return (v8 + 25);
}
return RecivedSize;
}
C++:
unsigned int __cdecl DecryptUDP(
unsigned __int8 *InputData,
int InputDataSize,
int OutData,
unsigned int BufferSize,
int Key1Size,
unsigned __int8 Key1,
int Key2Size,
unsigned __int8 Key2)
{
unsigned __int8 v8; // bl
unsigned __int8 v9; // cl
unsigned int v10; // esi
unsigned int v12; // ecx
int v13; // edx
unsigned int v14; // edi
unsigned __int8 _2_key2; // bh
int v16; // ecx
char _Key1; // bl
unsigned __int8 v18; // cl
char v19; // dl
char i; // dl
int v21; // eax
unsigned __int8 j; // cl
int v23; // eax
unsigned int v24; // esi
int v25; // eax
unsigned __int8 *v26; // edi
char _2_key1; // bl
char v28; // dl
char v29; // dl
unsigned __int8 k; // cl
int v31; // eax
unsigned __int8 m; // cl
int v33; // eax
unsigned int v34; // [esp+10h] [ebp-6Ch]
int v35; // [esp+14h] [ebp-68h]
int v36; // [esp+18h] [ebp-64h]
unsigned int v37; // [esp+1Ch] [ebp-60h]
unsigned __int8 v38; // [esp+22h] [ebp-5Ah]
unsigned __int8 v39; // [esp+23h] [ebp-59h]
int v40; // [esp+24h] [ebp-58h]
unsigned __int8 v41; // [esp+2Ah] [ebp-52h]
unsigned __int8 _Key2; // [esp+2Bh] [ebp-51h]
char Key2Array[29]; // [esp+2Ch] [ebp-50h] BYREF
__int16 v44; // [esp+49h] [ebp-33h]
char v45; // [esp+4Bh] [ebp-31h]
char Key1Array[29]; // [esp+4Ch] [ebp-30h] BYREF
__int16 v47; // [esp+69h] [ebp-13h]
char v48; // [esp+6Bh] [ebp-11h]
char v49[12]; // [esp+6Ch] [ebp-10h]
memset(Key1Array, 0, sizeof(Key1Array));
v47 = 0;
v48 = 0;
j_memcpy(Key1Array, Key1Size, Key1);
memset(Key2Array, 0, sizeof(Key2Array));
v44 = 0;
v45 = 0;
j_memcpy(Key2Array, Key2Size, Key2);
v8 = *InputData;
v41 = InputData[1];
v9 = InputData[3];
v39 = *InputData;
v38 = v9;
if ( (v9 - 2) > 7u )
return -1;
v10 = InputDataSize - v9;
v34 = v9;
if ( v10 - 4 >= BufferSize )
return 0;
v12 = 0;
v13 = 0;
v14 = 4;
_2_key2 = 0;
v37 = 0;
v40 = 0;
if ( v10 > 4 )
{
v16 = v8;
v35 = v8;
v37 = v10 - 4;
do
{
_Key1 = GetKey(Key1Array, Key1, v16 + v13, 1);
_Key2 = GetKey(Key2Array, Key2, v41 + v40, 1) ^ _Key1 ^ _2_key2;
v40 += _Key2 + 1;
v18 = 0;
v19 = _Key2 ^ InputData[v14];
*(OutData + v14 - 4) = v19;
for ( i = _Key2 ^ v19; v18 < Key1; Key1Array[v21] ^= i )
{
v21 = v18;
v18 += 2;
}
for ( j = 1; j < Key2; Key2Array[v23] ^= i )
{
v23 = j;
j += 2;
}
_2_key2 = _Key2;
++v14;
v13 = v40;
v16 = v35;
}
while ( v14 < v10 );
v12 = v10 - 4;
v8 = v39;
}
v24 = 0;
if ( v34 )
{
v25 = v8;
v26 = &InputData[v12 + 4];
v36 = v8;
do
{
_2_key1 = GetKey(Key1Array, Key1, v13 + v25, 1);
_2_key2 ^= GetKey(Key2Array, Key2, v41 + v40, 1) ^ _2_key1;
v28 = _2_key2 ^ *v26;
v49[v24] = v28;
v29 = _2_key2 ^ v28;
v40 += _2_key2 + 1;
for ( k = 0; k < Key1; Key1Array[v31] ^= v29 )
{
v31 = k;
k += 2;
}
for ( m = 1; m < Key2; Key2Array[v33] ^= v29 )
{
v33 = m;
m += 2;
}
++v24;
v13 = v40;
++v26;
v25 = v36;
}
while ( v24 < v34 );
}
if ( v38 == v49[0] || v38 == v49[1] )
return v37;
else
return -1;
}
C++:
char __cdecl GetKey(int a1, unsigned __int8 a2, unsigned int a3, char mode)
{
unsigned int v4; // esi
int v5; // ebx
unsigned __int8 v6; // al
if ( mode )
{
v4 = (a3 >> 3) % a2;
LOBYTE(v5) = a3 & 7;
v6 = (v4 + 1) % a2;
}
else
{
v4 = ((8 * a2 - a3 % (8 * a2)) / 8 % a2);
v6 = (v4 + 1) % a2;
v5 = (8 * a2 - a3 % (8 * a2)) % 8;
}
if ( v5 )
return (*(v6 + a1) >> (8 - v5)) + ((*(v4 + a1) & (255 >> v5)) << v5);
else
return *(v4 + a1);
}
Форматирование (BB-код):
|00000000| 04 00 B7 F3 65 40 00 52 00 00 00 2F 00 00 00 00 |....e@.R.../....|
|00000010| 00 8C 2E 28 34 14 30 3C 2B 41 16 40 EB 51 C9 35 |...(4.0<+A.@.Q.5|
|00000020| 36 DB ED 76 3F AE 10 84 AF 4B 4F C8 6B 0D FB A9 |6..v?....KO.k...|
|00000030| 66 EC 21 62 9B A4 94 82 07 AA 2E 2C 18 04 6E 4D |f.!b.......,..nM|
|00000040| FF F3 C5 FB 23 4C 82 A8 A0 04 02 00 1F E0 80 02 |....#L..........|
|00000050| 00 00 |.. |
- Передача пакета
C++:
int __thiscall SendPacket(SOCKET *this, byte *data, int unk, byte mode_or_key)
{
unsigned int Opcode; // eax
int EncryptedSize; // eax
__int16 v6; // si
int v7; // ecx
char TempBuffer[8096]; // [esp+10h] [ebp-1FA4h] BYREF
Opcode = *data & 0x7F;
if ( Opcode < 3 || Opcode > 4 )
goto LABEL_5;
j_memset(TempBuffer, 0, sizeof(TempBuffer));
EncryptedSize = EncryptUDP((data + 25), *(data + 7) - 17, TempBuffer, 8096u, (data + 2), 4u, (data + 13), 4u);
v6 = EncryptedSize;
if ( EncryptedSize > 0 )
{
j_memcpy(data + 25, TempBuffer, EncryptedSize);
*(data + 7) = v6 + 25;
LABEL_5:
v7 = *(data + 7);
*&data[v7] = *(dword_174B1F4 + 344);
*&data[v7 + 5] = *(dword_174B1F4 + 352);
data[v7 + 4] = mode_or_key;
*(data + 7) += 9;
return Send(this, data, *(data + 7), *(dword_174B1F4 + 336), *(dword_174B1F4 + 340));
}
return -1;
}
C++:
int __cdecl EncryptUDP(
int InputData, // possible
unsigned int InputDataSize,
unsigned __int8 *OutData,
unsigned int BufferSize,
int Key1Size,
unsigned __int8 Key1,
int Key2Size,
unsigned __int8 Key2)
{
int (*v8)(void); // esi
unsigned __int8 v9; // bl
unsigned __int8 v10; // bh
int v11; // eax
unsigned __int8 v12; // cl
int v14; // esi
unsigned int v15; // edi
unsigned __int8 _Key2; // bh
int encryptedSize; // ecx
int v18; // ecx
char _Key1; // bl
unsigned __int8 v20; // cl
char i; // bl
int v22; // eax
unsigned __int8 j; // cl
int v24; // eax
unsigned int v25; // edi
int v26; // eax
char Key; // bl
char v28; // al
int v29; // ecx
unsigned __int8 v30; // dl
char v31; // bl
int v32; // eax
unsigned __int8 v33; // dl
int v34; // eax
unsigned int v35; // [esp+Ch] [ebp-60h]
int v36; // [esp+10h] [ebp-5Ch]
int v37; // [esp+14h] [ebp-58h]
unsigned __int8 v38; // [esp+1Fh] [ebp-4Dh]
int v39; // [esp+20h] [ebp-4Ch]
unsigned __int8 v40; // [esp+27h] [ebp-45h]
char key2Array[29]; // [esp+28h] [ebp-44h] BYREF
__int16 v42; // [esp+45h] [ebp-27h]
char v43; // [esp+47h] [ebp-25h]
char key1Array[29]; // [esp+48h] [ebp-24h] BYREF
__int16 v45; // [esp+65h] [ebp-7h]
char v46; // [esp+67h] [ebp-5h]
memset(key1Array, 0, sizeof(key1Array));
v45 = 0;
v46 = 0;
j_memcpy(key1Array, Key1Size, Key1);
memset(key2Array, 0, sizeof(key2Array));
v42 = 0;
v43 = 0;
j_memcpy(key2Array, Key2Size, Key2);
v8 = rand;
v9 = rand() % (8 * Key1);
v38 = v9;
v10 = v8() % (8 * Key2);
v40 = v10;
v11 = v8() % 256;
v12 = ((2 - InputDataSize) & 7) + 2;
v35 = v12;
if ( InputDataSize + v12 + 4 >= BufferSize )
return 0;
v14 = 0;
v15 = 0;
OutData[1] = v10;
_Key2 = 0;
OutData[2] = v11;
OutData[3] = v12;
*OutData = v9;
encryptedSize = 4;
v39 = 4;
if ( InputDataSize )
{
v18 = v9;
v36 = v9;
v39 = InputDataSize + 4;
do
{
_Key1 = GetKey(key1Array, Key1, v18 + v14, 1);
_Key2 ^= GetKey(key2Array, Key2, v14 + v40, 1) ^ _Key1;
v14 += _Key2 + 1;
OutData[v15 + 4] = _Key2 ^ *(v15 + InputData);
v20 = 0;
for ( i = _Key2 ^ *(v15 + InputData); v20 < Key1; key1Array[v22] ^= i )
{
v22 = v20;
v20 += 2;
}
for ( j = 1; j < Key2; key2Array[v24] ^= i )
{
v24 = j;
j += 2;
}
v18 = v36;
++v15;
}
while ( v15 < InputDataSize );
encryptedSize = InputDataSize + 4;
v9 = v38;
}
v25 = 0;
if ( v35 )
{
v26 = v9;
v37 = v9;
do
{
Key = GetKey(key1Array, Key1, v14 + v26, 1);
v28 = GetKey(key2Array, Key2, v14 + v40, 1);
v29 = v39;
_Key2 ^= v28 ^ Key;
v14 += _Key2 + 1;
OutData[v39] = (((2 - InputDataSize) & 7) + 2) ^ _Key2;
v30 = 0;
v31 = _Key2 ^ *(v25 + InputData);
if ( Key1 )
{
do
{
v32 = v30;
v30 += 2;
key1Array[v32] ^= v31;
}
while ( v30 < Key1 );
v29 = v39;
}
v33 = 1;
if ( Key2 > 1u )
{
do
{
v34 = v33;
v33 += 2;
key2Array[v34] ^= v31;
}
while ( v33 < Key2 );
v29 = v39;
}
v26 = v37;
encryptedSize = v29 + 1;
++v25;
v39 = encryptedSize;
}
while ( v25 < v35 );
}
return encryptedSize;
}
- Ну и сам пакет который я получил (скипнув это шифрование патчем exe) тут явно не хватает пару байт
Форматирование (BB-код):
|00000000| 04 00 42 60 5D 40 00 47 00 00 00 2F 00 00 00 00 |..B`]@.G.../....|
|00000010| 00 8C 2E 28 34 14 30 3C 2B 40 00 00 00 00 80 60 |...(4.0<+@.....`|
|00000020| 02 06 80 04 40 3C 07 C0 00 00 00 00 00 00 00 00 |....@<..........|
|00000030| 33 40 40 09 34 13 92 26 8E 56 4F E9 90 40 08 04 |3@@.4..&.VO..@..|
|00000040| 00 3F C1 00 04 00 09 |.?..... |
Нужна любая помощь или подсказки. Уже с этим копаюсь почти 6 месяцев а головы так и не хватило. Пока что нужно именно что выше т.е UDP. По TCP есть похожее но это позже (там волосы дыбом встали когда увидел ключ long)
Дополнительно. Шифрованные данные начинаются с 25 байта (40 00 00 00 в нешифрованном пакете и 41 16 40 EB шифрованном) так же последние 9 байт пакета так же не шифруются.
Так же по BitRotate, простой битовый сдвиг который идёт до шифрования выше. Но так же не затрагивает первые 25 байт пакета и последние 9
- Реализация BitRotate
C#:
byte[] WithEnd, WithoutEnd;
byte[] Result = new byte[Packet.Length - 25];
Array.Copy(Packet.Data, 25, Result, 0, Result.Length);
WithEnd = Bitwise.Decrypt(Result, Packet.Length % 6 + 1);
WithoutEnd = new byte[WithEnd.Length - 9];
Array.Copy(WithEnd, WithoutEnd, WithoutEnd.Length);
Packet.WithEndData = WithEnd;
Packet.WithoutEndData = WithoutEnd;
C#:
public static byte[] Decrypt(byte[] Data, int Shift)
{
byte[] NewBuffer = new byte[Data.Length];
Array.Copy(Data, 0, NewBuffer, 0, NewBuffer.Length);
byte LastElement = NewBuffer[NewBuffer.Length - 1];
for (int i = NewBuffer.Length - 1; i > 0; --i)
{
NewBuffer[i] = (byte)((NewBuffer[i - 1] & 255) << 8 - Shift | (NewBuffer[i] & 255) >> Shift);
}
NewBuffer[0] = (byte)(LastElement << 8 - Shift | (NewBuffer[0] & 255) >> Shift);
return NewBuffer;
}
public static byte[] Encrypt(byte[] Data, int Shift)
{
byte[] NewBuffer = new byte[Data.Length];
Array.Copy(Data, 0, NewBuffer, 0, NewBuffer.Length);
byte FirstElement = NewBuffer[0];
for (int i = 0; i < NewBuffer.Length - 1; ++i)
{
NewBuffer[i] = (byte)((NewBuffer[i + 1] & 255) >> 8 - Shift | (NewBuffer[i] & 255) << Shift);
}
NewBuffer[NewBuffer.Length - 1] = (byte)(FirstElement >> 8 - Shift | (NewBuffer[NewBuffer.Length - 1] & 255) << Shift);
return NewBuffer;
}
Последнее редактирование: