Wednesday, December 12, 2012

Hmm it's been far too long since I posted something here...


GuildWars 2


So a while ago I got interested in seeing how game security was, more specifically how games these days protect people from snooping the traffic. But I was also interested in what counter measures are present to prevent or detect tampering, since bots/cheats are a big issue these days and can potentially ruin a game.

Since I was planning on playing Guild Wars 2 for a bit, I figured it would be a nice target to  investigate. The investigation was done on the beta client somewhere in march so my memory is already a bit fuzzy on some details. I've waited this long to post about it, since I didn't want to help bot makers, but I doubt it still matters today. A quick search on google will show there's already plenty of hacks out there, so anything posted here won't make much of a difference.


A First look


First thing I noticed was how much information was present in the binary. My initial thought was that this was due to it being a beta client, hence probably contained more debug info. Unfortunately a quick look at a recent binary shows this not to be the case.. there's still lots of useful information present.

For example, even just issuing strings gw2.exe is quite revealing:

!((m_view == VIEW_GAMEPLAY) && !CharClientContext()->GetControlledCharacter())
!iterator.IsValid()
DNot supported in this configuration!
..\..\..\Game\View\Headless\VhdContext.cpp
N@onRendered
..\..\..\Game\View\Default\VdfRender.cpp
metric < arrsize(m_metrics)
..\..\..\Game\View\Default\VdfLoad.cpp
m_state == STATE_LOAD_MANIFEST
m_state == STATE_MODELS_STREAM
m_mapId == mapId
m_state == STATE_LOAD_CONTENT || m_state == STATE_LOAD_MANIFEST || m_state == STATE_SERVER_WAIT
mapContentLoaded
mapDef != NULL
m_state == STATE_LOAD_CONTENT
m_state == STATE_SERVER_WAIT
m_state == STATE_MAP_STREAM

Even today's binary (16247) still shows all this detail. Anyone who has ever reversed code will understand how valuable this is during the reversing process.

The game was written in C++ with RTTI enabled, which is also a great source for information. (See Igor Skochinsky's post Recon 2012: Compiler Internals)

Anyway I'll explain the network protocols used by GuildWars 2 on here, which might help some people that are interested in writing a gw2 server emulator. I'll probably spread this over a couple of posts.

While reversing the client, I also discovered a security issue, which to this day is still present. Therefor I've notified ArenaNet today. I'll refrain from explaining the issue for some time, or until ArenaNet resolves the issue. Whichever comes first.

On to the nitty gritty now.


The connections


GuildWars 2 uses 2 ports for network communication:

- port 6600 : portal connection
- port 6112 : game server connection

Actually, ports 80 and 443 are also required, but those aren't involved in actual gameplay and it's pretty known which protocol is used on those :-)


Portal Connection


The portal connection starts as a clear text protocol, but immediately issues an AUTH TLS command, which initiates a secured connection. The actual data protocol used on this port is XML based. The game uses RapidXML to do the XML parsing.

Example XML piece:
<Reply>
<UserId>99999999-9999-9999-9999-999999999999</UserId>
<UserCenter>1</UserCenter>
<HasPhone>0</HasPhone>
</Reply>

The encryption used on this connection is AES in CBC mode. With a separate session key for incoming and outgoing traffic. An HMAC digest hash is also used, again one for incoming and one for outgoing communications.

The key exchange between the client and server is done via SRP (RFC5054, Secure Remote Password). Since SRP uses Diffie-Hellman, it won't prevent proxying this connection, which would allow people interested in writing cheats to get access to the communication on an external machine, without having to tamper with the actual client binary.

However this doesn't matter much as the game binary I investigated contained no security checks.

The game goes through some key expansion functions to generate the AES & HMAC keys.

NOTE: this is not vulnerable to MITM attacks, as one needs to know the password to be able to proxy the connection.

Game server connection


The connection to the game servers is over an RC4 encrypted connection. Again Diffie-Hellman is used as a key exchange, but in this case the server side packet is precomputed and stored in the game client, ie. the result of ga mod p has been precalculated and is stored in the game binary. Each release uses a new set of keys, so there's no point in trying to find the server key a (would take too long anyway).

The same key is used for transmitting and receiving data, but both paths use a separate state.

From what I heard, this is the same as how it was in GuildWars 1.

The actual data protocol used is a binary protocol with variable sized packets. The client has a MsgPack/Unpack function to (de)serialize the data to/from a C structure.

Again this is similar to how GuildWars 1 worked.


This is a quick overview of how the communication works, I'll go into greater detail in a following post.


2 comments:

Ge0 said...

Very nice blog post for anyone who would get into GW2 internals, and maybe still relevant these days (since your post is almost 3 years old!).

There is one point though:

"From here the connection will switch from text to a binary protocol."

You could have mentioned that it is actually the Transport Layer Security protocol, and not any random protocol.

It could especially prevent reversers from digging into the TLS protocol instead of reading http://en.wikipedia.org/wiki/Transport_Layer_Security, thus letting them gain some precious time.

Thank you for you work!

Karl Vogel said...

I noticed that it was TLS later on, see http://poke152.blogspot.be/2013/03/portal-connection-update.html