I'm trying to inject a packet to the wifi network in monitor mode using scapy. Here is my code
from scapy.all import *
class Dot11EltRates(Packet):
""" Our own definition for the supported rates field """
name = "802.11 Rates Information Element"
# Our Test STA supports the rates 6, 9, 12, 18, 24, 36, 48 and 54 Mbps
supported_rates = [0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c]
fields_desc = [ByteField("ID", 1), ByteField("len", len(supported_rates))]
for index, rate in enumerate(supported_rates):
fields_desc.append(ByteField("supported_rate{0}".format(index + 1),
rate))
src = "4c:5e:0c:11:01:95"
dst = "d0:39:57:b8:a8:bf"
packet = Dot11(
addr1=src,
addr2=dst,
addr3=src) / Dot11AssoReq(
cap=0x1100, listen_interval=0x00a) / Dot11Elt(
ID=0, info="MY_BSSID")
packet /= Dot11EltRates()
sendp(packet, iface="wlan0mon")
packet.show()
I checked the rates on both wifi cards using iw list
Also, both cards support monitor mode and packet injection: checked with aircrack-ng suite sudo aireplay-ng <interface> --test
- both show
Injection is working!
And yet, when I inject a packet with one card its only visible on that computer, the other doesn't see it (I'm using wireshark for this), I have set both wifi cards to the same channel and baudrate.
What am I missing?
Okay, I'm happy to share the solution that I came up with. Its in C, I'm using raw sockets and radiotap header to craft a legal packet. The networking cards that I initially used did not fully support packet injection. So, now im using Atheros AR9271 to inject packets and Realtek RTL8812BU for sniffing. Anyways here is the injection code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <sys/ioctl.h>
#include <openssl/rand.h>
struct radiotap_header
{
unsigned char it_version;
unsigned char it_pad;
unsigned short it_len;
unsigned int it_present;
};
struct ieee80211_header
{
unsigned short frame_control;
unsigned short duration_id;
unsigned char addr1[ETHER_ADDR_LEN];
unsigned char addr2[ETHER_ADDR_LEN];
unsigned char addr3[ETHER_ADDR_LEN];
unsigned short seq_ctrl;
};
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <interface>\n", argv[0]);
return 1;
}
int sockfd;
struct sockaddr_ll sll;
char *interface = argv[1];
sockfd = socket(AF_PACKET, SOCK_RAW, 0);
if (sockfd < 0)
{
perror("socket");
return 1;
}
struct ifreq if_idx;
memset(&if_idx, 0, sizeof(struct ifreq));
strncpy(if_idx.ifr_name, interface, IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)
{
perror("ioctl");
return 1;
}
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_ifindex = if_idx.ifr_ifindex;
sll.sll_protocol = htons(ETH_P_ALL);
if (bind(sockfd, (struct sockaddr *)&sll, sizeof(sll)) < 0)
{
perror("bind");
return 1;
}
struct radiotap_header radiotap_hdr;
radiotap_hdr.it_version = 0;
radiotap_hdr.it_pad = 0;
radiotap_hdr.it_len = 0x08;
radiotap_hdr.it_present = 0;
struct ieee80211_header wifi_hdr;
wifi_hdr.frame_control = htons(0x0800);
wifi_hdr.duration_id = htons(0x0000);
memset(wifi_hdr.addr1, 0xff, 6);
memset(wifi_hdr.addr2, 0x11, 6);
memset(wifi_hdr.addr3, 0x11, 6);
wifi_hdr.seq_ctrl = htons(0x0000);
int buffer_size = 1450;
char *bufferToSend = malloc(buffer_size);
char *str_to_append = "TestingTestingTesting";
int str_to_append_len = strlen(str_to_append);
int packet_size = sizeof(struct radiotap_header) + sizeof(struct ieee80211_header) + buffer_size;
unsigned char *complete_packet = (unsigned char *)malloc(packet_size);
if (RAND_poll() != 1)
{
printf("RAND_poll");
return 1;
}
if (RAND_bytes(bufferToSend, buffer_size) != 1)
{
printf("RAND_bytes");
return 1;
}
strncpy(bufferToSend + (buffer_size - str_to_append_len), str_to_append, str_to_append_len);
strncpy(bufferToSend, str_to_append, str_to_append_len);
memcpy(complete_packet, &radiotap_hdr, sizeof(struct radiotap_header));
memcpy(complete_packet + sizeof(struct radiotap_header), &wifi_hdr, sizeof(struct ieee80211_header));
memcpy(complete_packet + sizeof(struct radiotap_header) + sizeof(struct ieee80211_header), bufferToSend, buffer_size);
int ret = write(sockfd, complete_packet, packet_size);
if (ret < 0)
{
perror("write");
return 1;
}
printf("Packet sent successfully\n");
free(complete_packet);
free(bufferToSend);
close(sockfd);
return 0;
}
And here is the sniffer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <signal.h>
static volatile int keep_running = 1;
void int_handler(int dummy) {
keep_running = 0;
}
struct radiotap_header
{
unsigned char it_version;
unsigned char it_pad;
unsigned short it_len;
unsigned int it_present;
};
struct ieee80211_header
{
unsigned short frame_control;
unsigned short duration_id;
unsigned char addr1[6];
unsigned char addr2[6];
unsigned char addr3[6];
unsigned short seq_ctrl;
};
size_t bytes_received = 0;
void packet_handler(const unsigned char *packet, int packet_len)
{
bytes_received += packet_len;
struct radiotap_header *radiotap_hdr = (struct radiotap_header *)packet;
struct ieee80211_header *wifi_hdr = (struct ieee80211_header *)(packet + radiotap_hdr->it_len);
if (packet_len == 1516){
printf("Packet size: %d\n", packet_len);
printf("==============================================\n");
printf("Received packet:\n");
printf("Frame Control: 0x%04x\n", ntohs(wifi_hdr->frame_control));
printf("Duration ID: %d\n", ntohs(wifi_hdr->duration_id));
printf("Address 1: %02x:%02x:%02x:%02x:%02x:%02x\n", wifi_hdr->addr1[0], wifi_hdr->addr1[1], wifi_hdr->addr1[2], wifi_hdr->addr1[3], wifi_hdr->addr1[4], wifi_hdr->addr1[5]);
printf("Address 2: %02x:%02x:%02x:%02x:%02x:%02x\n", wifi_hdr->addr2[0], wifi_hdr->addr2[1], wifi_hdr->addr2[2], wifi_hdr->addr2[3], wifi_hdr->addr2[4], wifi_hdr->addr2[5]);
printf("Address 3: %02x:%02x:%02x:%02x:%02x:%02x\n", wifi_hdr->addr3[0], wifi_hdr->addr3[1], wifi_hdr->addr3[2], wifi_hdr->addr3[3], wifi_hdr->addr3[4], wifi_hdr->addr3[5]);
printf("Sequence Control: 0x%04x\n", ntohs(wifi_hdr->seq_ctrl));
printf("radiotap_hdr->it_len: %d\n", radiotap_hdr->it_len);
printf("sizeof(struct ieee80211_header): %d\n", sizeof(struct ieee80211_header));
int payload_start = radiotap_hdr->it_len + sizeof(struct ieee80211_header);
int payload_size = packet_len - payload_start;
printf("Payload start: %d\n", payload_start);
printf("Payload size: %d\n", payload_size);
printf("\n\n");
printf("Payload at start: \n");
for (int i = payload_start; i < payload_start + 20; i++){
printf("%c", packet[i]);
}
printf("\n");
printf("Payload at end: \n");
for (int i = payload_size - 20; i < packet_len; i++){
printf("%c", packet[i]);
}
printf("\n");
printf("==============================================\n");
}
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <interface>\n", argv[0]);
return 1;
}
signal(SIGINT, int_handler);
int sockfd;
struct sockaddr_ll sll;
char buffer[BUFSIZ];
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0)
{
perror("socket");
return 1;
}
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_ifindex = if_nametoindex(argv[1]);
if (sll.sll_ifindex == 0)
{
perror("if_nametoindex");
return 1;
}
if (bind(sockfd, (struct sockaddr *)&sll, sizeof(sll)) < 0)
{
perror("bind");
return 1;
}
printf("Listening on %s...\n", argv[1]);
while (keep_running)
{
int recv_len = recv(sockfd, buffer, BUFSIZ, 0);
if (recv_len < 0)
{
perror("recv");
return 1;
}
packet_handler((unsigned char *)buffer, recv_len);
}
close(sockfd);
printf("Total bytes received: %zu\n", bytes_received);
return 0;
}
I'm using openssl random header to generate random bytes for a payload. And for sniffer there is an if in packet_handler that is a filter for only packets of length 1516 (filtering only my injected packets).