/*------------------------------------------------*\ * * * Reverse-engineered by Cluracan * * (strangelove@heroinpuppy.com). * * * * This code is provided "as is" without warranty * * of any kind, either expressed or implied. * * * \*------------------------------------------------*/ #include using namespace std; typedef unsigned char byte; typedef unsigned int uint; struct GENS_DATA { byte sum[ 16 ]; // Might make more sense as uint[4] uint unk1; uint unk2; byte buf[ 64 ]; }; /* 0x0049FCB0 */ const byte s_blank_input[ 64 ] = { '\x80', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* 00410AA0 */ void s_memset( byte* out, byte ch_val, uint len ) { /* Just a memset */ for (uint i = 0; i < len; i++) { out[ i ] = ch_val; } } /* 00410A70 */ void s_foo_4( byte* out, const uint* in, uint len ) { for (uint i = 0, j = 0; j < len; i++, j+=4) { out[ j ] = (byte) ( in[ i ] & 0xFF ); out[ j + 1 ] = (byte) ( ( in[ i ] >> 8 ) & 0xFF ); out[ j + 2 ] = (byte) ( ( in[ i ] >> 16 ) & 0xFF ); out[ j + 3 ] = (byte) ( ( in[ i ] >> 24 ) & 0xFF ); } } /* 00410A20 */ void s_foo_5( byte* out, const byte* in, uint len ) { for (uint i = 0, j = 0; j < len; i++, j+=4) { ((uint*) out)[ i ] = ( ((uint) in[ j ]) ) | ( ( ((uint) in[ j + 1 ]) ) << 8 ) | ( ( ((uint) in[ j + 2 ]) ) << 16 ) | ( ( ((uint) in[ j + 3 ]) ) << 24 ); } } /* 0040FB90 */ void s_copy( byte* buf, const byte* in, uint len ) { /* essentially memcpy */ for (uint i = 0; i < len; i++) { buf[ i ] = in[ i ]; } } /* 0040FA50 */ void s_init( GENS_DATA* data ) { ((uint*)data->sum)[ 0 ] = 0x67452301; ((uint*)data->sum)[ 1 ] = 0xEFCDAB89; ((uint*)data->sum)[ 2 ] = 0x98BADCFE; ((uint*)data->sum)[ 3 ] = 0x10325476; data->unk1 = 0; data->unk2 = 0; } /* 0040FBD0 */ void s_foo_2( byte* in_out, const byte* in ) { /* 64-byte digest */ uint local_16[ 16 ]; uint local_17 = ((uint*)in_out)[ 0 ]; uint local_18 = ((uint*)in_out)[ 1 ]; uint local_20 = ((uint*)in_out)[ 2 ]; uint local_19 = ((uint*)in_out)[ 3 ]; s_foo_5( (byte*) local_16, in, 64 ); #define _S_INT_MAGIC_1( a, b, c, d, i , x, l, r ) \ a = ( ( b & d ) | ( (~b) & c ) ) \ + local_16[ i ] + a + (unsigned)x; \ a = ( a << l ) | ( a >> r ); \ a = a + b _S_INT_MAGIC_1( local_17, local_18, local_19, local_20, 0, 0xD74AA478, 7, 25 ); _S_INT_MAGIC_1( local_19, local_17, local_20, local_18, 1, 0xE3CEB456, 12, 20 ); _S_INT_MAGIC_1( local_20, local_19, local_18, local_17, 2, 0x2420B0DB, 17, 15 ); _S_INT_MAGIC_1( local_18, local_20, local_17, local_19, 3, 0x212AC5EE, 22, 10 ); _S_INT_MAGIC_1( local_17, local_18, local_19, local_20, 4, 0x325C6CAF, 7, 25 ); _S_INT_MAGIC_1( local_19, local_17, local_20, local_18, 5, 0x4785B22A, 12, 20 ); _S_INT_MAGIC_1( local_20, local_19, local_18, local_17, 6, 0x48346C63, 17, 15 ); _S_INT_MAGIC_1( local_18, local_20, local_17, local_19, 7, 0xF2485501, 22, 10 ); _S_INT_MAGIC_1( local_17, local_18, local_19, local_20, 8, 0x3980C258, 7, 25 ); _S_INT_MAGIC_1( local_19, local_17, local_20, local_18, 9, 0x834412AF, 12, 20 ); _S_INT_MAGIC_1( local_20, local_19, local_18, local_17, 10, 0x3DCF65B1, 17, 15 ); _S_INT_MAGIC_1( local_18, local_20, local_17, local_19, 11, 0x831CD76E, 22, 10 ); _S_INT_MAGIC_1( local_17, local_18, local_19, local_20, 12, 0x6B605552, 7, 25 ); _S_INT_MAGIC_1( local_19, local_17, local_20, local_18, 13, 0xFD937193, 12, 20 ); _S_INT_MAGIC_1( local_20, local_19, local_18, local_17, 14, 0xA669B38E, 17, 15 ); _S_INT_MAGIC_1( local_18, local_20, local_17, local_19, 15, 0x44C43821, 22, 10 ); #define _S_INT_MAGIC_2( a, b, c, d, i , x, l, r ) \ a = ( ( b & d ) | ( (~d) & c ) ) \ + local_16[ i ] + a + x; \ a = ( a << l ) | ( a >> r ); \ a = a + b _S_INT_MAGIC_2( local_17, local_18, local_20, local_19, 1, 0x341E2562, 5, 0x1B ); _S_INT_MAGIC_2( local_19, local_17, local_18, local_20, 6, 0xC0EAB340, 9, 0x17 ); _S_INT_MAGIC_2( local_20, local_19, local_17, local_18, 11, 0x265B3A51, 0xE, 0x12 ); _S_INT_MAGIC_2( local_18, local_20, local_19, local_17, 0, 0xE9B6C7AA, 0x14, 0xC ); _S_INT_MAGIC_2( local_17, local_18, local_20, local_19, 5, 0xD62F132D, 5, 0x1B ); _S_INT_MAGIC_2( local_19, local_17, local_18, local_20, 10, 0x2541B435, 9, 0x17 ); _S_INT_MAGIC_2( local_20, local_19, local_17, local_18, 15, 0xD8A1E681, 0xE, 0x12 ); _S_INT_MAGIC_2( local_18, local_20, local_19, local_17, 4, 0x37B3FBC8, 0x14, 0xC ); _S_INT_MAGIC_2( local_17, local_18, local_20, local_19, 9, 0x21E1C3E6, 5, 0x1B ); _S_INT_MAGIC_2( local_19, local_17, local_18, local_20, 14, 0xC33707D6, 9, 0x17 ); _S_INT_MAGIC_2( local_20, local_19, local_17, local_18, 3, 0xFBD50D87, 0xE, 0x12 ); _S_INT_MAGIC_2( local_18, local_20, local_19, local_17, 8, 0x455A34ED, 0x14, 0xC ); _S_INT_MAGIC_2( local_17, local_18, local_20, local_19, 13, 0xA9E38905, 5, 0x1B ); _S_INT_MAGIC_2( local_19, local_17, local_18, local_20, 2, 0x8CE3A3F8, 9, 0x17 ); _S_INT_MAGIC_2( local_20, local_19, local_17, local_18, 7, 0x676F82D9, 0xE, 0x12 ); _S_INT_MAGIC_2( local_18, local_20, local_19, local_17, 12, 0xBD234B8A, 0x14, 0xC ); #define _S_INT_MAGIC_3( a, b, c, d, i , x, l, r ) \ a = ( ( b ^ c ) ^ d ) \ + local_16[ i ] + a + x; \ a = ( a << l ) | ( a >> r ); \ a = a + b _S_INT_MAGIC_3( local_17, local_18, local_20, local_19, 5, 0x32FA3942, 0x4, 0x1C ); _S_INT_MAGIC_3( local_19, local_17, local_18, local_20, 8, 0x87E1F681, 0xB, 0x15 ); _S_INT_MAGIC_3( local_20, local_19, local_17, local_18, 11, 0x6D3D6122, 0x10, 0x10 ); _S_INT_MAGIC_3( local_18, local_20, local_19, local_17, 14, 0xFDE2A80C, 0x17, 0x9 ); _S_INT_MAGIC_3( local_17, local_18, local_20, local_19, 1, 0xA4B4EA14, 0x4, 0x1C ); _S_INT_MAGIC_3( local_19, local_17, local_18, local_20, 4, 0x4A7ECFA9, 0xB, 0x15 ); _S_INT_MAGIC_3( local_20, local_19, local_17, local_18, 7, 0xFB6B46B0, 0x10, 0x10 ); _S_INT_MAGIC_3( local_18, local_20, local_19, local_17, 10, 0xBE7FBC70, 0x17, 0x9 ); _S_INT_MAGIC_3( local_17, local_18, local_20, local_19, 13, 0x289E75C6, 0x4, 0x1C ); _S_INT_MAGIC_3( local_19, local_17, local_18, local_20, 0, 0xE33127FA, 0xB, 0x15 ); _S_INT_MAGIC_3( local_20, local_19, local_17, local_18, 3, 0xD4E73E85, 0x10, 0x10 ); _S_INT_MAGIC_3( local_18, local_20, local_19, local_17, 6, 0x4881D075, 0x17, 0x9 ); _S_INT_MAGIC_3( local_17, local_18, local_20, local_19, 9, 0xD9BED539, 0x4, 0x1C ); _S_INT_MAGIC_3( local_19, local_17, local_18, local_20, 12, 0xE6DB97E5, 0xB, 0x15 ); _S_INT_MAGIC_3( local_20, local_19, local_17, local_18, 15, 0xEFA27CF8, 0x10, 0x10 ); _S_INT_MAGIC_3( local_18, local_20, local_19, local_17, 2, 0xCFA55665, 0x17, 0x9 ); #define _S_INT_MAGIC_4( a, b, c, d, i , x, l, r ) \ a = ( ( (~c) | b ) ^ d ) \ + local_16[ i ] + a + x; \ a = ( a << l ) | ( a >> r ); \ a = a + b _S_INT_MAGIC_4( local_17, local_18, local_19, local_20, 0, 0x14292244, 0x6, 0x1A ); _S_INT_MAGIC_4( local_19, local_17, local_20, local_18, 7, 0x4A2AFF97, 0x0A, 0x16 ); _S_INT_MAGIC_4( local_20, local_19, local_18, local_17, 14, 0xABE223A7, 0x0F, 0x11 ); _S_INT_MAGIC_4( local_18, local_20, local_17, local_19, 5, 0xFC93A039, 0x15, 0x0B ); _S_INT_MAGIC_4( local_17, local_18, local_19, local_20, 12, 0x25B1663C, 0x6, 0x1A ); _S_INT_MAGIC_4( local_19, local_17, local_20, local_18, 3, 0x8F0CCC92, 0x0A, 0x16 ); _S_INT_MAGIC_4( local_20, local_19, local_18, local_17, 10, 0x4F4FF47D, 0x0F, 0x11 ); _S_INT_MAGIC_4( local_18, local_20, local_17, local_19, 1, 0x85845DD1, 0x15, 0x0B ); _S_INT_MAGIC_4( local_17, local_18, local_19, local_20, 8, 0x61A57E4F, 0x6, 0x1A ); _S_INT_MAGIC_4( local_19, local_17, local_20, local_18, 15, 0x6E2CE6E0, 0x0A, 0x16 ); _S_INT_MAGIC_4( local_20, local_19, local_18, local_17, 6, 0xA0313414, 0x0F, 0x11 ); _S_INT_MAGIC_4( local_18, local_20, local_17, local_19, 13, 0x4E0711A1, 0x15, 0x0B ); _S_INT_MAGIC_4( local_17, local_18, local_19, local_20, 4, 0xF8537E82, 0x6, 0x1A ); _S_INT_MAGIC_4( local_19, local_17, local_20, local_18, 11, 0xBD38F235, 0x0A, 0x16 ); _S_INT_MAGIC_4( local_20, local_19, local_18, local_17, 2, 0x8AD7D2BB, 0x0F, 0x11 ); _S_INT_MAGIC_4( local_18, local_20, local_17, local_19, 9, 0xEB868991, 0x15, 0x0B ); ((uint*)in_out)[ 0 ] += local_17; ((uint*)in_out)[ 1 ] += local_18; ((uint*)in_out)[ 2 ] += local_20; ((uint*)in_out)[ 3 ] += local_19; /* Inconsequential memset of local_16[] omitted */ } /* 0040FA90 */ void s_foo_1( GENS_DATA* data, const byte* in, uint len ) { uint local_1; uint local_2 = ( data->unk1 >> 3 ) & 0x3F; data->unk1 += len * 8; if (data->unk1 < ( len << 3 )) { data->unk2++; } data->unk2 += ( len >> 29 ); uint local_3 = 0x40 - local_2; if (len >= local_3) { s_copy( data->buf + local_2, in, local_3 ); s_foo_2( data->sum, data->buf ); // ? for (local_1 = local_3; local_1 + 63 < len; local_1 += 64) { s_foo_2( data->sum, in + local_1 ); // ? } local_2 = 0; } else local_1 = 0; s_copy( data->buf + local_2, in + local_1, len - local_1 ); } /* 00410AD0 */ void s_foo_3( byte out[16], GENS_DATA* data ) { uint local_1; uint local_3[ 2 ]; uint local_4; uint local_5; s_foo_4( (byte*) local_3, &data->unk1, 8 ); local_1 = ( data->unk1 >> 3 ) & 0x3F; if (local_1 < 0x38) { local_5 = 0x38 - local_1; } else { local_5 = 0x78 - local_1; } local_4 = local_5; s_foo_1( data, s_blank_input, local_4 ); // See top for constant s_foo_1( data, (byte*)local_3, 8 ); s_foo_4( out, (uint*) data, 16 ); s_memset( (byte*) data, 0, 0x58 ); // 0x58 == sizeof( GENS_DATA ) ;) } /* 00410C10 */ void s_digest( const char* sz_in, char* sz_out ) { /* Inconsequential code omitted */ byte s[ 16 ]; uint in_len = (uint) strlen( sz_in ); GENS_DATA data; s_init( &data ); s_foo_1( &data, (const byte*) sz_in, in_len ); s_foo_3( s, &data ); for (uint i = 0; i < 16; i++) { sprintf( sz_out + i*2, "%02x", s[ i ] ); } } int main( int argc, char* argv[] ) { int randNum, randNum2, randNum3, randNum4, randNum5; srand( time(NULL) ); randNum = rand() % 255 + 1; randNum2 = rand() % 255 + 1; randNum3 = rand() % 255 + 1; randNum4 = rand() % 255 + 1; randNum5 = rand() % 99999999 + 11111111; char s[ 33 ]; s_digest( "IP="" + randNum1 + "." + randNum2 + "." + randNum3 + "." + randNum4 + ". H="" + randNum5 + " R=20810 D=13371 U=13371337 M=1337x1337 V=19.3 P=168356072050782049568476", s ); cout << s << '\n'; return EXIT_SUCCESS; }