diff --git a/day6/homework/fake_feiqiu.c b/day6/homework/fake_feiqiu.c index 1de635f..3d57e7a 100644 --- a/day6/homework/fake_feiqiu.c +++ b/day6/homework/fake_feiqiu.c @@ -5,6 +5,14 @@ UDP -> 8 UDP 数据报数据部分 */ + +// 伪装飞秋数据报(UDP) +// 1. 伪装飞秋数据报的源IP和目的IP +// 2. 伪装飞秋数据报的源端口和目的端口 +// 3. 伪装飞秋数据报的校验和 +// 4. 伪装飞秋数据报的数据部分 +// 5. 伪装飞秋数据报的长度 + #include #include #include @@ -20,9 +28,14 @@ #include #include #include // system +#include // iconv, 用于转换编码 + +#include "fake_feiqiu_head.h" ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name); unsigned short checksum(unsigned short *buf, int len); +char *convertToUTF8(const char *str); // 将字符串转换为UTF-8编码 +char *convertToGB2312(const char *str); // 将字符串转换为GB2312编码 // 伪头部(UDP 校验时需要再 UDP 报文之间加上伪头部) typedef struct pseudo_udp_head_struct @@ -43,21 +56,11 @@ int main(int argc, char const *argv[]) perror("raw socket"); return -1; } - /* - // 网卡结构体 - struct ifreq ether_req; // 网卡接口请求结构体 - strncpy(ether_req.ifr_name, "ens34", IFNAMSIZ); // 指定网卡名字, IFNAMESIZ 是接口网卡的名字大小 - // 如果网卡不存在,返回错误,否则返回网卡接口索引 - if (ioctl(sock_fd, SIOCGIFINDEX, ðer_req) == -1) - { - perror("ioctl"); - return -1; - } - // 发送接口的结构体 - struct sockaddr_ll sll; // 网络层套接字地址结构体 - bzero(&sll, sizeof(sll)); - sll.sll_ifindex = ether_req.ifr_ifindex; // 将网卡的接口类型赋值给发送接口 */ + // 设置网卡名 + char eth_name[128] = ""; + printf("请输入要伪装的网卡名: "); + scanf("%s", eth_name); char sender_ip[128] = ""; printf("请输入要伪装的发送者IP: "); @@ -93,13 +96,6 @@ int main(int argc, char const *argv[]) unsigned char udp_buf[1500] = ""; // UDP 数据报 - // 伪装飞秋数据报(UDP) - // 1. 伪装飞秋数据报的源IP和目的IP - // 2. 伪装飞秋数据报的源端口和目的端口 - // 3. 伪装飞秋数据报的校验和 - // 4. 伪装飞秋数据报的数据部分 - // 5. 伪装飞秋数据报的长度 - // 伪装飞秋数据报的数据部分 // char msg_data[1024] = "1_lbt6_47#128#704D7B3F6397#0#0#0#4001#9:1694470508:chai:chai:32:hi liangzai"; char msg_data[1024] = ""; @@ -108,6 +104,7 @@ int main(int argc, char const *argv[]) // scanf("%s", say_what); fgets(say_what, sizeof(say_what), stdin); // 比 scanf 的优点是可以输入空格 say_what[strlen(say_what) - 1] = '\0'; // 去掉最后的换行符 + if (strcmp(say_what, "exit") == 0) { break; @@ -117,26 +114,10 @@ int main(int argc, char const *argv[]) system("clear"); continue; } -/* if (strncpy(say_what, "change", 6) == 0) - { - printf("请输入要伪装的发送者名字:"); - scanf("%s", sender_name); - printf("请输入要伪装的发送者电脑名字:"); - scanf("%s", sender_pc_name); - continue; - } - if (strncmp(say_what, "help", 4) == 0) - { - printf("请输入要发送的内容:\n"); - printf("1. 输入exit退出\n"); - printf("2. 输入clear清屏\n"); - printf("3. 输入change更改伪装信息\n"); - continue; - } */ - sprintf(msg_data, "1:%d:%s:%s:%d:%s", 123, sender_name, sender_pc_name, 32, say_what); + sprintf(msg_data, "1:%d:%s:%s:%d:%s", 123, convertToGB2312(sender_name), convertToGB2312(sender_pc_name), IPMSG_SENDMSG, convertToGB2312(say_what)); int msg_data_len = strlen(msg_data) + strlen(msg_data) % 2; // 整数补齐偶数位,strlen(msg_data)%2 : 偶数+0,奇数+1 - printf("msg_data_len = %d ---> %s\n", msg_data_len, msg_data); + printf("msg_data_len = %d ---> %s\n", msg_data_len, convertToUTF8(msg_data)); /* ---------------------组装 UDP 数据报的 UDP 首部--------------------- */ struct udphdr *udp_head = (struct udphdr *)(udp_buf + 14 + 20); // UDP 首部开始位置 @@ -151,8 +132,6 @@ int main(int argc, char const *argv[]) UDP 校验中的伪头部(pseudo header)是在计算 UDP 校验和时使用的辅助数据。伪头部包含了源 IP 地址、目的 IP 地址、协议类型(通常是 UDP)和 UDP 报文长度等信息。 在计算 UDP 校验和时,将伪头部和 UDP 报文的内容拼接在一起,然后计算校验和。这样做的目的是增加校验和的安全性,使其更具可靠性。 */ - // 196: 4c:e1:73:47:16:3a - // 158: e8:d8:d1:48:46:ae unsigned char pseudo_udp_buf[1056] = ""; // 伪头部 PSEUDO_UDP_HEAD *pseudo_udp_head = (PSEUDO_UDP_HEAD *)pseudo_udp_buf; @@ -195,7 +174,7 @@ int main(int argc, char const *argv[]) /* ---------------------发送数据--------------------- */ // int send_len = sendto(sock_fd, udp_buf, 14 + 20 + 8 + msg_data_len, 0, (struct sockaddr *)&sll, sizeof(sll)); - int send_len = send_datapacket(sock_fd, udp_buf, 14 + 20 + 8 + msg_data_len, "ens38"); + int send_len = send_datapacket(sock_fd, udp_buf, 14 + 20 + 8 + msg_data_len, eth_name); printf("send_len = %d\n", send_len); } @@ -246,4 +225,86 @@ unsigned short checksum(unsigned short *buf, int len) sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return ~sum; +} + +// 将字符串转换为UTF-8编码 +char *convertToUTF8(const char *str) +{ + // 输入字符串的长度 + size_t inlen = strlen(str); + + // 输出缓冲区的长度,假设为输入长度的3倍(UTF-8编码最多占用3个字节) + size_t outlen = inlen * 3; + + // 创建转换句柄 + iconv_t cd = iconv_open("UTF-8", "GB2312"); // 从 GB2312 转换为 UTF-8 + + // 分配输出缓冲区 + char *outbuf = (char *)malloc(outlen); + if (outbuf == NULL) + { + perror("Memory allocation failed"); + return NULL; + } + + // 进行转换 + char *inbuf = (char *)str; + char *outptr = outbuf; + + if (iconv(cd, &inbuf, &inlen, &outptr, &outlen) == (size_t)-1) + { + perror("Conversion failed"); + free(outbuf); + iconv_close(cd); + return NULL; + } + + // 关闭转换句柄 + iconv_close(cd); + + // 添加字符串结束符 + *outptr = '\0'; + + return outbuf; +} + +// 将字符串转换为GB2312编码 +char *convertToGB2312(const char *str) +{ + // 输入字符串的长度 + size_t inlen = strlen(str); + + // 输出缓冲区的长度,假设为输入长度的3倍(UTF-8编码最多占用3个字节) + size_t outlen = inlen * 3; + + // 创建转换句柄 + iconv_t cd = iconv_open("GB2312", "UTF-8"); // 从 UTF-8 转换为 GB2312 + + // 分配输出缓冲区 + char *outbuf = (char *)malloc(outlen); + if (outbuf == NULL) + { + perror("Memory allocation failed"); + return NULL; + } + + // 进行转换 + char *inbuf = (char *)str; + char *outptr = outbuf; + + if (iconv(cd, &inbuf, &inlen, &outptr, &outlen) == (size_t)-1) + { + perror("Conversion failed"); + free(outbuf); + iconv_close(cd); + return NULL; + } + + // 关闭转换句柄 + iconv_close(cd); + + // 添加字符串结束符 + *outptr = '\0'; + + return outbuf; } \ No newline at end of file diff --git a/day6/homework/fake_feiqiu_head.h b/day6/homework/fake_feiqiu_head.h new file mode 100644 index 0000000..77e404e --- /dev/null +++ b/day6/homework/fake_feiqiu_head.h @@ -0,0 +1,33 @@ +#ifndef __FAKE_FEIQIU_HEAD_H__ +#define __FAKE_FEIQIU_HEAD_H__ + +enum ipmsg_e +{ + IPMSG_NOOPERATION = 0x00000000, + + IPMSG_BR_ENTRY = 0x00000001, + IPMSG_BR_EXIT = 0x00000002, + IPMSG_ANSENTRY = 0x00000003, + IPMSG_BR_ABSENCE = 0x00000004, + + IPMSG_BR_ISGETLIST = 0x00000010, + IPMSG_OKGETLIST = 0x00000011, + IPMSG_GETLIST = 0x00000012, + IPMSG_ANSLIST = 0x00000013, + IPMSG_FILE_MTIME = 0x00000014, + IPMSG_FILE_CREATETIME = 0x00000016, + IPMSG_BR_ISGETLIST2 = 0x00000018, + + IPMSG_SENDMSG = 0x00000020, + IPMSG_RECVMSG = 0x00000021, + IPMSG_READMSG = 0x00000030, + IPMSG_DELMSG = 0x00000031, + + /* option for all command */ + IPMSG_ABSENCEOPT = 0x00000100, + IPMSG_SERVEROPT = 0x00000200, + IPMSG_DIALUPOPT = 0x00010000, + IPMSG_FILEATTACHOPT = 0x00200000 +}; + +#endif \ No newline at end of file