본문 바로가기

카테고리 없음

네트워크

#include <sys/time.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <pcap/pcap.h>

#define PROMISCUOUS 1
#define NONPROMISCUOUS 0
#define TCPHEADERSIZE 6*4

// IP 헤더 구조체
struct ip *iph;
// TCP 헤더 구조체
struct tcphdr *tcph;

// 패킷을 받아들일경우 이 함수를 호출한다. 
// packet 가 받아들인 패킷이다.
void callback(u_char *useless, const struct pcap_pkthdr *pkthdr,
     const u_char *packet)
{
 struct ether_header *ep;
 unsigned short ether_type;

 char *uname = NULL;
 char *pass = NULL;
 char buf[80];

 // 이더넷 헤더를 가져온다.
 ep = (struct ether_header *)packet;


 // IP 헤더를 가져오기 위해서
 // 이더넷 헤더 크기만큼 offset 한다.
 packet += sizeof(struct ether_header);
 ether_type = ntohs(ep->ether_type);

 // Network Layer 의 Protocol 타입을 알아낸다. 
 // 만약 IP 프로토콜을 사용한다면
 // IP 정보를 얻어온다. 
 if (ether_type == ETHERTYPE_IP)
 {
  iph = (struct ip *)packet;
  if (iph->ip_p == IPPROTO_TCP)
  {
   tcph = (struct tcp *)(packet + iph->ip_hl * 4);
  }

  memset(buf, 0x00, 80);

  // 유저 데이타를 얻어오기 위해서
  // IP, TCP, Ethernet 헤더 크기만큼 offset 한다.
  packet += (iph->ip_hl * 4)+TCPHEADERSIZE+(sizeof(struct ether_header));

  // 패킷에 ID와 password 관련 문자열을 포함하는지 확인한다. 
 /* if ( ((uname = strstr(packet, "uname=")) != NULL)//  패킷받은것 중에 "안의 내용(uname=) "중에 포함되있는 문자가 있으면 포인터를 리턴
   && ((pass = strstr(packet, "&pass=")) != NULL))
  {
   // 헤더 정보를 출력한후
   printf("HEADER INFO\n");
   printf("Src Address : %s\n", inet_ntoa(iph->ip_src));
   printf("Dst Address : %s\n", inet_ntoa(iph->ip_dst));

   printf("Src Port    : %d\n" , ntohs(tcph->source));
   printf("Dst Port    : %d\n" , ntohs(tcph->dest));

   // 문자열에서 필요한 정보 즉 ID와 Password 만을
   // 추출해 낸다.  
   strncpy(buf, uname+6, strstr(uname, "&") - (uname + 6));
   printf("Uname : <%s>\n", buf);
   memset(buf, 0x00, 80);
   strncpy(buf, pass+6, strstr(pass+6, "&") - (pass + 6));
   printf("Pass  : <%s>\n", buf);
   printf("======================\n\n");
  }*/
 }
}

int main(int argc, char **argv)
{
 char *dev;
 char *net;
 char *mask;

 bpf_u_int32 netp;
 bpf_u_int32 maskp;
 char errbuf[PCAP_ERRBUF_SIZE];
 int ret;
 struct pcap_pkthdr hdr;
 struct in_addr net_addr, mask_addr;

 struct bpf_program fp;

 pcap_t *pcd;  // packet capture descriptor

 //  디바이스 이름을 얻어온다.
 dev = pcap_lookupdev(errbuf);
 if (dev == NULL)
 {
  printf("%s\n", errbuf);
  exit(1);
 }
 printf("DEV : %s\n", dev);
 // 디바이스에 대한 네트웍 정보를 얻어온다. 
 ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
 if (ret == -1)
 {
  printf("%s\n", errbuf);
  exit(1);
 }

 // 네트웍 정보를 사람이 보기 쉽도록
 // 변환한다음 출력한다.
 net_addr.s_addr = netp;
 net = inet_ntoa(net_addr);
 printf("NET : %s\n", net);

 mask_addr.s_addr = maskp;
 mask = inet_ntoa(mask_addr);
 printf("MSK : %s\n", mask);
 printf("=======================\n");

 // 디바이스에 대한 packet capture descriptor
 // 를 얻어온다. 
 pcd = pcap_open_live(dev, BUFSIZ,  NONPROMISCUOUS, -1, errbuf);
 if (pcd == NULL)
 {
  printf("%s\n", errbuf);
  exit(1);
 }

 // 컴파일 옵션을 준다. 
 if (pcap_compile(pcd, &fp, argv[2], 0, netp) == -1)//  argv[2]>>>port 80
 {
  printf("compile error\n");
  exit(1);
 }
 // 컴파일 옵션대로 필터룰을 세팅한다.
 if (pcap_setfilter(pcd, &fp) == -1)
 {
  printf("setfilter error\n");
  exit(0);
 }

 // 지정된 횟수만큼 패킷캡쳐를 한다.
 // pcap_setfilter 을 통과한 패킷에 대해서
 // callback 함수를 호출한다.
 pcap_loop(pcd, atoi(argv[1]), callback, NULL);
}// atoi(argv[1]콜백함수 몇번 실행할 것인지 결정