Daytona USA Progress

Online games, how to get online, and anything involving Dreamcast online can be discussed here.

Moderator: pcwzrd13

User avatar
Scrivani
Vagabond
Posts: 724
Contact:

Re: Daytona USA Progress

Post#111 » Wed Dec 21, 2022 7:01 pm

Very, very good! And thanks for sharing all steps
Happy if may help:
- BBA Mode for DreamPi: https://bit.ly/3JEIuhs
- VPN Port Fowarding: https://bit.ly/3Bgw4bu
- DC Now Data Analysis: https://bit.ly/42coxXw
- DC KARA NOT DEAD AT ALL- VCD Method: https://bit.ly/3P6VePw
- Know part of BR Community: https://bit.ly/3iLXS12

User avatar
Scrivani
Vagabond
Posts: 724
Contact:

Re: Daytona USA Progress

Post#112 » Wed Dec 21, 2022 7:03 pm

It seems this internal picoppp port opening is just required to type of access you are doing, like this cross access in the same network, flycast pico ppp sub network actualy
Happy if may help:
- BBA Mode for DreamPi: https://bit.ly/3JEIuhs
- VPN Port Fowarding: https://bit.ly/3Bgw4bu
- DC Now Data Analysis: https://bit.ly/42coxXw
- DC KARA NOT DEAD AT ALL- VCD Method: https://bit.ly/3P6VePw
- Know part of BR Community: https://bit.ly/3iLXS12

User avatar
Scrivani
Vagabond
Posts: 724
Contact:

Re: Daytona USA Progress

Post#113 » Wed Dec 21, 2022 7:06 pm

Seems that will not be a problem in real hardware, if the server host do his server port opening and if dc client also open those new daytona usa ports
Happy if may help:
- BBA Mode for DreamPi: https://bit.ly/3JEIuhs
- VPN Port Fowarding: https://bit.ly/3Bgw4bu
- DC Now Data Analysis: https://bit.ly/42coxXw
- DC KARA NOT DEAD AT ALL- VCD Method: https://bit.ly/3P6VePw
- Know part of BR Community: https://bit.ly/3iLXS12

ioncannon
Anarki
Posts: 90

Re: Daytona USA Progress

Post#114 » Wed Dec 21, 2022 7:26 pm

My thoughts as well. I am having trouble with Flycast though..... the build works fine on the other computer but on my main machine it crashes as soon as data is received. Wtf.....

The best would be getting both the debugger working and port unblocked so that I can trace how the data is being parsed. Then it's just a matter of doing the same analysis as was done on the Lobby Engine.

ioncannon
Anarki
Posts: 90

Re: Daytona USA Progress

Post#115 » Fri Dec 23, 2022 4:19 pm

Found another "system" problem that was causing issues with the connection. The engine uses the client's ip as a key throughout the system. Since Flycast's internal PPP server was setting all clients to 192.168.167.2, the game would see a duplicate key and abort the connection.

Modded one to be *.*.*.3 and one to be *.*.*.2 and we got even further; loooootta packets being sent but it seems to give up waiting on something.

Still no idea where the TCP "game server" comes into play. Wonder if it is only used for a small subset of unused features and Daytona is fully P2P.

ioncannon
Anarki
Posts: 90

Re: Daytona USA Progress

Post#116 » Mon Dec 26, 2022 4:35 pm

Still no further but I do have a hypothesis where the code is sitting now. It seems everything is setup correctly and I have figured out how the received packets are parsed and where the UDP opcode switches are.

The packet that gets spammed before the game times out is what gets sent when `ne_SendAsyncData` is called by the main game linking the library. Daytona goes through 4 loading steps before it can start the game (waitOthers, waitStart, syncStep1, syncStep2). I can see that it sends 2 bytes during the first state, and then 5 bytes during the second. The peer never replies which it should with the same amount of data.

Wish my Flycast debugger didn't start randomly crashing once I unblocked those ports.

Edit: So it looks like the gameserver is totally optional, which I assume was used for MMOs and such. Found the flag that each TCP msg was checking got set by the initial configuration Daytona sent in the NE_Engine init function. It was set to 0, so no TCP traffic will happen. Only UDP P2P traffic. At least I don't have to write a game server (until we look at other NE games) phew.

That then isolates my research to just the UDP side.

Edit 2: Not just optional; it's either-or. Either the Net Engine is setup to do P2P traffic or it's setup to do Client-Server. Very versatile and interesting design.


Ignore, I'm dumb.

ioncannon
Anarki
Posts: 90

Re: Daytona USA Progress

Post#117 » Tue Jan 03, 2023 10:41 am

Posting nother update:

