<<< Date Index >>>     <<< Thread Index >>>

Hidden Gamespy code leads to vulnerabilities in diffused games (BF1942, Halo, Dredd and more)



#######################################################################

                             Luigi Auriemma

Application:  Gamespy SDK used for online cd-keys validation in third
              party code (hidden "security through obscurity" code)

Games/ver:    Battlefield 1942                     <= 1.6.19 and 1.6rc1
              ___________________________http://www.battlefield1942.com
              Contract Jack                                      <= 1.1
              ___________________________________http://nolf.sierra.com
              Gore                                       <= 1.48 (1.49)
              _________________________________http://gore.cryogame.com
              Haegemonia                                       <= 1.0.7
              ________________________________http://www.haegemonia.com
              Halo                                             <= 1.031
              _____________________http://www.microsoft.com/games/halo/
              Hidden & Dangerous 2                              <= 1.04
              ______________________http://www.hidden-and-dangerous.com
              IGI 2: Covert Strike                               <= 1.3
              _________________________________http://www.igi2-game.com
              Judge Dredd: Dredd vs. Death                      <= 1.01
              ______________________________http://www.dreddvsdeath.com
              Need For Speed Hot Pursuit 2                       <= 242
              ______________http://www.eagames.com/pccd/nfshp2/home.jsp
              Terminator 3: War of the Machines                     1.0
              _____________________________________http://www.t3war.com
              TRON 2.0                                         <= 1.042
              ____________________________________http://www.tron20.com
              probably also other games

Platforms:    Windows, Linux and MacOS

Bugs:         A] crash of games'servers
              B] privacy problems

Risk:         A] high
              B] very low

Exploitation: remote

Date:         24 Feb 2004

Author:       Luigi Auriemma
              e-mail: aluigi@xxxxxxxxxxxxxx
              web:    http://aluigi.altervista.org


#######################################################################


1) Introduction
2) Bugs
3) Analysis of the hidden code
4) The Code
5) Fix
6) Conclusion


#######################################################################

===============
1) Introduction
===============


First I want to premise that these bugs have been discovered during a
bug research on a specific game and I knew about the implication of
Gamespy only some minutes later.
Yes Gamespy, the people who say to "welcome any and all help" and then
send me an useless Cease&Desist and DEFAME me and moreover my hobby,
the same people who say to "protect gamers rights and provide security"
and then leave RogerWilco and Gamespy3d vulnerables to highly critical
and pubblic old bugs (still now), the same "trusted people" who claim
"Gamers trust us" and at the same time insert hidden functions in third
party games.
http://aluigi.altervista.org/papers/castleoflies.txt

The code now object of this research is just the SDK that Gamespy
gives/sells to games developers to implement the online management and
validation of games cd-keys.
The worst thing of this SDK is that it uses simples "security through
obscurity" methods to hide informations to the same users who use these
vulnerable games (any existent type of demo, retail and dedicated
server) so this advisory will also clarify these shameful methods
avoiding that these users like me continue to be joked.

The bugs I want to analyze are essentially the following:

  A] security bug/programming error:   crash in the games servers
  B] security through obscurity bug:   possible privacy problems

Fortunally the developers have the source code of the bugged SDK so all
the people I have personally contacted a lot of weeks ago have had the
possibility to fix the first bug without problems.

Then some weeks ago Gamespy has also released a patched SDK to the
developers of the vulnerable games, in fact they have been contacted
just by one of the developers I have talked with... in fact as
everybody knows for me is impossible to directly contact Gamespy
because they are incapable to understand and manage my bugs
signalations.

However I have also provided some unofficial fixes for the games that
have no official patches at the moment or that are no more supported.


#######################################################################

=======
2) Bugs
=======


-------------------------
A] crash of games'servers
-------------------------

The problem is located in the instructions that copy the portion of the
received query packet delimited by backslashes (as \query\) into a new
buffer.
The vulnerable instructions are similar to the following:

  int size = strchr(buff + 1, '\\') - buff;
  if(size > 32) return;
  strncpy(querybuff, buff + 1, size);

"buff" is the decoded packet (look at next section) containing one of
the hidden Gamespy commands, "size" is a signed integer number that
contains the amount of bytes to copy and "querybuff" is the buffer that
will contain the query for comparison with the hidden commands.

In this code we can find 2 programming errors:

- the return value of strchr() is not checked so if it fails the
  Gamespy code continues to think that the address of the string
  returned is valid also if it is 0 (failed).
- "size" is managed as a signed integer (+/- sign) so when strchr()
  fails the function does a "0 - buff" operation (difference between
  the end and the beginning of the query) that results in a negative 32
  bit number.
  The problem happens when the function checks if "size" is major than
  32 because naturally this is a signed comparison and "size" has a
  negative sign.

