Hello, im working on reversing the blowfish encryption scheme for a certain game, im kinda stuck atm, figured this would be the best place to turn and ask for some assistance.
This is what i know/have.
I have the PBox Key and the SBox Key, their algo is 'broken' in that they only use 1 SBox key throughout, so instead of using 4 random ones they only have 1. I also have the function in which the whole process takes place, all the blowfish stuff that is. That is where im having a problem, im finding it difficult to convert what Hexrays has given me into something usable. Im aware there are many free blowfish crypto out there on the net, but im having trouble turning my boxes into usable stuff for them :S
nonetheless here is the function
Here are the Boxes
Here is the subkey generation
This is a function that is called inside the first function that I showed
Please excuse the almost unreadness, its all psuedocode that was decompiled using Hexrays
If anybody can provide any help it would be greatly appreciated
This is what i know/have.
I have the PBox Key and the SBox Key, their algo is 'broken' in that they only use 1 SBox key throughout, so instead of using 4 random ones they only have 1. I also have the function in which the whole process takes place, all the blowfish stuff that is. That is where im having a problem, im finding it difficult to convert what Hexrays has given me into something usable. Im aware there are many free blowfish crypto out there on the net, but im having trouble turning my boxes into usable stuff for them :S
nonetheless here is the function
Code:
void __stdcall sub_48FB90(int a1, signed int a2, unsigned int a3, int a4)
{
signed int v4; // edi@2
unsigned int v5; // esi@3
signed int v6; // eax@4
int v7; // ecx@4
signed int v8; // eax@6
int v9; // ecx@6
signed int v10; // edx@7
unsigned int v11; // ecx@10
int v12; // ebp@10
int v13; // ebx@11
int v14; // ebx@11
unsigned int v15; // ett@11
int v16; // ebx@11
int v17; // ebx@11
unsigned int v18; // ett@11
int v19; // ebx@11
int v20; // ebx@11
unsigned int v21; // ett@11
int v22; // ebx@11
int v23; // ebx@11
unsigned int v24; // ett@11
int v25; // ebx@11
char v26; // zf@11
signed int v27; // ebx@12
int v28; // edi@12
int v29; // esi@12
unsigned int v30; // eax@13
int v31; // esi@14
signed int v32; // ebx@15
unsigned int v33; // ecx@16
signed int v35; // [sp+8h] [bp+4h]@14
if ( a1 )
{
v4 = a2;
if ( a2 )
{
v5 = a3;
if ( a3 >= 1 )
{
v6 = (signed int)&Blowfish_p_init;
v7 = a1 + 8;
do
{
*(_DWORD *)v7 = *(_DWORD *)v6;
v6 += 4;
v7 += 4;
}
while ( v6 < (signed int)&Blowfish_s_init );
v8 = (signed int)&Blowfish_s_init;
v9 = a1 + 80;
do
{
v10 = 256;
do
{
*(_DWORD *)v9 = *(_DWORD *)v8;
v8 += 4;
v9 += 4;
--v10;
}
while ( v10 );
}
while ( v8 < (signed int)&off_7768F8 );
v11 = 0;
v12 = a1 + 12;
a2 = 3;
do
{
v13 = *(_BYTE *)((v11 + 1) % v5 + v4);
*(_WORD *)((char *)&v13 + 1) = *(_BYTE *)(v11 + v4);
*(_DWORD *)(v12 - 4) ^= *(_BYTE *)((v11 + 3) % v5 + v4) | ((*(_BYTE *)((v11 + 2) % v5 + v4) | (v13 << 8)) << 8);
v14 = *(_BYTE *)(((v11 + 4) % v5 + 1) % v5 + v4);
*(_WORD *)((char *)&v14 + 1) = *(_BYTE *)((v11 + 4) % v5 + v4);
v15 = (v11 + 4) % v5 + 4;
*(_DWORD *)v12 ^= *(_BYTE *)(((v11 + 4) % v5 + 3) % v5 + v4) | ((*(_BYTE *)(((v11 + 4) % v5 + 2) % v5 + v4) | (v14 << 8)) << 8);
v16 = *(_BYTE *)((v15 % v5 + 1) % v5 + v4);
BYTE1(v16) = *(_BYTE *)(v15 % v5 + v4);
v17 = *(_BYTE *)((v15 % v5 + 3) % v5 + v4) | ((*(_BYTE *)((v15 % v5 + 2) % v5 + v4) | (v16 << 8)) << 8);
v18 = v15 % v5 + 4;
*(_DWORD *)(v12 + 4) ^= v17;
v19 = *(_BYTE *)((v18 % v5 + 1) % v5 + v4);
BYTE1(v19) = *(_BYTE *)(v18 % v5 + v4);
v20 = *(_BYTE *)((v18 % v5 + 3) % v5 + v4) | ((*(_BYTE *)((v18 % v5 + 2) % v5 + v4) | (v19 << 8)) << 8);
v21 = v18 % v5 + 4;
*(_DWORD *)(v12 + 8) ^= v20;
v12 += 24;
v22 = *(_BYTE *)((v21 % v5 + 1) % v5 + v4);
BYTE1(v22) = *(_BYTE *)(v21 % v5 + v4);
v23 = *(_BYTE *)((v21 % v5 + 3) % v5 + v4) | ((*(_BYTE *)((v21 % v5 + 2) % v5 + v4) | (v22 << 8)) << 8);
v24 = v21 % v5 + 4;
*(_DWORD *)(v12 - 12) ^= v23;
v25 = *(_BYTE *)((v24 % v5 + 1) % v5 + v4);
*(_WORD *)((char *)&v25 + 1) = *(_BYTE *)(v24 % v5 + v4);
*(_DWORD *)(v12 - 8) ^= *(_BYTE *)((v24 % v5 + 3) % v5 + v4) | ((*(_BYTE *)((v24 % v5 + 2) % v5 + v4) | (v25 << 8)) << 8);
v26 = a2-- == 1;
v11 = (v24 % v5 + 4) % v5;
}
while ( !v26 );
v28 = a1;
a2 = 0;
a3 = 0;
v29 = a1 + 12;
v27 = 9;
do
{
sub_48F410(a1, &a2, &a3);
v30 = a3;
*(_DWORD *)(v29 - 4) = a2;
*(_DWORD *)v29 = v30;
v29 += 8;
--v27;
}
while ( v27 );
v31 = a1 + 84;
v35 = 4;
do
{
v32 = 128;
do
{
sub_48F410(v28, &a2, &a3);
v33 = a3;
*(_DWORD *)(v31 - 4) = a2;
*(_DWORD *)v31 = v33;
v31 += 8;
--v32;
}
while ( v32 );
}
while ( v35-- != 1 );
}
}
}
}
Code:
PBox Key 0x88 0x6A 0x3F 0x24 0x0D3 8 0xA3 0x85 0x2E 0x8A 0x19 0x13 0x44 0x73 0x70 3 0x22 0x38 9 0x0A4 0x0D0 0x31 0x9F 0x29 0x98 0x0FA 0x2E 8 0x89 0x6c 0x4E 0x0EC SBox Key 0x0A6 0x0B 0x31 0x0D1 0x0AC 0x0B5 0x0DF 0x98 0xDB 0x72 0xFD 0x2F 0x0B7 0x0DF 0x1A 0x0D0 0x0ED 0x0AF 0x0E1 0x0B8 0x96 0x7E 0x26 0x6A 0x45 0x90 0x7C 0x0BA 0x99 0x7F 0x2C 0x0F1 0x47 0x99 0x0A1 0x24 0x0F7 0x6C 0x91 0x0B3 0x0E2 0x0F2 1 8 0x16 0x0FC 0x8E 0x85 0x0D8 0x20 0x69 0x63 0x69 0x4E 0x57 0x71 0x0A3 0x0FE 0x58 0x0A4 0x7E 0x3D 0x93 0x0F4 0x8F 0x74 0x95 0x0D 0x58 0x0B6 0x8E 0x72 0x58 0x0CD 0x8B 0x71 0x0EE 0x4A 0x15 0x82 0x1D 0x0A4 0x54 0x7B 0x0B5 0x59 0x5A 0x0C2
Code:
v6 = (signed int)&Blowfish_p_init;
v7 = a1 + 8;
do
{
*(_DWORD *)v7 = *(_DWORD *)v6;
v6 += 4;
v7 += 4;
}
while ( v6 < (signed int)&Blowfish_s_init );
v8 = (signed int)&Blowfish_s_init;
v9 = a1 + 80;
do
{
v10 = 256;
do
{
*(_DWORD *)v9 = *(_DWORD *)v8;
v8 += 4;
v9 += 4;
--v10;
}
while ( v10 );
}
while ( v8 < (signed int)&off_7768F8 );
Code:
int __stdcall sub_48F410(int a1, int a2, int a3)
{
int result; // eax@1
int v4; // edx@1
int v5; // ecx@1
int v6; // ebx@1
int v7; // edx@1
int v8; // ecx@1
int v9; // edx@1
int v10; // ecx@1
int v11; // edx@1
int v12; // ecx@1
int v13; // edx@1
int v14; // ecx@1
int v15; // edx@1
int v16; // ecx@1
int v17; // edx@1
int v18; // ecx@1
int v19; // edx@1
int v20; // ecx@1
int v21; // ebx@1
unsigned __int8 v22; // bp@1
int v23; // ecx@1
result = a1;
v4 = *(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8);
v5 = *(_DWORD *)a3 ^ *(_DWORD *)(a1 + 12) ^ (*(_DWORD *)(a1
+ 4 * (unsigned __int8)(*(_BYTE *)a2 ^ *(_BYTE *)(a1 + 8))
+ 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v4) + 2128) ^ (*(_DWORD *)(a1 + 4 * ((unsigned int)(*(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8)) >> 24) + 80)
+ *(_DWORD *)(a1 + 4 * (((unsigned int)(*(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8)) >> 16) & 0xFF) + 1104))));
v6 = *(_DWORD *)(a1 + 4 * BYTE1(v5) + 2128) ^ (*(_DWORD *)(a1
+ 4
* ((*(_DWORD *)a3 ^ *(_DWORD *)(a1 + 12) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)(*(_BYTE *)a2 ^ *(_BYTE *)(a1 + 8)) + 3152) + (*(_DWORD *)(a1 + 4 * BYTE1(v4) + 2128) ^ (unsigned int)(*(_DWORD *)(a1 + 4 * ((unsigned int)(*(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8)) >> 24) + 80) + *(_DWORD *)(a1 + 4 * (((unsigned int)(*(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8)) >> 16) & 0xFF) + 1104))))) >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((*(_DWORD *)a3 ^ *(_DWORD *)(a1 + 12) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)(*(_BYTE *)a2 ^ *(_BYTE *)(a1 + 8)) + 3152) + (*(_DWORD *)(a1 + 4 * BYTE1(v4) + 2128) ^ (unsigned int)(*(_DWORD *)(a1 + 4 * ((unsigned int)(*(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8)) >> 24) + 80) + *(_DWORD *)(a1 + 4 * (((unsigned int)(*(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8)) >> 16) & 0xFF) + 1104))))) >> 16) & 0xFF)
+ 1104));
v7 = *(_DWORD *)(a1 + 16) ^ (*(_DWORD *)(a1
+ 4
* (unsigned __int8)(*(_BYTE *)a3 ^ *(_BYTE *)(a1 + 12) ^ (*(_BYTE *)(a1 + 4 * (unsigned __int8)(*(_BYTE *)a2 ^ *(_BYTE *)(a1 + 8)) + 3152)
+ (*(_BYTE *)(a1 + 4 * BYTE1(v4) + 2128) ^ (*(_BYTE *)(a1 + 4 * ((unsigned int)(*(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8)) >> 24) + 80) + *(_BYTE *)(a1 + 4 * (((unsigned int)(*(_DWORD *)a2 ^ *(_DWORD *)(a1 + 8)) >> 16) & 0xFF) + 1104)))))
+ 3152)
+ v6) ^ v4;
v8 = *(_DWORD *)(a1 + 20) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v7 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v7) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v7 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v7 >> 16) & 0xFF)
+ 1104)))) ^ v5;
v9 = *(_DWORD *)(a1 + 24) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v8 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v8) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v8 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v8 >> 16) & 0xFF)
+ 1104)))) ^ v7;
v10 = *(_DWORD *)(a1 + 28) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v9 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v9) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v9 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v9 >> 16) & 0xFF)
+ 1104)))) ^ v8;
v11 = *(_DWORD *)(a1 + 32) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v10 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v10) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v10 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v10 >> 16) & 0xFF)
+ 1104)))) ^ v9;
v12 = *(_DWORD *)(a1 + 36) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v11 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v11) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v11 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v11 >> 16) & 0xFF)
+ 1104)))) ^ v10;
v13 = *(_DWORD *)(a1 + 40) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v12 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v12) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v12 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v12 >> 16) & 0xFF)
+ 1104)))) ^ v11;
v14 = *(_DWORD *)(a1 + 44) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v13 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v13) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v13 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v13 >> 16) & 0xFF)
+ 1104)))) ^ v12;
v15 = *(_DWORD *)(a1 + 48) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v14 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v14) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v14 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v14 >> 16) & 0xFF)
+ 1104)))) ^ v13;
v16 = *(_DWORD *)(a1 + 52) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v15 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v15) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v15 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v15 >> 16) & 0xFF)
+ 1104)))) ^ v14;
v17 = *(_DWORD *)(a1 + 56) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v16 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v16) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v16 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v16 >> 16) & 0xFF)
+ 1104)))) ^ v15;
v18 = *(_DWORD *)(a1 + 60) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v17 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v17) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v17 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v17 >> 16) & 0xFF)
+ 1104)))) ^ v16;
v19 = *(_DWORD *)(a1 + 64) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v18 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v18) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v18 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v18 >> 16) & 0xFF)
+ 1104)))) ^ v17;
v20 = *(_DWORD *)(a1 + 68) ^ (*(_DWORD *)(a1 + 4 * (unsigned __int8)v19 + 3152)
+ (*(_DWORD *)(a1 + 4 * BYTE1(v19) + 2128) ^ (*(_DWORD *)(a1
+ 4 * ((unsigned int)v19 >> 24)
+ 80)
+ *(_DWORD *)(a1
+ 4
* (((unsigned int)v19 >> 16) & 0xFF)
+ 1104)))) ^ v18;
v21 = *(_DWORD *)(a1 + 4 * BYTE1(v20) + 2128) ^ (*(_DWORD *)(a1 + 4 * ((unsigned int)v20 >> 24) + 80)
+ *(_DWORD *)(a1 + 4 * (((unsigned int)v20 >> 16) & 0xFF) + 1104));
v22 = v20;
v23 = *(_DWORD *)(a1 + 76) ^ v20;
*(_DWORD *)a3 = *(_DWORD *)(a1 + 72) ^ (*(_DWORD *)(a1 + 4 * v22 + 3152) + v21) ^ v19;
*(_DWORD *)a2 = v23;
return result;
}
If anybody can provide any help it would be greatly appreciated