阅读:4020回复:10
raw socket 非驱动方式 监听本机数据包
raw socket 非驱动方式 监听本机数据
|
|
|
沙发#
发布于:2007-04-18 10:29
Windows 版本
一个例子可以看看 步骤: 1. 把网卡置于混杂模式。 2. 捕获数据包。 3. 分析数据包。 注:下面的源代码取至Chad Renfro的<< Basic Packet-Sniffer Construction from the Ground Up>>一文中 /************************Tcp_sniff_2.c********************/ 1.#include 2.#include 3.#include 4.#include 5.#include 6.#include 7.#include 8.#include 9.#include "headers.h" #define INTERFACE "eth0" /*Prototype area*/ 10.int Open_Raw_Socket(void); 11.int Set_Promisc(char *interface, int sock); 12.int main() { 13.int sock, bytes_recieved, fromlen; 14.char buffer[65535]; 15.struct sockaddr_in from; 16.struct ip *ip; 17.struct tcp *tcp; 18.sock = Open_Raw_Socket(); 19. Set_Promisc(INTERFACE, sock); 20. while(1) 22. { 23. fromlen = sizeof from; 24. bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen); 25. printf("\nBytes received ::: %5d\n",bytes_recieved); 26. printf("Source address ::: %s\n",inet_ntoa(from.sin_addr)); 27. ip = (struct ip *)buffer; /*See if this is a TCP packet*/ 28. if(ip->ip_protocol == 6) { 29. printf("IP header length ::: %d\n",ip->ip_length); 30. printf("Protocol ::: %d\n",ip->ip_protocol); 31. tcp = (struct tcp *)(buffer + (4*ip->ip_length)); 32. printf("Source port ::: %d\n",ntohs(tcp->tcp_source_port)); 33. printf("Dest port ::: %d\n",ntohs(tcp->tcp_dest_port)); 34. } 35. } 36.} 37.int Open_Raw_Socket() { 38. int sock; 39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { /*Then the socket was not created properly and must die*/ 40. perror("The raw socket was not created"); 41. exit(0); 42. }; 43. return(sock); 44. } 45.int Set_Promisc(char *interface, int sock ) { 46. struct ifreq ifr; 47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1); 48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) { /*Could not retrieve flags for the interface*/ 49. perror("Could not retrive flags for the interface"); 50. exit(0); 51. } 52. printf("The interface is ::: %s\n", interface); 53. perror("Retrieved flags from interface successfully"); 54. ifr.ifr_flags |= IFF_PROMISC; 55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) { /*Could not set the flags on the interface */ 56. perror("Could not set the PROMISC flag:"); 57. exit(0); 58. } 59. printf("Setting interface ::: %s ::: to promisc", interface); 60. return(0); 61. } /***********************EOF**********************************/ 上面这段程序中有很详细的注解,不过我想还是有必要说一说,首先第10行--int Open_Raw_Socket(void); 是我们的自定义函数,具体内容如下: 37.int Open_Raw_Socket() { 38. int sock; 39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { /*Then the socket was not created properly and must die*/ 40. perror("The raw socket was not created"); 41. exit(0); 42. }; 43. return(sock); 44. } 第39行 if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { 这里我们调用了socket函数,使创建了了一个原始套接口,使之收到TCP/IP信息包。 接下来第11行-int Set_Promisc(char *interface, int sock),这也是我们的自定义函数,目的是把网卡置于混杂模式,具体内容如下: 45.int Set_Promisc(char *interface, int sock ) { 46. struct ifreq ifr; 47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1); 48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) { /*Could not retrieve flags for the interface*/ 49. perror("Could not retrive flags for the interface"); 50. exit(0); 51. } 52. printf("The interface is ::: %s\n", interface); 53. perror("Retrieved flags from interface successfully"); 54. ifr.ifr_flags |= IFF_PROMISC; 55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) { /*Could not set the flags on the interface */ 56. perror("Could not set the PROMISC flag:"); 57. exit(0); 58. } 59. printf("Setting interface ::: %s ::: to promisc", interface); 60. return(0); 61. } 首先 struct ifreq ifr; 定一了一个ifrreg的结构ifr,接下来 strncpy(ifr.ifr_name, interface,strnlen(interface)+1);,就是把我们网络设备的名字填充到ifr结构中,在这里 #define INTERFACE "eth0" ,让我们再往下看,ioctl(sock, SIOCGIFFLAGS, &ifr),SIOCGIFFLAGS请求表示需要获取接口标志,现在到了第54行,在我们成功的获取接口标志后把他设置成混杂模式,ifr.ifr_flags |= IFF_PROMISC;ioctl (sock, SIOCSIFFLAGS, &ifr)。OK,现在我们所说的第一步已经完成--------把网卡置于混杂模式。 现在进入第二步,捕获数据包。从第20行开始,我们进入了一个死循环,while(1),在第24行,recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen),这个函数要做的就是接收数据,冰把接收到的数据放入buffer中。就是这么简单,已经完成了我们要捕获数据包的任务。 到了第三步,分析数据包。27行,ip = (struct ip *)buffer,使我们在头文件中的IP结构对应于所接收到的数据,接下来判断在网络层中是否使用的是TCP协议,if(ip->ip_protocol == 6) ,如果答案是,tcp信息包从整个IP/TCP包 buffer + (4*ip->ip_length) 地址处开始,所以31行 tcp = (struct tcp *)(buffer + (4*ip->ip_length)),然后对应结构把你所需要的信息输出。 /*************************headers.h**************************/ /*structure of an ip header*/ struct ip { unsigned int ip_length:4; /*little-endian*/ unsigned int ip_version:4; unsigned char ip_tos; unsigned short ip_total_length; unsigned short ip_id; unsigned short ip_flags; unsigned char ip_ttl; unsigned char ip_protocol; unsigned short ip_cksum; unsigned int ip_source; unsigned int ip_dest; }; /* Structure of a TCP header */ struct tcp { unsigned short tcp_source_port; unsigned short tcp_dest_port; unsigned int tcp_seqno; unsigned int tcp_ackno; unsigned int tcp_res1:4, /*little-endian*/ tcp_hlen:4, tcp_fin:1, tcp_syn:1, tcp_rst:1, tcp_psh:1, tcp_ack:1, tcp_urg:1, tcp_res2:2; unsigned short tcp_winsize; unsigned short tcp_cksum; unsigned short tcp_urgent; }; /*********************EOF***********************************/ |
|
|
驱动小牛
![]() |
板凳#
发布于:2007-04-18 20:15
![]() |
地板#
发布于:2007-04-23 12:07
windows版本的?我怎么看象是linux源码
|
|
地下室#
发布于:2007-04-23 12:40
再来一份windows版本的
再来一份windows版本的 |
|
|
5楼#
发布于:2007-04-23 17:24
来一份可以编译通过的代码,适用于win2k /xp
|
|
|
6楼#
发布于:2007-04-24 10:03
收下
|
|
7楼#
发布于:2007-04-24 14:50
xp那份还不够raw,只能收到IP层以上的包。。。看来要发送arp之类的包还得写驱动,麻烦
![]() |
|
8楼#
发布于:2007-04-24 15:05
raw socket只是ip层及以上的,arp是和ip一层的东东,铁定不行...
|
|
|
9楼#
发布于:2007-12-18 17:32
这个windows版本的,貌似没有将网卡设为混杂模式吧。
将网卡设为混杂模式什么概念呢?我的理解是在同一局域网内,凡是经过本机网卡的数据包,不管MAC地址是不是自己的都接收过来。 可这个只能监听到本机发出或接入的数据吧。 有两点缺陷:1、MAC非本机地址的不能监听。 2、本机发往本机的不能监听(似乎没经过IP层) |
|
10楼#
发布于:2008-01-14 16:12
请问这种方式可以获取到一些木马或者rootkit的隐藏通信信息么?
|
|