Haven't got further with getting Daytona online. Tested the server/clients with Xiden and Eaudunord and they had experienced the same issue where the non-host just doesn't responds to the host's sent request data. To further test I need to get Flycast working with the debugger + open UDP ports but my attempts to compile it lead to crashes when the first packet is received. Unsure why it worked for a it on my wife's computer. Only thing else I can do is guesstimate why the client doesn't respond (I know where the code is, but not what the values might be in memory).

-------------

Frustrated by hitting the wall I looked at something else. On some positive news; I figured out most of the init function for the Dricas SSL code. Most of it is a memory scanner. The layout of the cert is

0x00 - Offset to actual DER encoded cert
0x04 - Encoded SHA1 bit size.
0x08 - 0x100 bytes containing half of the encoded SHA1 of the DER cert (this is read in 2 0x80 chunks).
0x108 - 0x40 bytes containing the actual SHA1 (encoded).
0x148 - The DER file.

It seems the initial header is only used to decode the SHA1 of the DER file. Once this hash is decoded, it then does another SHA1 on the DER file and compares the two hashes. If correct it returns a success. This was likely to stop people from tampering with the client cert.

That means for getting Dricas online you only need what is after 0x14C. Sadly I cannot seem to get it to actually generate into some kind of cert as it seems to not being following any specific format. Running it in a ASN.1 reader returns this data:

https://pastebin.com/1h4XYz0t

I am talking to a developer who was able to trick the PSO encryption system (a later one, not the DC one; which used SSL to encrypt all it's traffic) into accepting the cert and securing the traffic across the client/server. If I can get this working again, I already know all the valid request/response information and can easily get Dricas online again. This would mean retail games would no longer require patching (as IP's can be rerouted using IP tables and URLs can use DNS).

ncman071
Sunday Shootout
Posts: 678

Re: Daytona USA Progress

Post#118 » Tue Jan 03, 2023 5:05 pm

appreciate all your efforts friend. sounds like you are going above and beyond and it is greatly appreciated....much respect

ioncannon
Anarki
Posts: 90

Re: Daytona USA Progress

Post#119 » Sun Jan 08, 2023 6:43 pm

Figured out the skeleton view of how the SSL library is laid out and can at least following the parsing/sending of SSL packets. Here is the main connect state machine:

Code: Select all

  if (sslObj->randomBytesFromServer[4FC + -0x4c] == 3) {
    step = sslObj->state;
    if (step == 1) {
      step = SSL_sendClientHello(sslObj);
      if (step != 0) {
        return step;
      }
      sslObj->state = 2;
      goto LAB_8c14ec60;
    }
    if (step == 2) {
      step = SSL_readServerHello(sslObj);
      if (step == 0) {
        step = 3;
        goto LAB_8c14ed92;
      }
      if (step != -8) {
        return step;
      }
      sslObj->randomBytesFromServer[4FC + -0x4c] = 2;
      goto LAB_8c14ec60;
    }
    if (step == 3) {
      step = SSL_readCertificate(sslObj);
      if (step != 0) {
        return step;
      }
      step = 4;
    }
    else if (step == 6) {
      step = SSL_readServerKeyExchange(sslObj);
      if (step != 0) {
        return step;
      }
      step = 5;
    }
    else if ((step == 4) || (step == 5)) {
      step = SSL_readServerHelloDone(sslObj);
      if (step == 0) {
        step = 7;
      }
      else {
        if (step != -0x32) {
          return step;
        }
        step = 6;
      }
    }
    else if (step == 7) {
      step = SSL_sendClientCipherKeyExchange(sslObj);
      if (step != 0) {
        return step;
      }
      step = 8;
    }
    else {
      if (step != 8) {
        if (step == 9) {
          step = SSL_readServerFinished(sslObj);
          if (step != 0) {
            return step;
          }
          goto LAB_8c14eda6;
        }
        goto joined_r0x8c14ec98;
      }
      step = SSL_sendClientFinished(sslObj);
      if (step != 0) {
        return step;
      }
      step = 9;
    }
  }


Currently stuck on step SSL_readCertificate. I was able to craft a certificate that the library could read; had to be SSLv3, PrintableStrings only (not UTF8), and the only supported hashes were NULL, MD2, or MD5.

However I am running into two functions that probably do the final verification. A decode function (possibly RSA?) that is used in that above header info I posted. This is returning a non-zero error code that aborts the connection. Only one other function is called after this that I *think* compares two hashes.

Still gotta read up a bit more on how certs/SSL work with the hash and RSA keys.

ioncannon
Anarki
Posts: 90

Re: Daytona USA Progress

Post#120 » Tue Jan 10, 2023 5:27 pm

More credence to the rsa idea... the rsa decode function calls a function that reverses bits. So something like 00 01 02 03 04 will be come 04 03 02 01 00. I assume this is due to storage vs CPU endian reasons. I just realized why the header looks weird and has such huge gaps. Normally you'd see data and possible 0-padding at the end like so: 02050203050000000000000000000. Well if the file was stored reversed; it would make sense why you have a slew of zeros randomly placed at the start. I think ASN1 (for certs) also seems to be written in big endien anyway.

