我正在尝试使用 scapy 在监控模式下将数据包注入到 wifi 网络中。这是我的代码
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()
我使用
iw list
检查了两张 wifi 卡的费率
此外,两张卡都支持监控模式和数据包注入:使用aircrack-ng套件检查
sudo aireplay-ng <interface> --test
- 都显示
注射起作用了!
然而,当我用一张卡注入一个数据包时,它只在那台计算机上可见,另一张卡看不到它(我为此使用wireshark),我已将两个wifi卡设置为相同的通道和波特率。
我错过了什么?
好的,我很高兴分享我想出的解决方案。它是用 C 语言编写的,我使用原始套接字和 radiotap 标头来制作合法的数据包。我最初使用的网卡并不完全支持数据包注入。所以,现在我使用 Atheros AR9271 注入数据包,使用 Realtek RTL8812BU 进行嗅探。无论如何,这是注入代码:
#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;
}
这是嗅探器:
#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;
}
我使用 openssl 随机标头为有效负载生成随机字节。对于嗅探器来说,packet_handler 中有一个 if ,它是仅针对长度为 1516 的数据包的过滤器(仅过滤我注入的数据包)。