Information Assurance

Kenneth Lee


front | classes | research | personal | contact

Information Assurance

Bugtraq Analysis

Half-Life Server ver. 1.1.1.0 Vulnerability

back to bugtraq analyses page

The reference site for this exploit can be found here: http://www.securityfocus.com/archive/1/330880

Half-Life is a popular First Person Shooter (a.k.a. FPS) video game for the windows and linux platforms that has caught the world by storm since its release in 1998. Its popularity skyrocketed by the creation of several popular modifications to the game, such as Counter-Strike and Day of Defeat.

The following vulnerability can be exploited in two ways: the first is a DoS against the server, the second simply causes it to freeze up in an infinite loop.

Basically, the problem occurs when too long of a parameter is passed into the packet when joining a multiplayer game. Parameters are typically things like player name, character skin, etc.

#define PAYLOAD [268 chars]

#define BOF "\xff\xff\xff\xff" "connect %d" " %s \"" "\\prot\\2" "\\unique\\-1" "\\raw\\00000000000000000000000000000000" "\" \"" "\\model\\" MODEL "\\topcolor\\" TOPCOLOR "\\bottomcolor\\" BOTTOMCOLOR "\\rate\\9999.000000" "\\cl_updaterate\\20" "\\cl_lw\\1" "\\cl_lc\\1" "\\cl_dlmax\\128" "\\hud_classautokill\\1" "\\name\\" NAME "\\ "PAYLOAD "\\value" "\"\n"

d% is the supported protocol version that the server uses. %s is a challenge key previously sent by the server.

The problem occurs when Half-life processes PAYLOAD. Because the respective buffer for parsing PAYLOAD can only manage 264 characters, we have a problem on our hands.

Specifically, the game calls a set of instructions within SWDS.DLL:

:00D3E425 3C5C cmp al, 5C

:00D3E427 740B je 00D3E434

:00D3E429 8801 mov byte ptr [ecx], al

:00D3E42B 8A4601 mov al, byte ptr [esi+01]

:00D3E42E 41 inc ecx :00D3E42F 46 inc esi

:00D3E430 3AC3 cmp al, bl

:00D3E432 75F1 jne 00D3E425

Basically, this set of assembly instructions works sort of like strcpy() in that it takes the variable and stores it in memory, and moves to the next position. The problem is that mov byte ptr can cause an overflow since there is no check to see if the buffer is large enough to hold what we want.

This is a general idea of how the stack is laid out, the value buffer being ontop of everything else. If EIP is fully overwritten, then an exploit is possible against the server.

[value_buff]...[parameter_buff]...[EBP][EIP]

The server freeze and the buffer overflow operate almost exactly the same in terms of what code they utilize--the only difference being the location of the PAYLOAD. If Payload is specified as a parameter first, then an overflow is possible because no check is made against the size of the parameter buffer, and everything can be overwritten. However, if the Payload is inserted as a value to a parameter, then the infinite loop case prevails (because even though the value buffer gets overwritten, you don't have enough acceptable characters to overwrite all the way to the EIP.

The reason that having the Payload as a value does not cause an overflow is because Half-Life can only accept values that are 380 characters or less per string, thus limiting the amount of memory you can overwrite. This, combined with the fact that the value buffer is above the parameter buffer on the stack prevents you from overriding the EIP.In fact, what happens instead as a result of this attempt at an overflow is that you have a really good DoS against the server because the function continuously checks the value string over and over.

There are two ways to correct this problem: the first being to simply avoid accepting Parameters and Values that use 268 or more characters. Because a lot of modifications tend to streamline their code, a lot of parameters for Half-Life modifications tend to be very small in size anyways, so cutting off strings more than 268 characters would have a minimal effect. The other way would be to check if the parameter and value buffers have enough spare to write the string into memory.

The discoverer of these vulnerabilities posted his own solution to this problem which basically avoids the data if it is longer than 256 bytes (I personally do not know of any Half-Life modifications that use strings that long for parameters/values). Valve also released a server patch that fixed the problem.