smtddr's notes

[Things I find interesting]

Tatsunoko-vs-Capcom - LeaderBoard hack part.2 - More on Tatsunoko-vs-Capcom network traffic.

So, let’s discuss the Tatsunoko-vs-Capcom(TvC) traffic. Particularly a Ranking match’s scoring conversation:

Below is the traffic of winning a match:

GET /tatvscapwii/web/client/put2.asp?pid=249190728 HTTP/1.1
Host: gamestats2.gs.nintendowifi.net
User-Agent: GameSpyHTTP/1.0
Connection: close

HTTP/1.1 200 OK
Date: Sat, 07 May 2011 13:08:35 GMT
Server: Microsoft-IIS/6.0
p3p: CP='NOI ADMa OUR STP'
X-Powered-By: ASP.NET
cluster-server: gstprdweb12.las1.colo.ignops.com
X-Powered-By: ASP.NET
Content-Length: 32
Content-Type: text/html
Set-Cookie: ASPSESSIONIDCSBDTSCD=KOEKABKCPAPGEFONCEHADKEA; path=/
Cache-control: private

Eisq8fZ2s33Wriz3iku8rE9Tz1WgWh4x

GET /tatvscapwii/web/client/put2.asp?pid=249190728&hash=a619fbb3a5fe6b680ae70a747dc2c747e256502d&data=aFtrRUhZ2g5cAAAA_wAAAAAAAABgHwAATAAAAAAACCsAAAAAAAADPwAADI4AAB9gAAAAAP__Izn__x4OAAD__wAAAAEAAAATAFMATQBUAEAARABEAFIAIAAgAAAAAAAAAAAAAAAAAAA= HTTP/1.1
Host: gamestats2.gs.nintendowifi.net
User-Agent: GameSpyHTTP/1.0
Connection: close

HTTP/1.1 200 OK
Date: Sat, 07 May 2011 13:08:35 GMT
Server: Microsoft-IIS/6.0
p3p: CP='NOI ADMa OUR STP'
X-Powered-By: ASP.NET
cluster-server: gstprdweb13.las1.colo.ignops.com
Content-Length: 44
Content-Type: text/html
Set-Cookie: ASPSESSIONIDQQCADDRC=FNGBCLJCKMKJGCDPPGCPGNJG; path=/
Cache-control: private

doneb7e684e8313b5729fd1c70a3fc19e425700449f6

GET /tatvscapwii/web/client/put2.asp?pid=249190728 HTTP/1.1
Host: gamestats2.gs.nintendowifi.net
User-Agent: GameSpyHTTP/1.0
Connection: close

HTTP/1.1 200 OK
Date: Sat, 07 May 2011 13:08:35 GMT
Server: Microsoft-IIS/6.0
p3p: CP='NOI ADMa OUR STP'
X-Powered-By: ASP.NET
cluster-server: gstprdweb11.las1.colo.ignops.com
X-Powered-By: ASP.NET
Content-Length: 32
Content-Type: text/html
Set-Cookie: ASPSESSIONIDSATQCABT=LMKHNBKCKKHKMLCLAFMBBCFN; path=/
Cache-control: private

fJmleCovupF2RaTTdbUkdUxSnlzRaqcQ

GET /tatvscapwii/web/client/put2.asp?pid=249190728&hash=0d776df35c1cc4a4e52445255428d3a4a1d12e09&data=aFtoZUhZ2g5cAAAA_wAAAAIAAABSAAAATAAAAAAAABsAAAAAAAAACAAAACQAAABSAAAAAP__Izn__x4OAAD__wAAAAEAAAATAFMATQBUAEAARABEAFIAIAAgAAAAAAAAAAAAAAAAAAA= HTTP/1.1
Host: gamestats2.gs.nintendowifi.net
User-Agent: GameSpyHTTP/1.0
Connection: close

HTTP/1.1 200 OK
Date: Sat, 07 May 2011 13:08:35 GMT
Server: Microsoft-IIS/6.0
p3p: CP='NOI ADMa OUR STP'
X-Powered-By: ASP.NET
cluster-server: gstprdweb15.las1.colo.ignops.com
Content-Length: 44
Content-Type: text/html
Set-Cookie: ASPSESSIONIDSSBBQQBD=CIIPBAKCNLGHPELOCKLHBAGH; path=/
Cache-control: private

