Monitor mode / packet injection not working

44 Views Asked by At

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?

1

There are 1 best solutions below

0
Filip Vuković On BEST ANSWER

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).