From 1fac49bb9bed3b10829eb71be99afce836196af7 Mon Sep 17 00:00:00 2001 From: flykhan Date: Mon, 11 Sep 2023 20:58:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=9F=E5=A7=8B=E5=A5=97=E6=8E=A5=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- day6/n1.c | 22 +++++++++ day6/n2.c | 66 +++++++++++++++++++++++++ day6/n3.c | 115 ++++++++++++++++++++++++++++++++++++++++++++ day6/n4.c | 79 ++++++++++++++++++++++++++++++ day6/n5.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ day6/n6.c | 92 +++++++++++++++++++++++++++++++++++ 6 files changed, 515 insertions(+) create mode 100644 day6/n1.c create mode 100644 day6/n2.c create mode 100644 day6/n3.c create mode 100644 day6/n4.c create mode 100644 day6/n5.c create mode 100644 day6/n6.c diff --git a/day6/n1.c b/day6/n1.c new file mode 100644 index 0000000..850a0d7 --- /dev/null +++ b/day6/n1.c @@ -0,0 +1,22 @@ +/*创建链路层的原始套接字*/ +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) +{ + // 创建原始套接字 + int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sock_fd < 0) + { + perror("raw socket"); + return -1; + } + printf("原始套接字创建成功\n"); + + close(sock_fd); + + return 0; +} diff --git a/day6/n2.c b/day6/n2.c new file mode 100644 index 0000000..35a959c --- /dev/null +++ b/day6/n2.c @@ -0,0 +1,66 @@ +/*拆解到IP报文*/ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char const *argv[]) +{ + // 创建原始套接字 + int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sock_fd < 0) + { + perror("raw socket"); + return -1; + } + printf("原始套接字创建成功\n"); + + // 多次接收数据 + while (1) + { + // 接链路层的数据报文(MAC报文) + unsigned char buf[1518] = ""; // 记得使用无符号类型 + int len = recvfrom(sock_fd, buf, sizeof(buf), 0, NULL, NULL); + if (len < 18) + { + perror("recvfrom"); + continue; + } + + // 拆解 MAC 数据报文 + unsigned char dst_mac[18] = ""; // 目的MAC地址 + unsigned char src_mac[18] = ""; // 源MAC地址 + unsigned short mac_type = ntohs(*((unsigned short *)(buf + 12))); + + // sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); + // sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); + sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + // if (strncmp(src_mac, "00:00:00", 8) != 0) + printf("dst_mac %s -> src_mac %s type(%#x)\n", dst_mac, src_mac, mac_type); + + sleep(1); + + switch (mac_type) + { + case 0x0800: + printf("-----ip 数据包-----\n"); + break; + case 0x0806: + printf("-----ARP 数据包-----\n"); + break; + case 0x8035: + printf("-----RARP 数据包-----\n"); + break; + } + } + + close(sock_fd); + + return 0; +} diff --git a/day6/n3.c b/day6/n3.c new file mode 100644 index 0000000..3bbe4f5 --- /dev/null +++ b/day6/n3.c @@ -0,0 +1,115 @@ +/*拆解UDP数据报*/ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) +{ + // 创建原始套接字 + int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sock_fd < 0) + { + perror("raw socket"); + return -1; + } + printf("原始套接字创建成功\n"); + + // 多次接收数据 + while (1) + { + // 接链路层的数据报文(MAC报文) + unsigned char buf[1518] = ""; // 记得使用无符号类型 + int len = recvfrom(sock_fd, buf, sizeof(buf), 0, NULL, NULL); + if (len < 18) + { + perror("recvfrom"); + continue; + } + + // 拆解 MAC 数据报文 + unsigned char dst_mac[18] = ""; // 目的MAC地址 + unsigned char src_mac[18] = ""; // 源MAC地址 + unsigned short mac_type = ntohs(*((unsigned short *)(buf + 12))); + + sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); + + if (strncmp(src_mac, "00:00:00", 8) != 0) + printf("src_mac %s -> dst_mac %s type(%#x)\n", src_mac, dst_mac, mac_type); + + // sleep(1); + // usleep(5); + + switch (mac_type) + { + case 0x0800: + printf("-----ip 数据包-----\n"); + // 拆解IP数据报 + unsigned char *ip_buf = buf + 14; + // 读取IP首部长度: 单位是 4 字节 + unsigned char ip_head_len = (ip_buf[0] & 0x0f) * 4; + printf("IP数据报的首部长度: %d\n", ip_head_len); + + unsigned char ip_type = ip_buf[9]; // 协议类型 + // 读取源IP和目的IP + unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源IP + unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的IP + inet_ntop(AF_INET, (unsigned int *)(ip_buf + 12), src_ip, INET_ADDRSTRLEN); + inet_ntop(AF_INET, (unsigned int *)(ip_buf + 16), dst_ip, INET_ADDRSTRLEN); + printf("src_ip: %s -> dst_ip: %s \n", src_ip, dst_ip); + + if (ip_type == 1) + { + printf("\t------ICMP 数据报-----\n"); + } + else if (ip_type == 2) + { + printf("\t------IGMP 数据报-----\n"); + } + else if (ip_type == 6) + { + printf("\t------TCP 数据报-----\n"); + // 拆解TCP的数据报 + unsigned char *tcp_buf = ip_buf + ip_head_len; // 取出TCP的报文 + unsigned short src_port = ntohs(*((unsigned short *)(tcp_buf))); // 源端口 + unsigned short dst_port = ntohs(*((unsigned short *)(tcp_buf + 2))); // 目的端口 + printf("\tsrc_port: %d -> dst_port: %d\n", src_port, dst_port); + + // TCP 的数据报 + } + else if (ip_type == 17) + { + printf("\t------UDP 数据报-----\n"); + // 拆解UDP的数据报 + unsigned char *udp_buf = ip_buf + ip_head_len; // 取出UDP的报文 + unsigned short src_port = ntohs(*((unsigned short *)udp_buf)); + unsigned short dst_port = ntohs(*((unsigned short *)(udp_buf + 2))); + + printf("\tsrc_port: %d -> dst_port: %d\n", src_port, dst_port); + + // UDP 的数据报长度: 由首部+数据长度(偶数)组成 + unsigned short udp_buf_len = ntohs(*((unsigned short *)(udp_buf + 4))); // ntohs 用于大端转小端 + int udp_date_size = udp_buf_len - 8; + char udp_date[128] = ""; // UDP 数据部分 + strncpy(udp_date, udp_buf + 8, udp_buf_len - 8); + printf("\t\t %d -> %d data: %s\n", src_port, dst_port, udp_date); + } + + break; + case 0x0806: + printf("-----ARP 数据包-----\n"); + break; + case 0x8035: + printf("-----RARP 数据包-----\n"); + break; + } + } + + close(sock_fd); + + return 0; +} diff --git a/day6/n4.c b/day6/n4.c new file mode 100644 index 0000000..ac0c4be --- /dev/null +++ b/day6/n4.c @@ -0,0 +1,79 @@ +/*单播ARP应答*/ +#include +#include +#include +#include +#include +#include // ifreq +#include +#include // bzero +#include + +// 发送原始数据报 +ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name); + +ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name) +{ + // 1. 获取网络接口类型(通过网卡名查找网卡索引) + struct ifreq ether_req; + bzero(ðer_req, sizeof(ether_req)); + strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name + + if (ioctl(fd, SIOCGIFINDEX, ðer_req) == -1) + { + perror("ioctl"); + return -1; + } + + // 2. 选择发送数据的网络接口索引(选择合适的网卡索引) + struct sockaddr_ll sll; + bzero(&sll, sizeof(sll)); + sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue + + // 3. 发送数据 + ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll)); + return len; +} + +int main(int argc, char const *argv[]) +{ + // 创建原始套接字 + int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sock_fd < 0) + { + perror("raw socket"); + return -1; + } + + // 组ARP应答报文(如果是ARP欺骗,则源MAC为0x00,0x00,0x00,0x00,0x00,0x00) + uint32_t src_ip = inet_addr("10.12.156.204"); // 发送的 ip 地址 + uint32_t dst_ip = inet_addr("10.12.156.178"); // 点分十进制转换为数字字符串 + + unsigned char *src_ip_p = (unsigned char *)&src_ip; // src_ip 的字符类型指针 + unsigned char *dst_ip_p = (unsigned char *)&dst_ip; + + unsigned char buf[] = { + 0x00, 0x0c, 0x29, 0xf7, 0x81, 0x4c, /*目的MAC地址*/ + 0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /* 源MAC地址 */ + 0x08, 0x06, /* ARP帧类型 */ + 0x00, 0x01, /* 硬件类型 */ + 0x08, 0x00, /* 协议类型(IP协议0x0800) */ + 0x06, 0x04, /* 硬件地址长度(MAC地址长度) 和 协议地址长度(IP 地址长度) */ + 0x00, 0x02, /* OP操作类型(ARP应答 = 2) */ + 0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /* 发送端MAC地址 */ + src_ip_p[0], src_ip_p[1], src_ip_p[2], src_ip_p[3], /* 源(发送端) IP 地址 */ + 0x00, 0x0c, 0x29, 0xf7, 0x81, 0x4c, /*接收端MAC地址*/ + dst_ip_p[0], dst_ip_p[1], dst_ip_p[2], dst_ip_p[3] /* 接收端 IP 地址 */ + }; + + // 单播发送ARP应答 + ssize_t len = send_datapacket(sock_fd, buf, sizeof(buf), "ens38"); + if (len > 0) + { + printf("send arp success! \n"); + } + + close(sock_fd); + + return 0; +} diff --git a/day6/n5.c b/day6/n5.c new file mode 100644 index 0000000..7198eb8 --- /dev/null +++ b/day6/n5.c @@ -0,0 +1,141 @@ +/* +扫描所有局域网IP地址的MAC信息 +发ARP请求报文,通过for循环组成同一个网段的不同IP地址,发送出来,并接收响应的ARP报文信息 +*/ +#include +#include +#include +#include +#include +#include // ifreq +#include +#include // bzero +#include +#include +#include +#include +#include + +// 发送原始数据报 +ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name); + +void *recv_packetdata(void *arg) +{ + // 创建原始套接字 + int sock_fd = *((int *)arg); + + while (1) + { + // 接链接层的数据报文 + unsigned char buf[1518] = ""; + int len = recvfrom(sock_fd, buf, sizeof(buf), 0, NULL, NULL); + if (len < 18) + { + perror("recvfrom"); + continue; + } + + // 拆解MAC数据报文 + unsigned char dst_mac[18] = ""; + unsigned char src_mac[18] = ""; + unsigned short mac_type = ntohs(*((unsigned short *)(buf + 12))); + sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", + buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); + if (mac_type == 0x0806) // 当类型为ARP时 + { + printf("------ARP数据报-----\n"); + unsigned char src_ip[16] = ""; + unsigned char dst_ip[16] = ""; + unsigned short op = ntohs(*((unsigned short *)(buf + 20))); + if (op == 2) // 只显示ARP应答的数据 + { + // inet_ntop函数被用于将存储在buf + 28位置的二进制IPv4地址转换为字符串表示形式,并将结果存储在src_ip变量中。 + inet_ntop(AF_INET, (unsigned int *)(buf + 28), src_ip, 16); + inet_ntop(AF_INET, (unsigned int *)(buf + 38), dst_ip, 16); + printf("%s(%s) -> %s(%s)\n", src_mac, src_ip, dst_mac, dst_ip); + } + } + } +} + +int main(int argc, char const *argv[]) +{ + + // 创建原始套接字 // htons(ETH_P_ALL)的作用是将以太网协议号转换为网络字节序,以便在创建原始套接字时使用正确的协议号。 + int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sock_fd < 0) + { + perror("raw socket"); + return -1; + } + + // 创建接收数据报的线程 + pthread_t tid; + pthread_create(&tid, NULL, recv_packetdata, &sock_fd); + // pthread_detach(tid); + + // 组织ARP应答报文(如果是ARP欺骗,则源MAC地址可以修改为全0或修改为其他用于伪装的MAC地址) + uint32_t src_ip = inet_addr("10.12.156.204"); + // 扫描所有网内的IP的MAC地址 + for (int i = 150; i < 253; i++) + // for (int i = 2; i < 255; i++) + { + unsigned char dst_ip_[16] = ""; + sprintf(dst_ip_, "10.12.156.%d", i); + // inet_addr函数被用于将点分十进制表示的IPv4地址转换为32位无符号整数的网络字节序表示。 + uint32_t dst_ip = inet_addr(dst_ip_); + unsigned char *src_ip_pointer = (unsigned char *)&src_ip; // 定义源地址ip指针 + unsigned char *dst_ip_pointer = (unsigned char *)&dst_ip; + unsigned char buf[] = { + // 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 用于广播, 常用于扫描MAC地址 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*目标MAC*/ + 0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /*源MAC*/ + 0x08, 0x06, /*帧类型(ARP)*/ + 0x00, 0x01, /*硬件类型(以太网)*/ + 0x08, 0x00, /*协议类型(IP)*/ + 0x06, 0x04, /*硬件地址长度(6字节)和协议地址长度(4字节)*/ + 0x00, 0x01, /*操作类型(ARP请求)*/ + 0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /*发送方MAC*/ + src_ip_pointer[0], src_ip_pointer[1], src_ip_pointer[2], src_ip_pointer[3], /*发送方IP*/ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*目标MAC*/ + dst_ip_pointer[0], dst_ip_pointer[1], dst_ip_pointer[2], dst_ip_pointer[3] /*目标IP*/ + }; + + // 单播(发送ARP请求): 通过网卡名查找网卡索引, 选择合适的网卡索引, 发送数据 + ssize_t len = send_datapacket(sock_fd, buf, sizeof(buf), "ens38"); + if (len > 0) + { + printf("发送ARP应答报文成功\n"); + } + usleep(1000 * 1000); + } + + pthread_join(tid, NULL); + close(sock_fd); + return 0; +} + +ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name) +{ + // 1. 获取网络接口类型(通过网卡名查找网卡索引) + struct ifreq ether_req; + bzero(ðer_req, sizeof(ether_req)); + strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name + + if (ioctl(fd, SIOCGIFINDEX, ðer_req) == -1) + { + perror("ioctl"); + return -1; + } + + // 2. 选择发送数据的网络接口索引(选择合适的网卡索引) + struct sockaddr_ll sll; + bzero(&sll, sizeof(sll)); + sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue + + // 3. 发送数据 + ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll)); + return len; +} \ No newline at end of file diff --git a/day6/n6.c b/day6/n6.c new file mode 100644 index 0000000..3887b3e --- /dev/null +++ b/day6/n6.c @@ -0,0 +1,92 @@ +/* ARP欺骗-练习3 +实时响应ARP报文,将源MAC地址的全置0. +*/ + +#include // inet_addr +#include // in_addr +#include // ether_aton +#include // sockaddr_ll +#include // ioctl +#include // ifreq +#include // close +#include // bzero +#include // printf +#include // pthread_create +#include // open +#include // open + +// 发送原始数据报 +ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name); + +void *arp_packetdata_send(void *arg) +{ + // 创建原始套接字 + int sock_fd = *((int *)arg); + + while (1) + { + // 发送ARP欺骗应答报文 + unsigned char src_ip_pointer[] = {10, 12, 156, 204}; // 发送的 IP 地址 + unsigned char dst_ip_pointer[] = {10, 12, 156, 178}; // 目标 IP 地址 点分十进制转换为数字字符串 + unsigned char dst_mac[] = {0x00, 0xd8, 0x61, 0x03, 0x45, 0x65}; // 目标 MAC 地址 + unsigned char arp_buf[] = { + dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], // 目的MAC地址 + // 00:0c:29:85:cc:67 + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 源MAC地址 + 0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, // 源MAC地址 + 0x08, 0x06, // ARP帧类型 + 0x00, 0x01, // 硬件类型 + 0x08, 0x00, // 协议类型(IP协议0x0800) + 0x06, 0x04, // 硬件地址长度(MAC地址长度) 和 协议地址长度(IP 地址长度) + 0x00, 0x02, // 操作类型(ARP应答0x0002) + 0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, // 发送方MAC地址 + src_ip_pointer[0], src_ip_pointer[1], src_ip_pointer[2], src_ip_pointer[3], // 发送方IP地址 + dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], // 目的MAC地址 + dst_ip_pointer[0], dst_ip_pointer[1], dst_ip_pointer[2], dst_ip_pointer[3] // 目的IP地址 + }; + + // 单播发送ARP应答报文 + ssize_t len = send_datapacket(sock_fd, arp_buf, sizeof(arp_buf), "ens38"); // ens38 为网卡名 + } +} + +int main(int argc, char const *argv[]) +{ + // 创建原始套接字 + int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sock_fd < 0) + { + perror("raw socket"); + return -1; + } + + // 创建线程发送ARP欺骗应答报文 + pthread_t tid; + pthread_create(&tid, NULL, arp_packetdata_send, &sock_fd); + pthread_join(tid, NULL); + close(sock_fd); + return 0; +} + +ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name) +{ + // 1. 根据网卡名获取网卡索引 + struct ifreq ether_req; + bzero(ðer_req, sizeof(ether_req)); // 清空结构体 ether_req + strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name // 将网卡名复制到 ether_req.ifr_name 中 + // 通过网卡名查找网卡索引 SIOCGIFINDEX 为获取网卡索引 + if (ioctl(fd, SIOCGIFINDEX, ðer_req) == -1) + { + perror("ioctl"); + return -1; + } + + // 2. 选择发送数据的网络接口索引 + struct sockaddr_ll sll; + bzero(&sll, sizeof(sll)); // 清空结构体 sll + sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue // 选择发送数据的网络接口索引 + + // 3. 发送数据 + ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll)); + return len; +}