Jump to content
SubSpace Forum Network

Recommended Posts

Posted

I can explain XOR

 

In C++ the symbol looks like this ^ and its a bitwise operator

Here is a good example of some code that will swap values

 

Lets say

int a=7;

int b=10;

 

a ^= b;

b ^= a;

a ^= b;

 

Now you are saying "WTF", ill explain.

The binary value of 7 is 00000111 and the binary value of 10 is 00001010

 

So what XOR means is Exclusive OR, ill show you how a regular OR works (c++ the operator is | )

 

00000111 = 7

00001010 = 10

 

OR'd together the number becomes

 

00001111 = 15

 

So what happened was that the numbers combined. In an Exclusive OR (XOR)

 

00000111 = 7

00001010 = 10

 

XOR'd together

 

00001101 = 13

 

So hopely you see the difference, because its kinda hard to explain :(

 

So in that swap code i posted above

 

//a ^=b does the below

//00000111

//00001010

 

a ^=b; //a now = 00001101

 

//b ^=a does the below

//00001101

//00001010

b ^=a; //b now = 00000111

 

//a ^=b does the below

//00001101

//00000111

a ^=b;//a now = 1010

 

So in the end, a = 10 and b = 7 thus the values have been swaped

Posted
Well I did know what the xor operator does, but I didn't know you can swap numbers like that. Anyways, im looking to see an explaination of the subspace encryption.
Posted

The subspace encryption has not been broken by anyone (yet). I doubt if it ever will. Thus no one will be able to explain you the encryption. (Also because it kept secret to avoid people making their own client and cheat)

 

-MMaverick

Posted

the subspace encryption has been broken, you're thinking of continuum encryption.

 

this is straight from http://www.ssihosting.com/catid/files/addendum.txt

 

-=Encryption=-

SubSpace uses encryption.  Encryption means to obscure the true meaning of a message
using a numerical pattern.

When SubSpace connects to a SubGame game server, it firsts completes a key exchange.
ie.

00 01 KK KK KK KK VV VV
00 05 SS SS RR RR
00 06 SS SS RR RR TT TT TT TT
00 02 ~K ~K ~K ~K
'KK = Random number (must be negative)
'VV = Encryption version (1 for SubSpace, 16 for Continuum)
'SS = Number of connections since last recycle
'RR = Random number
'TT = Local time
'~K = Session key (must be unary -KK)


There is some protocol that goes along with these packets:

00 01 gets resent until 00 02 is recv'd.
If KK >= 0, then a proper SubSpace server will not acknowledge your connection.
00 05/00 06 isn't used in older SubSpace servers, it's recommended you take this
  into account while designing your own stack.
Up until the 00 02 response, no other packet types (should be) accepted by the server.


Why we use 00 05/00 06:

A few years ago I discovered that sending a massive load of 00 01 packets to a SubGame
would effectively create a Denial of Service condition; PriitK patched it by
masterfully recoding the connection protocol for SubGame to ignore requests until it
gets an 00 06 response to SG's 00 05.  It is therefore a fix for a nasty problem.


Why we use packets limited to 520 bytes:

For both bandwidth reasons and, interestingly enough, the hard fact that SubSpace's
encryption uses a buffer of 520 bytes - anything longer cannot be decoded.


There are some ways to disable encryption:

Send a KK field of 0.  00 01 00 00 00 00 01 00
The server must respond with a NULL key (no encryption).
Custom SubSpace stacks may ignore this.

Encryption may be disabled server-side if the key you send
is the same as the key you get back.


But if you want to use encryption:

The lengthy DOC by Coconut emulator explains how he ripped SS encryption
to a DLL file with SoftICE for use in VB programs.  MERVBot contains C++
code which encapsulates all aspects of maintaining a SubSpace session,
including encryption.


Security of the encryption:

This method of encryption is very weak to a chosen-plaintext attack, and
tends to share every fourth byte of the keystream with other connections
established within ~48 hours.

For example, SECRET_KEY ^ PLAINTEXT -> CIPHER_TEXT, if you know PLAINTEXT
then PLAINTEXT ^ CIPHER_TEXT = SECRET_KEY.  In short, do not trust any
personal data on a logged connection to SubSpace.  Continuum, on the other
hand, has military-grade encryption =))

 

