SREmu Backup

 unsigned long GenerateValue( unsigned long* Ptr ) {
    unsigned long val = *Ptr;
    for( int i = 0; i < 32; i++ )
       val = (((((((((((val >> 2)^val) >> 2)^val) >> 1)^val)  >> 1)^val) >> 1)^val)&1)|((((val&1) << 31)|(val  >> 1))&0xFFFFFFFE);
    return ( *Ptr = val );
 }
  
 unsigned char byte1seeds[3];
 void SetupSecurityCNT( unsigned long seed ) {
    if( seed == 0 ) seed = 0x9ABFB3B6;
    unsigned long mut = PackData.cntSeed;
    unsigned long mut1 = GenerateValue( &mut );
    unsigned long mut2 = GenerateValue( &mut );
    unsigned long mut3 = GenerateValue( &mut );
    GenerateValue( &mut );
    unsigned char byte1 = (mut&0xFF)^(mut3&0xFF)
    unsigned char byte2 = (mut1&0xFF)^(mut2&0xFF);
    if( !byte1 ) byte1 = 1;
    if( !byte2 ) byte2 = 1;
    byte1seeds[0] = byte1^byte2;
    byte1seeds[1] = byte2;
    byte1seeds[2] = byte1;
 }
  
 unsigned char SecurityCNT( void ) {
    unsigned char result = (byte1seeds[2]*(~byte1seeds[0]+byte1seeds[1]));
    result = result ^ ( result >> 4 );
    byte1seeds[0] = result;
    return result;
 }
  
 unsigned char SecurityCRC( char* packet, int length, unsigned long seed )  {
    if( !packet ) return 0;
    unsigned long checksum = 0xFFFFFFFF;
    length &= 0x7FFF;
    char* ptr = packet;
    unsigned long moddedseed = seed << 8;
    for( int i = 0; i < length; i++ )
       checksum = ( checksum >> 8 ) ^ table[moddedseed + ( ( *(ptr++) ^  checksum ) & 0xFF )];
    unsigned char result = ( (checksum>>24)&0xFF ) + (  (checksum>>8)&0xFF ) + ( (checksum>>16)&0xFF ) + (  checksum&0xFF );
    return result;
 }

The first packet looks like this:

struct firstpacket {
    unsigned short size;
    unsigned short code;
    unsigned short security;
    unsigned char flags;
    unsigned char bfKey[8];
    unsigned long countSeed;
    unsigned long checkSeed;
    unsigned long handshakeDwords[5];
};

If flags & 0x08, the seeds will be there, otherwise they won’t. You call SetupSecurityCNT with the countSeed after you get it, and when you get checkSeed, & it with 0xFF then if it’s 0, set it to 1.

The packet must be 100% built and ready to send (including the CNT byte) before you can generate the CRC byte. Now, set the CRC byte value to 0, then call the SecurityCRC function, passing seed the checkSeed value in the first packet, and set the CRC byte in the packet to the result. You can now send the packet.

But, since the client and your CNT function are out of synch, you must then re-generate the CNT and CRC bytes of each outgoing packet from the client or you’ll get d/c’ed. It’s easy, really, just call your SecurityCNT function to get the frist byte, and set the CRC byte of the packet to 0, then generate the CRC normally and send it on its way.

https://cdn.projecthax.com/downloads/sremu.tar.gz