smtddr's notes

[Things I find interesting]

Deeper into the authtoken!

The more I test, the weaker this protection gets. :-)

In my last post, I discussed reversing the logic of userid & gsbrcd

I’ve been able to determine that authtokens never expire, so the challenge & authtoken from my last post can still be used to gain write access to my online stats. This is important, because now I know I don’t actually need to access nas.nintendowifi.net for a new challenge & authtoken.

Also, this tells me that on GameSpy’s servers that there must an auth function f(x,y,z) = profileID, where x = response md5, y = challenge and z = authtoken with no regard to any kind of datestamp.

Note that what I just said, is probably false! ^_^ I find it hard to believe someone would actually use the md5 hash itself in any kind of calculation. So, here’s what probably happens:

  1. GameSpy decodes authtoken
  2. Inside authtoken is the challenge string
  3. GameSpy takes that challenge string and does the same f(challenge,sesskey) the Wii does to see if the md5 response hash it calculates is equal to the one the Wii gave it.

Please note that it is impossible for the md5 hash to be inside the authtoken. Why? Because the response hash is calculated using the sesskey that was give just before the authp command. I’ve just proved that an old challenge & authtoken pair still work(because I wrote code that writes to my stats without any communication to naswii.nintendowifi.net), so if there was an old hash in there being used it wouldn’t match the new one calcuated at each run of my script.

The only mathematical way all this can make sense, is for the authtoken to be decoded and contain the challenge. There’s no other way for the stats-server to know what the challenge is in order to validate the response hash. At least, that’s what I’m seeing at the moment.

So, GameSpy must be able to decrypt the authtoken all by itself. Note that naswii.nintendowifi.com must have something like create_authtoken(userid,gsbrcd,challenge,authtoken) where challenge is the random 8 char challenge it placed in the authtoken. Thus, what I conclude must be the pseudo’ish-code on GameSpy’s side is:

char buf[12];
int profileid;
char challenge[8];
current_session = Whatever_framework_supplying_current_session_state;

secret_decrypt(authtoken,buf);


profileid = first_four_bytes_of_buf;
challenge = the_last_eight_bytes_of_buf;

server_expected_resp = do_sharedsecret_challengeresponse_func(current_session->sesskey,challenge);

if(server_expected_resp == current_session->Wii_authp_resp_field)
grant_wii_write_access();
else
deny_wii_write_access_();

So yeah, maybe I should focus on reversing this authtoken. That’s all for now - see you all later.