Then from mervbot's encrypt.cpp:

 

//////// Misc. encryption ////////

char ROT13(char c)
{
if (c >= 'a' && c <= 'z')
{
 c += 13;
 if (c > 'z') c -= 26;
}
else if (c >= 'A' && c <= 'Z')
{
 c += 13;
 if (c > 'Z') c -= 26;
}

return c;
}


//////// SubSpace packet encryption ////////
// Courtesy of Coconut Emulator

SS_ENCR::SS_ENCR()
{
key = 0;
sentKey = 0;
}

Uint32 SS_ENCR::generateKey()
{
if (sentKey)
 return sentKey;

Uint32 edx = getTime() * 0xCCCCCCCD;

Uint32 res = (keygen.getNext() << 16) + (edx >> 3) + keygen.getNext();

res = (res ^ edx) - edx;

if (res <= 0x7fffffff) res = ~res + 1;

return (sentKey = res);
}

Uint32 SS_ENCR::getSessionKey(Uint32 clientKey)
{
return ((~clientKey) + 1);	// Two's complement, same as arithmetic minus on unsigned data
}

bool SS_ENCR::validateSessionKey(Uint32 serverKey)
{
return ((serverKey == sentKey) || (serverKey == getSessionKey(sentKey)));
}

bool SS_ENCR::initializeEncryption(Uint32 serverKey)
{
if (!validateSessionKey(serverKey)) return false;

if (sentKey == serverKey)
{
 key = 0;

 memset(keystream, 0, 520);
}
else
{
 key = serverKey;

 Uint16 *stream = (Uint16*)keystream;

 prng.seed(serverKey);

 for (Uint32 i = 0; i < 260; ++i)
 {
	 stream[i] = prng.getNextE();
 }
}

return true;
}

void SS_ENCR::encrypt(char *msg, Uint32 len)
{
if (!key) return;

Uint32 ksi = 0,
    i = 1,
    IV = key;

if (*msg == 0)
{
 if (len <= 2) return;

 ++i;
}

while (i + 4 <= len)
{
 *(Uint32*)&msg[i] = IV = (getLong(msg, i) ^ getLong(keystream, ksi) ^ IV);

 i += 4;
 ksi += 4;
}

Uint32 diff = len - i;

if (diff)
{
 Uint32 buffer = 0;
 memcpy(&buffer, msg + i, diff);
 buffer ^= getLong(keystream, ksi) ^ IV;
 memcpy(msg + i, &buffer, diff);
}
}

void SS_ENCR::decrypt(char *msg, Uint32 len)
{
if (!key) return;

Uint32 ksi = 0,
    i = 1,
    IV = key,
    EDX;

if (*msg == 0)
{
 if (len <= 2) return;

 ++i;
}

while (i + 4 <= len)
{
 EDX = getLong(msg, i);
 *(Uint32*)&msg[i] = getLong(keystream, ksi) ^ IV ^ EDX;
 IV = EDX;

 i += 4;
 ksi += 4;
}

Uint32 diff = len - i;

if (diff)
{
 Uint32 buffer = 0;
 memcpy(&buffer, msg + i, diff);
 buffer ^= getLong(keystream, ksi) ^ IV;
 memcpy(msg + i, &buffer, diff);
}
}

void SS_ENCR::reset()
{
key = 0;
sentKey = 0;
}


//////// Billing password encryption ////////
// Also from Coconut Emulator

void hashP!@#$%^&*word(BYTE *in, BYTE *out)
{
Uint32 StrLen = STRLEN((char*)in);
BYTE Factor = simpleChecksum(in, StrLen);
BYTE Char;

for (Uint32 L = 0; L < StrLen; ++L)
{
 Char = in[L] ^ Factor;
 Factor = (Factor ^ (Char << (Char & 3))) & 255;
 if (Char == 0)
	 Char = 0xED;
 out[L] = Char;
}

out[L] = 0;
}


//////// Billing password decryption ////////

