linux或者Android使用内核抓包c语言程序
本文连接:https://i.cnblogs.com/posts/edit;postId=14928858
参考程序:http://www.nsfocus.net/index.php?act=magazine&do=view&mid=1797
设置包过滤参考:https://www.kernel.org/doc/Documentation/networking/filter.txt
完整程序 ioctl.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <linux/in.h> #include <linux/if_ether.h> #include <net/if.h> #include <linux/filter.h> #include <sys/ioctl.h> #include <arpa/inet.h> int main(int argc, char **argv) { int sock, n; char buffer[2048]; unsigned char *iphead, *ethhead; struct ifreq ethreq; //$tcpdump -i eth0 tcp src port 502 -dd # 设置过滤 可以通过此命令获取c程序片段,复制到下面 struct sock_filter BPF_code[] = { {0x28, 0, 0, 0x0000000c}, {0x15, 0, 6, 0x000086dd}, {0x30, 0, 0, 0x00000014}, {0x15, 0, 15, 0x00000006}, {0x28, 0, 0, 0x00000036}, {0x15, 12, 0, 0x000001f6}, {0x28, 0, 0, 0x00000038}, {0x15, 10, 11, 0x000001f6}, {0x15, 0, 10, 0x00000800}, {0x30, 0, 0, 0x00000017}, {0x15, 0, 8, 0x00000006}, {0x28, 0, 0, 0x00000014}, {0x45, 6, 0, 0x00001fff}, {0xb1, 0, 0, 0x0000000e}, {0x48, 0, 0, 0x0000000e}, {0x15, 2, 0, 0x000001f6}, {0x48, 0, 0, 0x00000010}, {0x15, 0, 1, 0x000001f6}, {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000}}; struct sock_fprog Filter; Filter.len = sizeof(BPF_code) / sizeof(BPF_code[0]); Filter.filter = BPF_code; if ((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0) { perror("socket"); exit(1); } /* Set the network card in promiscuos mode */ strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ); if (ioctl(sock, SIOCGIFFLAGS, ðreq) == -1) { perror("ioctl"); close(sock); exit(1); } ethreq.ifr_flags |= IFF_PROMISC; if (ioctl(sock, SIOCSIFFLAGS, ðreq) == -1) { perror("ioctl"); close(sock); exit(1); } /* Attach the filter to the socket */ if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter)) < 0) { perror("setsockopt"); close(sock); exit(1); } while (1) { printf("----------\n"); n = recvfrom(sock, buffer, 2048, 0, NULL, NULL); printf("%d bytes read\n", n); /* Check to see if the packet contains at least * complete Ethernet (14), IP (20) and TCP/UDP * (8) headers. */ if (n < 42) { perror("recvfrom():"); printf("Incomplete packet (errno is %d)\n", errno); close(sock); exit(0); } ethhead = buffer; printf("Ethernet MAC: [%02X:%02X:%02X:%02X:%02X:%02X]", ethhead[0], ethhead[1], ethhead[2], ethhead[3], ethhead[4], ethhead[5]); printf("->[%02X:%02X:%02X:%02X:%02X:%02X]", ethhead[6], ethhead[7], ethhead[8], ethhead[9], ethhead[10], ethhead[11]); printf(" type[%04x]\n", (ntohs(ethhead[12] | ethhead[13] << 8))); iphead = buffer + 14; /* Skip Ethernet header */ if (*iphead == 0x45) { /* Double check for IPv4 * and no options present */ printf("Layer-4 protocol %d\n", iphead[9]); printf("Version: %d HeaderLen: %d[%d] ", (*iphead >> 4), (*iphead & 0x0f), (*iphead & 0x0f) * 4); printf("TotalLen %d\n", (iphead[2] << 8 | iphead[3])); printf("IP [%d.%d.%d.%d:%d]", iphead[12], iphead[13], iphead[14], iphead[15], (iphead[20] << 8 | iphead[21])); printf("->[%d.%d.%d.%d:%d]\n", iphead[16], iphead[17], iphead[18], iphead[19], (iphead[22] << 8 | iphead[23])); for (int i = 0; i < n; ++i) { printf(" %02x", buffer[i] & 0xff); if ((i + 1) % 16 == 0) printf("\n"); } printf("\n"); } } }
测试
如果在Android编译,需要安卓gcc,这个apk下载后使用压缩软件winrar打开,将gcc.zip复制出来解压到/data(似乎这里读写权限没有问题)目录下(我的目录是/data/ruphy)并设置环境变量:
export PATH=$PATH:/data/ruphy/gcc/bin:/data/ruphy/gcc/arm-linux-androideabi/bin:/data/ruphy/gcc/libexec
雷电模拟器开启终端,使用gcc编译ioctl.c为ioctl.o可执行文件并执行启动抓包
在Linux使用nc开启一个tcp服务,也可以不需要,因为模拟器可以上网,随便产生tcp连接即可
然后在模拟器使用telnet连接服务并通信