OpenVAS Scanner 23.32.3
nasl_frame_forgery.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
10
11#include "nasl_frame_forgery.h"
12
13#include "../misc/bpf_share.h" /* for bpf_open_live */
15#include "../misc/pcap_openvas.h" /* for get_iface_from_ip */
16#include "../misc/plugutils.h"
17#include "capture_packet.h"
18#include "nasl_debug.h"
19
20#include <errno.h>
21#include <gvm/base/networking.h>
22#include <linux/if_packet.h>
23#include <net/ethernet.h>
24#include <net/if.h>
25#include <net/if_arp.h>
26#include <netinet/ether.h>
27#include <netinet/if_ether.h>
28#include <stdint.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <sys/ioctl.h>
32#include <unistd.h>
33
34#undef G_LOG_DOMAIN
38#define G_LOG_DOMAIN "lib misc"
39
41{
42 struct arphdr arp_header;
43 u_char __ar_sha[ETH_ALEN]; /* Sender hardware address. */
44 u_char __ar_sip[4]; /* Sender IP address. */
45 u_char __ar_tha[ETH_ALEN]; /* Target hardware address. */
46 u_char __ar_tip[4]; /* Target IP address. */
47 u_char __zero_padding[18];
48} __attribute__ ((packed));
49
51{
52 struct ethhdr framehdr;
53 u_char *payload;
54} __attribute__ ((packed));
55
62static void
63dump_frame (const u_char *frame, int frame_sz)
64{
65 int f = 0;
66
67 printf ("\nThe Frame:\n");
68 while (f < frame_sz)
69 {
70 printf ("%02x%02x ", ((u_char *) frame)[f], ((u_char *) frame)[f + 1]);
71 f += 2;
72 if (f % 16 == 0)
73 printf ("\n");
74 }
75 printf ("\n\n");
76}
77
84static void
85prepare_sockaddr_ll (struct sockaddr_ll *soc_addr_ll, int ifindex,
86 const u_char *ether_dst_addr)
87{
88 soc_addr_ll->sll_family = AF_PACKET;
89 soc_addr_ll->sll_ifindex = ifindex;
90 soc_addr_ll->sll_halen = ETHER_ADDR_LEN;
91 soc_addr_ll->sll_protocol = htons (ETH_P_ALL);
92 memcpy (soc_addr_ll->sll_addr, ether_dst_addr, ETHER_ADDR_LEN);
93}
94
102static void
103prepare_message (u_char *msg, struct sockaddr_ll *soc_addr_ll, u_char *payload,
104 int payload_sz)
105{
106 struct iovec iov;
107 struct msghdr *message;
108
109 iov.iov_base = payload;
110 iov.iov_len = payload_sz;
111
112 message = g_malloc0 (sizeof (struct msghdr) + payload_sz);
113
114 message->msg_name = soc_addr_ll;
115 message->msg_namelen = sizeof (struct sockaddr_ll);
116 message->msg_iov = &iov;
117 message->msg_iovlen = 1;
118 message->msg_control = 0;
119 message->msg_controllen = 0;
120
121 memcpy (msg, (u_char *) message, sizeof (struct msghdr) + payload_sz);
122 g_free (message);
123}
124
140static int
141send_frame (const u_char *frame, int frame_sz, int use_pcap, int timeout,
142 char *filter, struct in6_addr *ipaddr, u_char **answer)
143{
144 int soc;
145 u_char *message;
146 int ifindex;
147 int bpf = -1;
148 int frame_and_payload = 0;
149 int answer_sz = -1;
150
151 // Create the raw socket
152 soc = socket (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
153 if (soc == -1)
154 {
155 g_debug ("%s: %s", __func__, strerror (errno));
156 return -1;
157 }
158
159 // We will need the eth index. We get it depending on the target's IP..
160 if (get_iface_index (ipaddr, &ifindex) < 0)
161 {
162 g_message ("%s: Missing interface index\n", __func__);
163 return -1;
164 }
165
166 // Prepare sockaddr_ll. This is necessary for further captures
167 u_char dst_haddr[ETHER_ADDR_LEN];
168 memcpy (&dst_haddr, (struct pseudo_frame *) frame, ETHER_ADDR_LEN);
169
170 struct sockaddr_ll soc_addr;
171 memset (&soc_addr, '\0', sizeof (struct sockaddr_ll));
172 prepare_sockaddr_ll (&soc_addr, ifindex, dst_haddr);
173
174 /* Init capture */
175 if (use_pcap != 0 && bpf < 0)
176 {
177 if (IN6_IS_ADDR_V4MAPPED (ipaddr))
178 {
179 struct in_addr sin, this_host;
180 memset (&sin, '\0', sizeof (struct in_addr));
181 memset (&this_host, '\0', sizeof (struct in_addr));
182 sin.s_addr = ipaddr->s6_addr32[3];
183 bpf = init_capture_device (sin, this_host, filter);
184 }
185 else
186 {
187 struct in6_addr this_host;
188 memset (&this_host, '\0', sizeof (struct in6_addr));
189 bpf = init_v6_capture_device (*ipaddr, this_host, filter);
190 }
191 }
192
193 // Prepare the message and send it
194 message = g_malloc0 (sizeof (struct msghdr) + frame_sz);
195 prepare_message (message, &soc_addr, (u_char *) frame, frame_sz);
196
197 int b = sendmsg (soc, (struct msghdr *) message, 0);
198 g_free (message);
199 if (b == -1)
200 {
201 g_message ("%s: Error sending message: %s", __func__, strerror (errno));
202 return -2;
203 }
204 if (bpf >= 0)
205 {
206 *answer = (u_char *) capture_next_frame (bpf, timeout, &answer_sz,
207 frame_and_payload);
208 bpf_close (bpf);
209 close (soc);
210 return answer_sz;
211 }
212
213 close (soc);
214 return 0;
215}
216
229static int
230forge_frame (const u_char *ether_src_addr, const u_char *ether_dst_addr,
231 int ether_proto, u_char *payload, int payload_sz,
232 struct pseudo_frame **frame)
233{
234 int frame_sz;
235
236 *frame = (struct pseudo_frame *) g_malloc0 (sizeof (struct pseudo_frame)
237 + payload_sz);
238
239 memcpy ((*frame)->framehdr.h_dest, ether_dst_addr, ETHER_ADDR_LEN);
240 memcpy ((*frame)->framehdr.h_source, ether_src_addr, ETHER_ADDR_LEN);
241 (*frame)->framehdr.h_proto = htons (ether_proto);
242 (*frame)->payload = payload;
243
244 frame_sz = ETH_HLEN + payload_sz;
245 memcpy ((char *) *frame + ETH_HLEN, payload, payload_sz);
246
247 return frame_sz;
248}
249
267tree_cell *
269{
270 tree_cell *retc;
271 struct pseudo_frame *frame;
272 int frame_sz;
273 u_char *payload = (u_char *) get_str_var_by_name (lexic, "payload");
274 int payload_sz = get_var_size_by_name (lexic, "payload");
275 char *ether_src_addr = get_str_var_by_name (lexic, "src_haddr");
276 char *ether_dst_addr = get_str_var_by_name (lexic, "dst_haddr");
277 int ether_proto = get_int_var_by_name (lexic, "ether_proto", 0x0800);
278
279 if (ether_src_addr == NULL || ether_dst_addr == NULL || payload == NULL)
280 {
281 nasl_perror (lexic,
282 "%s usage: payload, src_haddr and dst_haddr are mandatory "
283 "parameters.\n",
284 __func__);
285 return NULL;
286 }
287
288 frame_sz = forge_frame ((u_char *) ether_src_addr, (u_char *) ether_dst_addr,
289 ether_proto, payload, payload_sz, &frame);
290
292 retc->x.str_val = (char *) frame;
293 retc->size = frame_sz;
294 return retc;
295}
296
313tree_cell *
315{
316 tree_cell *retc = NULL;
317 struct script_infos *script_infos = lexic->script_infos;
318 struct in6_addr *ipaddr = plug_get_host_ip (script_infos);
319 u_char *frame = (u_char *) get_str_var_by_name (lexic, "frame");
320 int frame_sz = get_var_size_by_name (lexic, "frame");
321 int use_pcap = get_int_var_by_name (lexic, "pcap_active", 1);
322 int to = get_int_var_by_name (lexic, "pcap_timeout", 5);
323 char *filter = get_str_var_by_name (lexic, "pcap_filter");
324 u_char *answer = NULL;
325 int answer_sz;
326
327 if (frame == NULL || frame_sz <= 0)
328 {
329 nasl_perror (lexic, "%s usage: frame is a mandatory parameters.\n",
330 __func__);
331 return NULL;
332 }
333
334 answer_sz =
335 send_frame (frame, frame_sz, use_pcap, to, filter, ipaddr, &answer);
336 if (answer_sz == -2)
337 {
338 g_message ("%s: Not possible to send the frame", __func__);
339 return NULL;
340 }
341
342 if (answer && answer_sz > -1)
343 {
345 retc->x.str_val = (char *) answer;
346 retc->size = answer_sz;
347 }
348
349 return retc;
350}
351
362tree_cell *
364{
365 u_char *frame = (u_char *) get_str_var_by_name (lexic, "frame");
366 int frame_sz = get_var_size_by_name (lexic, "frame");
367
368 if (frame == NULL || frame_sz <= 0)
369 {
370 nasl_perror (lexic, "%s usage: frame is a mandatory parameters.\n",
371 __func__);
372 return NULL;
373 }
374
375 dump_frame (frame, frame_sz);
376 return NULL;
377}
378
388static int
389get_local_mac_address_from_ip (char *ip_address, u_char *mac)
390{
391 struct ifreq ifr;
392 int sock;
393 char *if_name = NULL;
394
395 if_name = get_iface_from_ip (ip_address);
396 if (!if_name)
397 {
398 g_debug ("%s: Missing interface name", __func__);
399 return -1;
400 }
401
402 strncpy (ifr.ifr_name, if_name, sizeof (ifr.ifr_name) - 1);
403 g_free (if_name);
404 ifr.ifr_name[sizeof (ifr.ifr_name) - 1] = '\0';
405
406 sock = socket (PF_INET, SOCK_STREAM, 0);
407 if (-1 == sock)
408 {
409 perror ("socket() ");
410 return -1;
411 }
412
413 if (-1 == ioctl (sock, SIOCGIFHWADDR, &ifr))
414 {
415 g_debug ("%s: ioctl(SIOCGIFHWADDR)", __func__);
416 return -1;
417 }
418
419 memcpy (mac, (u_char *) ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
420 close (sock);
421
422 return 0;
423}
424
437tree_cell *
439{
440 tree_cell *retc = NULL;
441 char *buffer = NULL;
442 u_char *mac;
443
444 char *ip_address = get_str_var_by_num (lexic, 0);
445
446 mac = g_malloc0 (sizeof (u_char) * ETHER_ADDR_LEN);
448 if (mac != NULL)
449 {
450 buffer = g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1],
451 mac[2], mac[3], mac[4], mac[5]);
452 g_free (mac);
454 retc->x.str_val = buffer;
455 retc->size = 17;
456 }
457
458 return retc;
459}
460
470tree_cell *
472{
473 tree_cell *retc = NULL;
474 struct in6_addr src, *dst = plug_get_host_ip (lexic->script_infos);
475 struct in_addr dst_inaddr, src_inaddr;
476 struct pseudo_eth_arp eth_arp;
477 struct pseudo_frame *frame;
478 int frame_sz;
479 char ip_src_str[INET6_ADDRSTRLEN];
480 u_char mac_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
481 u_char mac[6], *mac_aux;
482 char filter[255];
483 u_char *answer = NULL;
484 int answer_sz;
485 int to = get_int_var_by_name (lexic, "pcap_timeout", 5);
486
487 /* Get source IP address via routethrough. We need it to find our mac address.
488 */
489 if (dst == NULL || (IN6_IS_ADDR_V4MAPPED (dst) != 1))
490 return retc;
491
492 memset (&dst_inaddr, '\0', sizeof (struct in_addr));
493 dst_inaddr.s_addr = dst->s6_addr32[3];
494 routethrough (&dst_inaddr, &src_inaddr);
495 ipv4_as_ipv6 (&src_inaddr, &src);
496
497 /* Getting target IP address as string, to get the mac address */
498 addr6_to_str (&src, ip_src_str);
499
500 mac_aux = (u_char *) g_malloc0 (sizeof (u_char) * 6);
501 get_local_mac_address_from_ip (ip_src_str, mac_aux);
502 mac[0] = mac_aux[0];
503 mac[1] = mac_aux[1];
504 mac[2] = mac_aux[2];
505 mac[3] = mac_aux[3];
506 mac[4] = mac_aux[4];
507 mac[5] = mac_aux[5];
508 g_free (mac_aux);
509
510 /* Building ARP header */
511 memset (&eth_arp, '\0', sizeof (struct pseudo_eth_arp));
512 eth_arp.arp_header.ar_hrd = htons (ARPHRD_ETHER);
513 eth_arp.arp_header.ar_pro = htons (ETHERTYPE_IP);
514 eth_arp.arp_header.ar_hln = ETH_ALEN;
515 eth_arp.arp_header.ar_pln = 4;
516 eth_arp.arp_header.ar_op = htons (ARPOP_REQUEST);
517
518 memcpy (&(eth_arp.__ar_sha), mac, ETH_ALEN);
519 memcpy (&(eth_arp.__ar_sip), &src_inaddr, 4);
520 memcpy (&(eth_arp.__ar_tha), mac_broadcast_addr, ETH_ALEN);
521 memcpy (&(eth_arp.__ar_tip), &dst_inaddr, 4);
522
523 frame_sz =
524 forge_frame (mac, mac_broadcast_addr, ETH_P_ARP, (u_char *) &eth_arp,
525 sizeof (struct pseudo_eth_arp), &frame);
526
527 /* Prepare filter */
528 snprintf (filter, sizeof (filter), "arp and src host %s",
529 inet_ntoa (dst_inaddr));
530
531 answer_sz =
532 send_frame ((const u_char *) frame, frame_sz, 1, to, filter, dst, &answer);
533 g_free (frame);
534 if (answer_sz == -2)
535 {
536 g_message ("%s: Not possible to send the frame", __func__);
537 return NULL;
538 }
539
540 if (answer && answer_sz > -1)
541 {
542 char *daddr;
543 struct ether_header *answer_aux;
544
545 answer_aux = (struct ether_header *) answer;
546 daddr = g_strdup_printf (
547 "%02x:%02x:%02x:%02x:%02x:%02x", (u_int) answer_aux->ether_shost[0],
548 (u_int) answer_aux->ether_shost[1], (u_int) answer_aux->ether_shost[2],
549 (u_int) answer_aux->ether_shost[3], (u_int) answer_aux->ether_shost[4],
550 (u_int) answer_aux->ether_shost[5]);
551
553 retc->x.str_val = daddr;
554 retc->size = strlen (daddr);
555 }
556 else
557 g_debug ("%s: No answer received.", __func__);
558
559 return retc;
560}
void bpf_close(int bpf)
Definition bpf_share.c:164
Header file for module bpf_share.
char * capture_next_frame(int bpf, int timeout, int *sz, int dl_layer_only)
Capture a link layer frame.
int init_capture_device(struct in_addr src, struct in_addr dest, char *filter)
Set up the pcap filter, and select the correct interface.
int init_v6_capture_device(struct in6_addr src, struct in6_addr dest, char *filter)
gpg_err_code_t mac(const char *key, const size_t key_len, const char *data, const size_t data_len, const char *iv, const size_t iv_len, int algo, int flags, char **out, size_t *out_len)
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition nasl_debug.c:105
static int forge_frame(const u_char *ether_src_addr, const u_char *ether_dst_addr, int ether_proto, u_char *payload, int payload_sz, struct pseudo_frame **frame)
Forge a datalink layer frame.
tree_cell * nasl_send_frame(lex_ctxt *lexic)
Send a frame and listen to the answer.
static int get_local_mac_address_from_ip(char *ip_address, u_char *mac)
Get the MAC address of host.
static int send_frame(const u_char *frame, int frame_sz, int use_pcap, int timeout, char *filter, struct in6_addr *ipaddr, u_char **answer)
Send a frame and listen to the answer.
static void prepare_sockaddr_ll(struct sockaddr_ll *soc_addr_ll, int ifindex, const u_char *ether_dst_addr)
Prepare message header to be sent with sendmsg().
tree_cell * nasl_dump_frame(lex_ctxt *lexic)
Dump a datalink layer frame.
static void prepare_message(u_char *msg, struct sockaddr_ll *soc_addr_ll, u_char *payload, int payload_sz)
Prepare message header to be sent with sendmsg().
tree_cell * nasl_get_local_mac_address_from_ip(lex_ctxt *lexic)
Get the MAC address of host.
static void dump_frame(const u_char *frame, int frame_sz)
Dump a datalink layer frame.
u_char * payload
tree_cell * nasl_forge_frame(lex_ctxt *lexic)
Forge a datalink layer frame.
tree_cell * nasl_send_arp_request(lex_ctxt *lexic)
Send an arp request to an IP host.
Header file for module nasl_frame_forgery.
struct struct_lex_ctxt lex_ctxt
int get_var_size_by_name(lex_ctxt *, const char *)
Definition nasl_var.c:1138
char * get_str_var_by_name(lex_ctxt *, const char *)
Definition nasl_var.c:1118
char * get_str_var_by_num(lex_ctxt *, int)
Definition nasl_var.c:1108
long int get_int_var_by_name(lex_ctxt *, const char *, int)
Definition nasl_var.c:1101
struct in_addr daddr
struct pseudo_udp_hdr __attribute__
tree_cell * alloc_typed_cell(int typ)
Definition nasl_tree.c:25
@ CONST_DATA
Definition nasl_tree.h:82
struct TC tree_cell
char * routethrough(struct in_addr *dest, struct in_addr *source)
An awesome function to determine what interface a packet to a given destination should be routed thro...
Definition pcap.c:1070
int get_iface_index(struct in6_addr *ipaddr, int *ifindex)
Get the interface index depending on the target's IP.
Definition pcap.c:1334
char * get_iface_from_ip(const char *local_ip)
Given an IP address, determines which interface belongs to.
Definition pcap.c:1280
Header file for module pcap.
struct in6_addr * plug_get_host_ip(struct script_infos *args)
Definition plugutils.c:371
Header file for module plugutils.
int size
Definition nasl_tree.h:99
union TC::@332262321161220155002104006201360276211317150140 x
char * str_val
Definition nasl_tree.h:103
u_char __ar_sha[ETH_ALEN]
struct arphdr arp_header
u_char __ar_tha[ETH_ALEN]
u_char __zero_padding[18]
struct ethhdr framehdr
struct script_infos * script_infos