doneb7e684e8313b5729fd1c70a3fc19e425700449f6

GET /tatvscapwii/web/client/put2.asp?pid=249190728 HTTP/1.1
Host: gamestats2.gs.nintendowifi.net
User-Agent: GameSpyHTTP/1.0
Connection: close

HTTP/1.1 200 OK
Date: Sat, 07 May 2011 13:08:36 GMT
Server: Microsoft-IIS/6.0
p3p: CP='NOI ADMa OUR STP'
X-Powered-By: ASP.NET
cluster-server: gstprdweb12.las1.colo.ignops.com
X-Powered-By: ASP.NET
Content-Length: 32
Content-Type: text/html
Set-Cookie: ASPSESSIONIDCSBDTSCD=HAFKABKCDOEDAGJHINNOCGHE; path=/
Cache-control: private

MOQ13Tc1lPwq2HkKvTe15iwTSvKQSTdw

GET /tatvscapwii/web/client/put2.asp?pid=249190728&hash=179ddea6eb183a252e3737c43aba5194b3537d90&data=aFtoYUhZ2g5cAAAA_wAAAAYAAABSAAAATAAAAAAAABsAAAAAAAAACAAAACQAAABSAAAAAP__Izn__x4OAAD__wAAAAEAAAATAFMATQBUAEAARABEAFIAIAAgAAAAAAAAAAAAAAAAAAA= HTTP/1.1
Host: gamestats2.gs.nintendowifi.net
User-Agent: GameSpyHTTP/1.0
Connection: close

HTTP/1.1 200 OK
Date: Sat, 07 May 2011 13:08:36 GMT
Server: Microsoft-IIS/6.0
p3p: CP='NOI ADMa OUR STP'
X-Powered-By: ASP.NET
cluster-server: gstprdweb15.las1.colo.ignops.com
Content-Length: 44
Content-Type: text/html
Set-Cookie: ASPSESSIONIDSSBBQQBD=MIIPBAKCBEICEFDBAFOCKIHD; path=/
Cache-control: private

doneb7e684e8313b5729fd1c70a3fc19e425700449f6

So, first it sends the PID(unique to each online player) to get a string, then sends a hash & a data field. If you read http://projectpokemon.org/wiki/GTS_protocol, you’ll see the work hackers have done for Pokemon. It has helped me understand what I’m looking at with TvC. So now I know that the first string Nintendo gives me is a token, the hash the game sends back is sha1(salt + token), and the data is a base64_urlsafe_encoding of game info. Probably scoring and the like. One very important thing, the most important part in fact, that the PokemonGTS people have is the salt. I don’t know what the salt is for TvC. If I did, things would get very interesting and that would probably be the end of TvC ranking matches because of hackers spoofing scores. I’ve since written a relay-server in python to intercept these communications, allowing me to make settle changes. So I can say a few things:

The data string has nothing to do with the hash, in that I can reuse an old data string with newer hashes over & over. No matter what the hash & data string is, the reply is always the same. doneb7e684e8313b5729fd1c70a3fc19e425700449f6. If this is changed, the WII replies with RST-packet and goes offline. No doubt, this is unique to each PID If I alter the data arbitrarily, Nintendo replies validation-error. If I alter the hash, Nintendo replies invalid hash If I wait too long to send the hash(10 seconds or so), Nintendo replies token expired If I repeat the pid+hash+data send, Nintendo accepts the repeats over & over again. Even if I change the data string for each request. So, the hash can be reused until it expires. If I send a pid bigger than 10 digits, Nintendo replies with:

unhandled overflow exception: 
Microsoft JScript runtime error ‘800a0006′
Overflow /tatvscapwii/web/session.inc, line 41

If I send a pid that’s not all digits e.g. 2938F83, Nintendo replies with :

unhandled exception: 
Type mismatch /tatvscapwii/web/session.inc, line 41

If I replace the token from the server with a ” “(white space), the game sends RST-packet and goes offline. And… that’s about it! Still collecting more info about this!

See you next time -^_^-