The effect of the bug is an exception in the strncpy() function that
interrupts the server immediately.


-------------------
B] privacy problems
-------------------

As already said, the Gamespy code implements security through obscurity
techniques to avoid that the servers'administrators see or understand
the queries sent and received to their own systems (why? I don't know,
ask to Gamespy).
These queries however are nothing of "special" but can cause some
privacy problems to games servers and clients.
The following is the command that gives problems:

ison: used to know if in the target game server is playing an user with
      a specific cd-key

For example this command can be used to track a specific user if we
know his cd-key or its MD5 hash (hash sent to any game server where the
client joins).


#######################################################################

==============================
3) Analysis of the hidden code
==============================


The Gamespy cd-key SDK is a partially hidden function activated when
the game server receives a packet with a specific byte in it or must
validate a client's cd-key.
I'm just one of the users of some of the vulnerable games and I don't
accept that someone inserts hidden code in the games I buy or
administer (moreover if they are not the developers and I don't trust
in them) so this analysis will finally light on a part of this code,
the part that directly affects users.

The hidden function used to manage the "undocumented" queries is
activated when a packet starting with the char ';' (byte 0x3b) reaches
the query port of the game server of any user online.
The query port is just the same UDP port used to receive the
information queries as "basic", "info", "status", "rules" and all the
others.

The char ';' in reality is the char backslash (the same used at the
beginning of any normal query) "XORed" with the char 'g' of the string
"gamespy", in fact the packet that reaches the game server is simply
encoded using the XOR operator.
The following is an optimized C function that explains how works the
encoding/deconding operation:

void gamespyxor(u_char *string, int len) {
    u_char  gamespy[] = "gamespy",
            *gs;
    for(gs = gamespy; len; len--, gs++, string++) {
        if(!*gs) gs = gamespy;
        *string ^= *gs;
    }
}

After having decoded the data the hidden Gamespy function assembles the
supported 4 commands in memory for comparison with that received in the
packet. The method used for this operation is very simple and its only
purpose is to hide the available commands to who tries to open the game
executable with a disassembler or a hex editor.
The following is a real example showing how the 4 commands used in the
function are assembled:

:004422B7 B175                    mov cl, 75
:004422B9 B06F                    mov al, 6F
:004422BB 56                      push esi
:004422BC 8BF2                    mov esi, edx
:004422BE B26E                    mov dl, 6E
:004422C0 884C240C                mov byte[esp+0C], cl
:004422C4 884C2410                mov byte[esp+10], cl
:004422C8 884C2420                mov byte[esp+20], cl
:004422CC 884C2423                mov byte[esp+23], cl
:004422D0 33C9                    xor ecx, ecx
:004422D2 85F6                    test esi, esi
:004422D4 8844240D                mov byte[esp+0D], al
:004422D8 88442412                mov byte[esp+12], al
:004422DC 8844241A                mov byte[esp+1A], al
:004422E0 88442422                mov byte[esp+22], al
:004422E4 C644240E6B              mov byte[esp+0E], 6B
:004422E9 C644240F00              mov byte[esp+0F], 00
:004422EE 88542411                mov byte[esp+11], dl
:004422F2 C64424136B              mov byte[esp+13], 6B
:004422F7 C644241400              mov byte[esp+14], 00
:004422FC C644241869              mov byte[esp+18], 69
:00442301 C644241973              mov byte[esp+19], 73
:00442306 8854241B                mov byte[esp+1B], dl
:0044230A C644241C00              mov byte[esp+1C], 00
:0044230F C644242163              mov byte[esp+21], 63
:00442314 88542424                mov byte[esp+24], dl
:00442318 C644242574              mov byte[esp+25], 74
:0044231D C644242600              mov byte[esp+26], 00

The portion of code comes directly from the file BF1942_w32ded.exe of
Battlefield 1942 Win32 dedicated server 1.6.19 but this "hiding
technique" is the same used in all the other vulnerable games and
moreover also in all the Gamespy products (..."Gamers trust us"...).

The generated commands are exactly: "uok", "unok", "ison" and "ucount".
The first 2 commands in reality are replies sent by the Gamespy master
server to the games servers when they request the validation of a
cd-key using the "auth" query.

Instead the real interesting commands are "ison" and a bit "ucount"
that are used respectively to know if a specific cd-key is currently
used in the target game server and how many players in the server are
using cd-keys.
The following are some practical usage examples:

\uok\\cd\0123456789abcdef0123456789abcdef\skey\1\errmsg\Valid CD Key
\unok\\cd\0123456789abcdef0123456789abcdef\skey\1\errmsg\Invalid CD Key
\ison\skey\1\cd\0123456789abcdef0123456789abcdef
\ucount\