void inverseHash(BYTE *In, BYTE *Out, BYTE Key)
{
size_t StrLen = STRLEN((char*)In);

for (Uint32 L = 0; L < StrLen; ++L)
{
 BYTE Char = In[L];
 if (Char == 0xED)
	 Char = 0;
 Out[L] = Char ^ (BYTE)Key;
 Key = (Key ^ (Char << (Char & 3))) & 255;
}
}

void decryptHashedP!@#$%^&*word(BYTE *password)
{
Uint32 StrLen = STRLEN((char*)password);

BYTE *Buffer = new BYTE[StrLen + 1];
Buffer[StrLen] = 0;

// passwords of EVEN length are very easy to crack.
if (StrLen & 1)
{
 // Guess and check to find one of the solutions
 for (int i = 0; i < 256; ++i)
 {
	 // Generate a possible solution
	 inverseHash(password, Buffer, i);

	 // Compare resultant hash with given hash
	 BYTE Char, Key = i;
	 bool OK = true;

	 for (Uint32 L = 0; L < StrLen; ++L)
	 {
   Char = Buffer[L];

   if (!isPrintable(Char))
   {
  	 OK = false;

  	 break;
   }

   Char ^= Key;
   Key = (Key ^ (Char << (Char & 3))) & 255;
   if (Char == 0)
  	 Char = 0xED;

   if (Char != password[L])
   {
  	 OK = false;

  	 break;
   }
	 }

	 if (OK)
   break;
 }
}
else
{
 // Generate password checksum
 inverseHash(password, Buffer, 0);

 // Generate actual password
 inverseHash(password, Buffer, simpleChecksum(Buffer, StrLen));
}

memcpy(password, Buffer, StrLen);

delete Buffer;
Buffer = NULL;
}

 

make what you want of it...

Posted

I think I already got the encryption this is what I got (in perl):

 

sub initialize {

my $seed = $_[0];

my ($tempSeed, $oldSeed);

$tempSeed = $seed;

 

for ($i = 0; $i < (520 / 2); $i++) {

$oldSeed = $tempSeed;

 

$tempSeed = (($oldSeed * 0x834E0B5F) >> 48) & 0xffffffff;

$tempSeed = (($tempSeed + ($tempSeed >> 31)) & 0xffffffff);

$tempSeed = (((($oldSeed % 0x1F31D) * 16807) - ($tempSeed * 2836) + 123) & 0xffffffff);

if ($tempSeed > 0x7fffffff ) {

$tempSeed = (($tempSeed + 0x7fffffff) & 0xffffffff);

}

$table[$i .. ($i+1)] = ence_short(short(tempSeed & 0xffff));

}

}

 

sub ssencrypt {

my @packet = @_;

my ($tempKey, $count, @output);

$tempKey = $serverKey;

#$count = scalar(@packet) + (4 - scalar(@packet) % 4);

$count = scalar(@packet);

@output = @packet;

for ($i = 0; $i < $count; $i += 4) {

$tempInt = dece_int(@output[$i .. ($i+3)]) ^ dece_int($table[$i]) ^ $tempKey;

$tempKey = $tempInt;

@output[$i .. ($i+3)] = ence_int(int($tempInt & 0xffffffff));

}

return @output;

}

 

sub ssdecrypt {

my @packet = @_;

my ($tempKey, $count, @output);

$tempKey = $serverKey;

#$count = scalar(@packet) + (4 - scalar(@packet) % 4);

$count = scalar(@packet);

@output = @packet;

for ($i = 0; $i < $count; $i += 4) {

$tempInt = dece_int($table[$i]) ^ $tempKey ^ dece_int(@output[$i .. ($i+3)]);

$tempKey = dece_int($i .. ($i+3));

@output[$i .. ($i+3)] = ence_int(int($tempInt & 0xffffffff));

}

return @output;

}

  • 2 weeks later...
Posted
The subspace encryption has not been broken by anyone (yet). I doubt if it ever will. Thus no one will be able to explain you the encryption. (Also because it kept secret to avoid people making their own client and cheat)

 

-MMaverick

SubSpace encryption is broken in every sense of the word. There's some code on my website that can decrypt password packets without the key, which would be useful if you were using one of the old buffer stealing exploits.

Guest
This topic is now closed to further replies.
×
×
  • Create New...