Even more so: The two chunks are 0x80 bytes in size; or 1024 bits.... the size of an RSA key at that time (think we use 2048 bit keys now). However it's half the size in this case.... so 512 bits.

That would also make the second chunk just be the number 3. Possibly an exponent? Keys are a combination of a modulus and exponent, two prime numbers. 3 is prime, and I've seen the exponent many times be the smaller of the two parts. So the last 0x40 bytes might be the data being decrypted?

So our header actually would look like:

0x000 - Offset to actual DER encoded cert
0x004 - Encoded data size in bits
0x008 - 0x80 RSA Key modulus.
0x088 - 0x80 RSA Key exponent.
0x108 - 0x40 bytes containing the encrypted data (hash of the cert). Theoretically can be any size.
0x148 - The certificate in ASN1/DER format.

It's a cert + signature on top basically. Here is the cert from Sakura Taisen Online (same used in all games) for the Dricas auth. Highlighted is what I *think* is the modulus. The lone "3" is what I think is the exponent.

Untitled.png


Again I still need to figure out the RSA decrypt function to map out it's params and confirm this is indeed what it is doing. I also am not sure if this will help us, as I am kinda half-understanding how certs and the signature work. Still, the verification function and the pinnedCert verification function ARE doing the same thing, so if we feed it the same inputs and they match.... it should pass the one thing stopping us from getting to the chiper exchange phase. After that we are golden.

Edit: Think I all but confirmed it's RSA. This looks like the main modular exponentiation func. I was also right that the "3" was an exponent. The difference is this lib uses really big (1024 bit in size) numbers so uses a data structure + funcs to handle it which I call BigNum.

Code: Select all

void rsaModExpAlg(big_num_t *dataOut,big_num_t *dataIn,big_num_t *exponent,big_num_t *modulus)
{
  int isExpNot0;
  uint nextByte;
  int i;
  int j;
  uint 80000000h;
  int e_size;
  uint *e_buffPos;
  undefined4 bigNum1;
  undefined auStack44 [4];
  undefined4 bigNum2;
  undefined4 local_24;
  undefined *bigNumMod;
  undefined *bigNumMulti;
 
  isExpNot0 = (*(code *)PTR_checkIfEValid_8c166094)(exponent);
  if (isExpNot0 == 0) {
    (*(code *)PTR_setBigNum_8c166098)(dataOut,1);
  }
  else {
    (*(code *)PTR_initBigNum_8c16609c)(&bigNum2);
    (*(code *)PTR_initBigNum_8c16609c)(&bigNum1);
    e_size = exponent->size;
    e_buffPos = exponent->value + e_size;
    (*(code *)PTR_setBigNum_8c166098)(&bigNum2,1);
    bigNumMod = PTR_modBigNum_8c1660a4;
    bigNumMulti = PTR_multiBigNum_8c1660a0;
    while (e_buffPos = e_buffPos + -1, i = e_size + -1, e_size != 0) {
      j = 0x20;
      nextByte = *e_buffPos;
      80000000h = DAT_8c1660a8;
      do {
        (*(code *)bigNumMulti)(bigNum1,auStack44,bigNum2,local_24,bigNum2,local_24);
        (*(code *)bigNumMod)(&bigNum2,&bigNum1,modulus);
        if ((nextByte & 80000000h) != 0) {
          (*(code *)bigNumMulti)(bigNum1,auStack44,bigNum2,local_24,dataIn->value,dataIn->size);
          (*(code *)bigNumMod)(&bigNum2,&bigNum1,modulus);
        }
        80000000h = 80000000h >> 1;
        j = j + -1;
        e_size = i;
      } while (j != 0);
    }
    (*(code *)PTR_copyBigNum_8c1660ac)(dataOut,&bigNum2);
    (*(code *)PTR_releaseBigNum_8c1660b0)(&bigNum2);
    (*(code *)PTR_releaseBigNum_8c1660b0)(&bigNum1);
  }
  return;
}


Compare the middle to something like:

Code: Select all

// The Modular Exponentiation Algorithm
int MEA(int p, int e, int n){
 
  int r2 = 1;
  int r1 = 0;
  int Q = 0;
  int R = 0;
 
  while( e != 0 ){
     R = (e % 2);
     Q = ((e - R) / 2);
 
     r1 = ((p * p) % n);
 
       if(R == 1){
          r2 = ((r2 * p) % n);
       }
     p = r1;
     e = Q;
  }
return r2;
}

  • Similar Topics
    Replies
    Views
    Last post

Return to “Online”

Who is online

Users browsing this forum: No registered users