Where "skey" is an ID number used to track replies to a specific query
and "cd" is the cd-key hash.
The cd-key hash is simply the MD5 hash calculated by the client on his
original cd-key, it is sent by each client to the game server that uses
it to validate the client through the master server.

When the server has assembled the available commands in memory it
compares the received query with eachone of these 4 strings and then
sends the relative answer if needed.
The following are the possible answers for the commands "ison" and
"ucount":

\uon\\skey\1     the requested cd-key is used in the target server
\uoff\\skey\1    the requested cd-key is not used in the target server
\ucount\9        in the target server there are 9 players using cd-keys


#######################################################################

===========
4) The Code
===========


-------------------------
A] crash of games'servers
-------------------------

To test this bug is needed the simple sending of the char ';' to the
UDP query port of the vulnerable game server that is hosting the match
who will crash immediately, however I have written also an useful
proof-of-concept:

    http://aluigi.altervista.org/poc/gshboom.zip


-------------------
B] privacy problems
-------------------

The following is a tool to check the games that use the hidden Gamespy
code, it is able to send all the availables 4 commands (remember that
"uok" and "unok" aren't queries but replies so they cannot be used):

    http://aluigi.altervista.org/papers/gshinfo.zip

Then I have written also a simple packet analyzer for Windows to know
and decode on the fly all the UDP packets sent and received from the
Gamespy master server or by any other host choosen by the user:

    http://aluigi.altervista.org/papers/gshsniff.zip

The latest tool instead is a logger used to log all and only the
encoded commands sent and received on a specific UDP query port:

    http://aluigi.altervista.org/papers/gshlog.zip


#######################################################################

======
5) Fix
======


----------------
Official patches
----------------

As already said, some weeks ago Gamespy has released an updated SDK
that should fix the vulnerability so virtually all the vulnerable games
that I didn't know were vulnerables have or will have a fix soon.

However ALL the developers of the vulnerable games I knew vulnerables
and I have personally checked have been quickly alerted with multiple
mails for one month.

The following is the patches'situation in the moment I'm writing:

 Battlefield 1942.....................FIXED only Linux DS 1.6RC2.
     I was in contact with Dice about the bug but after the Linux
     dedicated server patch I lost any contact with them (no replies)
     so I don't know the current status of the fixes for the retail and
     the win32 dedicated server
 Contract Jack........................NOT, seems no more supported
 Gore.................................NOT, MYFIX
 Haegemonia...........................NOT, seems to use a modified
     SDK so cannot be crashed with the classic attack but contains the
     vulnerable instructions
 Halo.................................FIXED in 1.04
 Hidden & Dangerous 2.................NOT, MYFIX DS only
 IGI 2: Covert Strike.................NOT, MYFIX DS only
 Judge Dredd: Dredd vs. Death.........NOT
 Need For Speed Hot Pursuit 2.........NOT
 Terminator 3: War of the Machines....FIX is coming, however it is not
     vulnerable to the classic attack explained in the previous section
 TRON 2.0.............................NOT, seems no more supported


--------
My fixes
--------

Fortunally patching the bug is very very simple so I have written some
manual patches (need hex editor) that fully patch the problem in almost
all the unpatched games:

Game                          file               offset    old  patch
----------------------------------------------------------------------
BF1942 win32 DS 1.6.19        BF1942_w32ded.exe  00042370  7f   77
Gore 1.48 and 1.49            gore.exe           000B86F2  7f   77
Hidden & Dangerous 2 1.04 DS  HD2DS.exe          003498CA  7f   77
Igi2 1.3 dedicated server     igi2.exe           001C937A  7f   77

  All the other games or retail versions use encrypted executables for
  their lame and useless CD protections and I don't and I can't support
  them with my fixes.
  This is another confirmation that CD protections are a limit for real
  users and in this case also for people who wanna fix their
  "no-more-supported" games:
  http://aluigi.altervista.org/patches/nocd.txt

Explanation of my fix
---------------------
My fix simply converts a JG (signed comparison) in a JA (UNsigned).
Practically when strchr() fails it returns a 0, then the Gamespy
function does a "0 - buff" to find how big is the query and then checks
if the result is major than 32.
BUT this comparison is signed (+/-) so the result of "0 - buff" in
reality is minor than 32 and the comparison fails.
My fix so does simply an UNsigned comparison so "0 - buff" is major
than 32 and the malicious query is successfully rejected.


#######################################################################

=============
6) Conclusion
=============


Trust should be gained with real facts and not with lies and secrets.


#######################################################################


--- 
Luigi Auriemma
http://aluigi.altervista.org