Jump to content
SubSpace Forum Network

catid

Member
  • Posts

    39
  • Joined

  • Last visited

Contact Methods

  • AIM
    MrCatid
  • MSN
    n/a
  • Website URL
    http://catid.sscentral.com
  • ICQ
    18736684
  • Yahoo
    n/a

Profile Information

  • Location
    Florida State

catid's Achievements

Newbie

Newbie (1/14)

  1. 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.
  2. Would you accept a bot programmer that is an -*BAD WORD*-?
  3. well the only stuff I'm missing is the stuff that I'd have to fool around with the !@#$%^&*embly to get, so door sync, cont encryption, that's about all I can think of offhand. And I have some stuff that doesn't exist in the continuum client. Snrrrub may have code for the door synch. Shrap is also sync'd. ctmenc is tough. you need to write a virtual machine to rip it, whether starting from a deadlisting or reading the code in memory (which is my fav apprch)
  4. G'day. Coming to you from my apartment & new cable service (hurrah!) Actually, the ships' bounding contours may be five-dimensional one-sided surfaces if we want them to be. ^_^
  5. Thanks Sexy Man Steak! By the way, Pikachu has a SPIKE! OMG!
  6. also just updated to fix bugs in the access level restrictions for the operator commands
  7. Patch is available here
  8. good find. would have appreciated you sending this to me, though, since i don't browse the forums very often
  9. agreed
  10. well, the difference between this and subgame is that this is totally stateless: the 00 01 key needs to be remembered until the client returns a 00 06. thus, subgame doesn't have flood protection, only anti-spoof protection
  11. This may be the best way to do totally stateless handshakes for VIE encryption. syncookies.txt : ----------------- Executive summary ----------------- I've developed new, stateless protection against spoofing connections to disrupt an ASSS zone. This protection is only for SubSpace (not Continuum) clients, as Ctm already has this ability. All SS clients should be compatible.  The following are tested: MERVBot (build 41), VIE SubSpace 1.34 New protection is only used when module enc_vie is loaded. Cons: 24 additional bytes overhead on SS/bot connections Slightly higher rate of connection failure due to ordinary packetloss; bots won't notice this. Pros: VIE connections cannot be spoofed, which disables a large number of attack vectors. ---------------------------------------------------- VIE SubSpace 1.34 connecting to ASSS with syncookies ---------------------------------------------------- c2s    Connection from 127.0.0.1:1817 (proto 1) c2s 0000  00 01 09 7F 9D E6 01 00              ........ Nothing new, yet. s2c 0000  00 0E 06 00 05 C7 B2 5A 1D 06 00 05 C8 6D 38 E7  .......Z.....m8. s2c 0010  06 00 05 F7 80 62 19 06 00 02 F7 80 62 19     .....b......b. Pow!  That doesn't look normal! The server hasn't actually connected with the client yet, despite that 00 02. To break it down: 00 0E -- clustered to reduce chance of packetloss and reordering    06  00 05 C7 B2 5A 1D -- syncookie, sent first so that it's returned first and processed first    06  00 05 C8 6D 38 E7 -- used to bust through encrypted responses, sent second to reduce calculations, MSB=0    06  00 05 F7 80 62 19 -- same as the key, sent third because the second one had more reason to be second    06  00 02 F7 80 62 19 -- normal key response, the client will think it's connected as soon as it receives this c2s 0000  00 06  C7 B2 5A 1D  9D 74 27 00           ....Z..t'. The server has just created a connection, since the syncookie was returned. c2s 0000  00 06  C8 6D 38 E7  9D 74 27 00           ...m8..t'. c2s 0000  00 06  F7 80 62 19  9D 74 27 00           ....b..t'. Client responds to each of the 00 05 messages in turn. The server ignores the first one in this case, based on the MSB of the response and gets the key from the second one. c2s    Before decryption: c2s 0000  00 03 56 65 DF AF 98 15 71 EA 5E 67 81 66 19 95  ..Ve....q.^g.f.. c2s 0010  BE 8B 43 6B CA 79 9E C6 09 CE 8D B8 62 82 11 FC  ..Ck.y......b... c2s 0020  99 EB 5E 12 A0 75 C7 F9 8C B9 72 35 1C D1 16 DC  ..^..u....r5.... c2s 0030  C5 17 33 BE 2E 99 5A 84 4C A7 80 7B A5 CB 97 0D  ..3...Z.L..{.... c2s 0040  17 2A ED 9C 64 C2 33 93 ED B0 9D 8C 56 71 43 B5  .*..d.3.....VqC. c2s 0050  F4 11 F8 F4 91 2B F3 75 01 CA 7B 85 56 06 6D 3F  .....+.u..{.V.m? c2s 0060  D8 F1 D5 98 5B AB 8D CC DE F5 04          ....[...... c2s    After decryption: c2s 0000  00 03 00 00 00 00 09 00 73 75 62 73 70 61 63 65  ........subspace c2s 0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ c2s 0020  00 00 00 00 00 00 00 00 62 61 68 2C 20 6D 64 61  ........bah, mda c2s 0030  6E 20 68 61 63 6B 65 72 73 00 00 00 00 00 00 00  n hackers....... c2s 0040  00 00 00 00 00 00 00 00 A7 CF 24 47 04 2C 01 97  ..........$G.,.. c2s 0050  FB 86 00 BC 01 00 00 2B 02 00 00 A6 97 D0 33 00  .......+......3. c2s 0060  00 00 00 00 00 00 00 00 00 00 00          ........... When client gets to the 00 02, he starts using encryption and sends a login packet. s2c    Before decryption: s2c 0000  00 04 56 65 DF AF                 ..Ve.. s2c    After decryption: s2c 0000  00 04 00 00 00 00                 ...... This was included to demonstrate that the server has connected with the client. --------------------------------------------------- MERVBot build 41 connecting to ASSS with syncookies --------------------------------------------------- Note: Build 40 and earlier did not allow 00 0e before receiving 00 02. Demonstrates support for bots that use efficient clustering to respond to messages. Normally this is a problem, since the cluster is encrypted before the server has received the encryption key or any other packets.  However, some mathematical tricks have made it possible to get around this limitation: the second 00 05 is used now.. c2s    Connection from 127.0.0.1:1825 (proto 1) c2s 0000  00 01 B7 E6 D8 EB 01 00              ........ Same as VIE SubSpace. s2c    SubSpace decryption enabled. s2c 0000  00 0E 06 00 05 C7 B2 5A 1D 06 00 05 0B B3 55 9B  .......Z......U. s2c 0010  06 00 05 49 19 27 14 06 00 02 49 19 27 14     ...I.'....I.'. Same as VIE SubSpace. c2s    Before decryption: c2s 0000  00 0E 33 0B 61 52 06 C7 AA 90 90 8E 82 E1 DF 1D  ..3.aR.......... c2s 0010  CB F8 F8 89 CD 84 BA AD 44 49 98 6B 2B F2 10 0F  ........DI.k+... c2s 0020  46 11 C2 EF 48 2A 7C CA B4 A8 62 AF 8F A3 F7 D6  F...H*|...b..... c2s 0030  94 88 D6 D1 08 1A 67 C7 D4 EC 3B 5C 3F 2B 1E 05  ......g...;\?+.. c2s 0040  34 FF C8 C4 9C 05 11 75 14 2B 79 9F 07 7F EA 24  4......u.+y....$ c2s 0050  95 BA 78 35 F4 01 DC CC C7 A0 1D 92 0F 5D 45 DD  ..x5.........]E. c2s 0060  68 0B 3C 68 0C 48 C0 F0 8D 97 25 66 90 37 02 65  h.<h.H....%f.7.e c2s 0070  05 3C 99 EC D1 66 7F DC 4B E0 05 5B D2 60 92 4D  .<...f..K..[.`.M c2s 0080  76 66 BE E4 5C D1 79 56 C1 A1 07 3F 5F 06 B0 1B  vf..\.yV...?_... c2s 0090  5C 67 82 B3 A4 C2 A6 DB 58 F9 E2 FA E0 E1     \g......X..... c2s 0000  00 0E 0A 00 06 C7 B2 5A 1D 76 60 28 00 0A 00 06  .......Z.v`(.... c2s 0010  0B B3 55 9B 76 60 28 00 0A 00 06 49 19 27 14 76  ..U.v`(....I.'.v c2s 0020  60 28 00 0E 00 05 76 60 28 00 01 00 00 00 00 00  `(....v`(....... c2s 0030  00 00 6B 00 03 00 00 00 00 09 00 43 61 74 69 64  ..k........Catid c2s 0040  2E 50 72 6F 62 65 00 00 00 00 00 00 00 00 00 00  .Probe.......... c2s 0050  00 00 00 00 00 00 00 00 00 00 00 70 72 6F 62 65  ...........probe c2s 0060  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ c2s 0070  00 00 00 00 00 00 00 00 00 00 00 79 92 7D 5C 04  ...........y.}\. c2s 0080  2C 01 00 00 86 00 BC 01 00 00 2B 02 00 00 A6 97  ,.........+..... c2s 0090  D0 33 00 00 00 00 00 00 00 00 00 00 00 00     .3............ The difference between VIE SS and certain bots is immediately obvious. To break it down, 00 0E -- clustering is the difference, the following are encrypted for the server, and he doesn't have the key    0A  00 06  C7 B2 5A 1D  76 60 28 00 -- we would like to see this field, since it contains the syncookie    0A  00 06  0B B3 55 9B  76 60 28 00 -- this time, the second message is the key. i should have details on how this works somewhere in this text file    0A  00 06  49 19 27 14  76 60 28 00 -- this message is ignored More bytes follow... s2c    Before decryption: s2c 0000  00 04 39 0B 67 95                 ..9.g. s2c 0000  00 04 00 00 00 00                 ...... Crazy, it worked. -------------------------------------------------------------- BEGIN BEGIN BEGIN BEGIN ASSS enc_vie.c BEGIN BEGIN BEGIN BEGIN -------------------------------------------------------------- This code was last updated March 17, 2004. /* dist: public */ #include "!@#$%^&*s.h" #include "encrypt.h" #include "md5.h" #define BAD_KEY (-1) /* valid keys must be positive */ /* structs */ typedef struct EncData { int key; char table[520]; } EncData; /* prototypes */ local void ConnInit(struct sockaddr_in *sin, byte *pkt, int len, void *v); local void Init(Player *p, int k); local int Encrypt(Player *p, byte *, int); local int Decrypt(Player *p, byte *, int); local void Void(Player *p); local ClientEncryptData * ClientInit(void); local int ClientEncrypt(ClientEncryptData *ced, byte *, int); local int ClientDecrypt(ClientEncryptData *ced, byte *, int); local void ClientVoid(ClientEncryptData *ced); local void do_init(EncData *ed, int k, int len); local int do_dec(EncData *ed, byte *data, int len); local int do_enc(EncData *ed, byte *data, int len); /* globals */ local int enckey; local pthread_mutex_t mtx; local Inet *net; local Iplayerdata *pd; local Iprng *prng; u32 syncookie_randno[3]; local Iencrypt ienc = { INTERFACE_HEAD_INIT("__unused__", "enc-vie") Encrypt, Decrypt, Void }; local Iclientencrypt iclienc = { INTERFACE_HEAD_INIT("__unused__", "enc-vie-client") ClientInit, ClientEncrypt, ClientDecrypt, ClientVoid }; EXPORT int MM_enc_vie(int action, Imodman *mm, Arena *arena) { if (action == MM_LOAD) {  net = mm->GetInterface(I_NET, ALLARENAS);  pd = mm->GetInterface(I_PLAYERDATA, ALLARENAS);  prng = mm->GetInterface(I_PLAYERDATA, ALLARENAS);  if (!net || !pd || !prng) return MM_FAIL;  enckey = pd->AllocatePlayerData(sizeof(EncData*));  if (enckey == -1) return MM_FAIL;  mm->RegCallback(CB_CONNINIT, ConnInit, ALLARENAS);  pthread_mutex_init(&mtx, NULL);  mm->RegInterface(&ienc, ALLARENAS);  mm->RegInterface(&iclienc, ALLARENAS);  prng->GoodFillBuffer(syncookie_randno, sizeof(syncookie_randno));  return MM_OK; } else if (action == MM_UNLOAD) {  if (mm->UnregInterface(&ienc, ALLARENAS))  return MM_FAIL;  if (mm->UnregInterface(&iclienc, ALLARENAS))  return MM_FAIL;  mm->UnregCallback(CB_CONNINIT, ConnInit, ALLARENAS);  pd->FreePlayerData(enckey);  mm->ReleaseInterface(net);  mm->ReleaseInterface(pd);  mm->ReleaseInterface(prng);  pthread_mutex_destroy(&mtx);  return MM_OK; } return MM_FAIL; } /* http://burtleburtle.net/bob/c/lookup2.c */ #define mix(a,b,c) \ { \  a -= b; a -= c; a ^= (c>>13); \  b -= c; b -= a; b ^= (a<<8); \  c -= a; c -= b; c ^= (b>>13); \  a -= b; a -= c; a ^= (c>>12);  \  b -= c; b -= a; b ^= (a<<16); \  c -= a; c -= b; c ^= (b>>5); \  a -= b; a -= c; a ^= (c>>3);  \  b -= c; b -= a; b ^= (a<<10); \  c -= a; c -= b; c ^= (b>>15); \ } /* H(IP, port, randno), "synchronization packet cookie" */ local u32 generate_syncookie(struct sockaddr_in *sin) { u32 randno, ip = sin->sin_addr.S_un.S_addr; u32 port = sin->sin_port | (sin->sin_port << 16); randno = syncookie_randno[0];  mix(ip, port, randno); randno |= syncookie_randno[1];  mix(ip, port, randno); randno += syncookie_randno[2];  mix(ip, port, randno); return (ip & port) + randno; } void ConnInit(struct sockaddr_in *sin, byte *pkt, int len, void *v) { if (len == 8 && pkt[0] == 0 && pkt[1] == 1 && pkt[6] == 1 && pkt[7] == 0) { /* handle the initial connection request */  u32 k = -*(int*)(pkt+2); /* session key */  byte resp[30] = {0, 14,  6, 0, 5, 0,0,0,0,     6, 0, 5, 0,0,0,0,     6, 0, 5, 0,0,0,0,     6, 0, 2, 0,0,0,0};  struct EncData ed;  if (k <= 0) return; /* ignore invalid keys */  do_init(&ed, k, 9);  *(u32*)(resp+5) = generate_syncookie(sin);  *(u32*)(resp+12) = (k ^ *(u32*)(ed.table+14)) | 0x80000000;  *(u32*)(resp+19) = k;  *(u32*)(resp+26) = k;  net->ReallyRawSend(sin, resp, 30, v); } else if (len >= 6 && pkt[0] == 0 && pkt[1] == 6) { /* handle unencrypted serial response mode */  u32 sc = *(u32*)(pkt+2);  Player *p;  if (sc == generate_syncookie(sin))  {  ienc.head.refcount++;  p = net->NewConnection(T_VIE, sin, &ienc, v);  if (!p)  {   byte out[2] = { 0x00, 0x07 };   net->ReallyRawSend(sin, out, 2, v);  }  /* we now await 2nd 00 06 to know what the key was */  } } else if (len >= 24 && pkt[0] == 0 && pkt[1] == 14) { /* handle encrypted cluster response mode */  struct EncData ed;  Player *p;  /* recover the key */  u32 sc, key = (*(u32*)(pkt+16) ^ *(u32*)(pkt+12));  key &= 0x7fffffff; /* must be positive */  /* recover the syncookie */  do_init(&ed, key, 4);  sc = *(u32*)(ed.table+3) ^ *(u32*)(pkt+5)  ^ ((*(u32*)(pkt+2) << 8) | (key >> 24));  if (sc == generate_syncookie(sin))  {  ienc.head.refcount++;  p = net->NewConnection(T_VIE, sin, &ienc, v);  if (!p)  {   byte out[2] = { 0x00, 0x07 };   net->ReallyRawSend(sin, out, 2, v); return;  }  Init(p, key);  } } else if (len >= 6 && pkt[0] == 0 && pkt[1] == 3) { /* a critical packet was lost before connecting */  byte out[2] = { 0x00, 0x07 };  net->ReallyRawSend(sin, out, 2, v); } } local void do_init(EncData *ed, int k, int len) { int t, loop; u16 *mytable; ed->key = k; if (k == 0) return; mytable = (u16*)(ed->table); for (loop = 0; loop < len; loop++) {  t = (long)(((long long)k * 0x834E0B5F) >> 48);  t = t + (t >> 31);  k = ((k % 0x1F31D) * 16807) - (t * 2836) + 123;  if (!k || (k & 0x80000000)) k += 0x7FFFFFFF;  mytable[loop] = (u16)k; } } void Init(Player *p, int k) { EncData *ed, **p_ed = PPDATA(p, enckey); pthread_mutex_lock(&mtx); if (!(ed = *p_ed)) ed = *p_ed = amalloc(sizeof(*ed)); pthread_mutex_unlock(&mtx); do_init(ed, k, 260); } int do_enc(EncData *ed, byte *data, int len) { int work = ed->key, *mytable = (int*)ed->table; int loop, until, *mydata; if (work == 0 || mytable == NULL) return len; if (data[0] == 0) {  mydata = (int*)(data + 2);  until = (len-2)/4 + 1; } else {  mydata = (int*)(data + 1);  until = (len-1)/4 + 1; } for (loop = 0; loop < until; loop++) {  work = mydata[loop] ^ (mytable[loop] ^ work);  mydata[loop] = work; } return len; } int Encrypt(Player *p, byte *data, int len) { EncData *ed, **p_ed = PPDATA(p, enckey); pthread_mutex_lock(&mtx); ed = *p_ed; pthread_mutex_unlock(&mtx); return ed ? do_enc(ed, data, len) : len; } int do_dec(EncData *ed, byte *data, int len) { int work = ed->key, *mytable = (int*)ed->table; int *mydata, loop, until; if (work == 0 || mytable == NULL) return len; if (data[0] == 0) {  mydata = (int*)(data + 2);  until = (len-2)/4 + 1; } else {  mydata = (int*)(data + 1);  until = (len-1)/4 + 1; } for (loop = 0; loop < until; loop++) {  int tmp = mydata[loop];  mydata[loop] = mytable[loop] ^ work ^ tmp;  work = tmp; } return len; } int Decrypt(Player *p, byte *d, int len) { EncData *ed, **p_ed = PPDATA(p, enckey); pthread_mutex_lock(&mtx); ed = *p_ed; pthread_mutex_unlock(&mtx); /* syncookie: catch 2nd 00 06 containing enc.key */ if (!ed && len == 10 && d[0] == 0 && d[1] == 6) {  u32 k = *(u32*)(d+2);  if (!(k & 0x80000000)) /* first one is negative */  Init(p, k);  return len; } return ed ? do_dec(ed, d, len) : len; } void Void(Player *p) { EncData *ed, **p_ed = PPDATA(p, enckey); pthread_mutex_lock(&mtx); ed = *p_ed; afree(ed); *p_ed = NULL; pthread_mutex_unlock(&mtx); } ClientEncryptData * ClientInit(void) { EncData *ed = amalloc(sizeof(*ed)); ed->key = BAD_KEY; return (ClientEncryptData*)ed; } int ClientEncrypt(ClientEncryptData *ced, byte *d, int n) { EncData *ed = (EncData*)ced; if (d[1] == 0x01 && d[0] == 0x00) {  /* sending key init */  /* temporarily overload the key field to be what _we_ sent */  ed->key = *(int*)(d+2);  return n; } else if (ed->key != BAD_KEY)  return do_enc(ed, d, n); else  return n; } int ClientDecrypt(ClientEncryptData *ced, byte *d, int n) { EncData *ed = (EncData*)ced; if (d[1] == 0x02 && d[0] == 0x00) {  /* got key response */  int gotkey = *(int*)(d+2);  if (gotkey == ed->key) /* signal for no encryption */  ed->key = BAD_KEY;  else  do_init(ed, gotkey, 260);  return n; } else if (ed->key != BAD_KEY)  return do_dec(ed, d, n); else  return n; } void ClientVoid(ClientEncryptData *ced) { afree(ced); } -------------------------------------------------------------- END END END END END END ASSS enc_vie.c END END END END END END -------------------------------------------------------------- -------------------------------------------------------------- BEGIN BEGIN BEGIN BEGIN patch to net.c BEGIN BEGIN BEGIN BEGIN -------------------------------------------------------------- + Allows encryption modules to decide for themselves which  packets to listen for; needed to use my VIE syncookies. + Removes that awful "recvd data before connection established" warning  that someone could use to flood the server logs and maybe DoS it.  This kind of warning is fine, however, after the source of the  packets has been authenticated by the anti-spoof protection. --- net.c 3 Feb 2004 07:21:29 -0000 1.107 +++ net.c 18 Mar 2004 05:04:27 -0000 @@ -932,19 +930,9 @@  if (p == NULL)  { -  /* this might be a new connection. make sure it's really -  * a connection init packet */ -  if (IS_CONNINIT(buf)) -  DO_CBS(CB_CONNINIT, ALLARENAS, ConnectionInitFunc, -   (&sin, buf->d.raw, len, ld)); -  else if (len > 1) -  lm->Log(L_DRIVEL, "<net> recvd data (%02x %02x; %d bytes) " -   "before connection established", -   buf->d.raw[0], buf->d.raw[1], len); -  else -  lm->Log(L_DRIVEL, "<net> recvd data (%02x; %d byte) " -   "before connection established", -   buf->d.raw[0], len); +  /* this might be a new connection */ +  DO_CBS(CB_CONNINIT, ALLARENAS, ConnectionInitFunc, +   (&sin, buf->d.raw, len, ld));  goto freebuf;  } -------------------------------------------------------------- END END END END END END patch to net.c END END END END END END -------------------------------------------------------------- Authors: catid(cat02e@fsu.edu) ICQ#18736684 AIM:MrCatid irc.freenode.net #sheepcloning Catid
  12. Check it here: MERVBot website link
  13. i could share with you the algorithm i'm using for tile-based collisions in my RPG
  14. cool beans i like that you got the radar to work; my client never got to that point, though i was not working on it for that long ;-) if you need some help with the non-trivial particulars of creating a client, such as game physics, give me a shout: cat02e@fsu.edu
  15. http//63.247.85.58/~gandalf4/catid 1st says this will work for now
×
×
  • Create New...