카테고리 없음

wincap을 이용한 패킷캡처 windows

컴공 2013. 6. 15. 20:12
반응형
//////////////////////////////////////////////////////////////////////////
// Product Date : 2009/09/18                                            //
// Author : (Last) Lee                                                  //
//          (First) Hyunbin                                             //
// comment : This Program is expression to Packet architecture~         //
//           by used to winpcap library.                                //
// 인지값 - void                                                        //
// 반환값 - void                                                        //
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// Preprocessor area
#include <pcap.h>
#include <pcap-bpf.h>
#include <protocol.h>

#pragma comment(lib,ws2_)

//////////////////////////////////////////////////////////////////////////
// Define area
#define INPUT // Pointer's direction
#define OUTPUT // Pointer's direction

#define ETH_ALEN 6                
#define ETHERTYPE_PUP       0x0200      /* Xerox PUP */
#define ETHERTYPE_IP        0x0800      /* IP */
#define ETHERTYPE_ARP       0x0806      /* Address resolution */
#define ETHERTYPE_REVARP    0x8035      /* Reverse ARP */

//////////////////////////////////////////////////////////////////////////
// Packet structure
typedef struct _Packet
{
const u_char * NProtocol; // Next Protocol
void (*Layer2)(INPUT void*);
void (*Layer3)(INPUT void*);
void (*Layer4)(INPUT void*);
}Packet;

//////////////////////////////////////////////////////////////////////////
// Function Prototype area
void Layer2_Ether(INPUT void * vP);
void Layer3_IP(INPUT void * vP);
void Layer3_ARP(INPUT void * vP);
void Layer3_REVARP(INPUT void * vP);
void Layer3_PUP(INPUT void * vP);
void PrintHexaNAscii(const unsigned char *buffer, int size);

//////////////////////////////////////////////////////////////////////////
// Product Date : 2009/09/18                                            //
// Author : (Last) Lee                                                  //
//          (First) Hyunbin                                             //
// comment : This function is main Function.                            //
// 인지값 - void                                                        //
// 반환값 - void                                                        //
//////////////////////////////////////////////////////////////////////////
int main()
{
    char errbuf[PCAP_ERRBUF_SIZE];
// 함수 원형 :  char* pcap_lookupdev
// 함수 설명 : pcap_open_live() 와 pcap_lookupnet() 에서 사용하기 위한 네트웍 디바이스에
// 대한 포인터를 되돌려준다. 성공할 경우 "eth0", "eth1" 과 같은 이름을
// 되돌려주며 실패할경우 0을 되돌려준다.
    char * spNetDevName = pcap_lookupdev(errbuf);
int iDataLink;
const u_char* ucData;
struct pcap_pkthdr stPInfo;
Packet stData; // Packet Information

pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
int iCnt = 0;
pcap_t *adhandle;
char packet_filter[] = "ip and udp";

// stData구조체를 0으로 초기화
memset(&stData, 0, sizeof(stData));

// 모든 네트워크 디바이스의 정보를 찾아서 3번째 인자에 넘겨준다.
if (-1 == pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf))
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
// 찾은 모든 device의 정보 출력한다.
for(d=alldevs; d; d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}

    // device를 찾지 못했다면
if(i==0)
    {
// 찾지 못했음을 알리고 종료한다.
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return -1;
}

    // 원하는 device를 선택한다.
printf("Enter the interface number (1-%d):",i);
scanf("%d", &inum);
    
// 허용된 범위 이외의 값을 입력하면
if(inum < 1 || inum > i)
{
printf("\nInterface number out of range.\n");
// device 디스크립터인 alldevs를 해제후 프로그램을 종료한다.
pcap_freealldevs(alldevs);
return -1;
    }

// 선택한 device로 이동한다.
    for(d=alldevs, iCnt=0; iCnt< inum-1 ;d=d->next, iCnt++);
    
// 선택한 device를 open한다.
    if ( NULL == (adhandle= pcap_open(d->name,  // name of the device
 65536,     // portion of the packet to capture. 
 // 65536 grants that the whole packet~
 // will be captured on all the MACs.
 PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
 1000,      // read timeout
 NULL,      // remote authentication
 errbuf     // error buffer
 )
 )
)
// 장치를 찾지 못했다면
{
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n");
        // device를 free시킨다. 
   pcap_freealldevs(alldevs);
return -1;
    }

// 마찬가지로 장치를 찾지 못했다면 
if(0 == adhandle) 
{
printf("Error : [%s]\n", errbuf);
return 101;
}
// 장치를 찾았다면 데이터 링크의 정보를 iDataLink에 입력시킨다.
else
{
// 함수 원형 : int pcap_datalink(pcap_t *p)
// 함수 설명 : link layer 타입을 되돌려준다(DLT_EN10MB 과 같은) 
iDataLink = pcap_datalink(adhandle);
}
// Datalink 정보를 출력
if(DLT_EN10MB == iDataLink)
{
printf("2Layter Type : [Ethernet 10Mb]\n");
stData.Layer2 = Layer2_Ether; // Regist Layer 2
}
else 
{
// 정보가 없다면 찾지 못했음을 알리고 종료한다.
printf("2Layter Type : Not Ethernet Type...\n");
return 0;
}

printf("======================================================\n");
printf("=============== Packet Capture start! ================\n");
printf("======================================================\n");

// main roop 구문
do{
/* 원형 : u_char *  pcap_next (pcap_t *p, struct pcap_pkthdr *h)
* 설명 : 다음 패킷의 포인터를 리턴한다. 
* 인자 : pcap_t *p : 패킷 캡쳐 descriptor 
*  struct pcap_pkthdr *h : 패킷의 정보를 가리키고 있는 포인터
*/
ucData = pcap_next(adhandle, &stPInfo);

printf("Cap length : [%d]\n", stPInfo.caplen);
printf("Length : [%d]\n", stPInfo.len);

// 패킷의 크기가 400이하이면 무시
if(400 > stPInfo.caplen) 
continue;
// 입력된 패킷의 정보를 PrintHexaNAscii함수를 사용하여
// 패킷의 크기만큼 출력한다.
PrintHexaNAscii(ucData, stPInfo.caplen);

printf("\n******************************************************\n");
printf("*************** Packet analysis Started **************\n");
printf("******************************************************\n");
stData.NProtocol = ucData;
stData.Layer2(&stData);
}while(stPInfo.caplen<400);

if(0 != stData.Layer3)
{
stData.Layer3(&stData);
}

// 모든 장치를 free시킨다.
pcap_freealldevs(alldevs);

return 0;
}


//////////////////////////////////////////////////////////////////////////
// Product Date : 2009/09/18                                            //
// Author : (Last) Lee                                                  //
//          (First) Hyunbin                                             //
// comment : This function is expression to IP Protocol in Layer3.      //
//           Layer3인 IP의 정보를 출력시는 함수.                        //
// 인지값 - INPUT(포인터의 방향을 표시)                                 //
//    void * vP (현재 패킷을 카리키는 포인터)                     //
// 반환값 - void                                                        //
//////////////////////////////////////////////////////////////////////////
void Layer3_IP(INPUT void * vP)
// vP : Packet struct Start Address
{
struct in_addr addr;
struct IP_HEADER* ihP
 = (struct IP_HEADER*)(((Packet *)vP)->NProtocol);

((Packet*)vP)->NProtocol =(const u_char *)(ihP+1); // Next Protocol Address

//u_char* temp = (u_char*)(&(ihP->ip_src));
printf("======================================================\n");
printf("============== Layer 3 : IP Information ==============\n");
printf("======================================================\n");
printf("==       Source          ->       Destination       ==\n");
addr.s_addr = ihP->src;
printf("==  %15s"
, inet_ntoa(addr)
);
addr.s_addr = ihP->dest;
printf("      ->    %15s      ==\n"
, inet_ntoa(addr)
);

printf("======================================================\n");
printf("== Version : IPv%1d                                   ==\n",
((ihP->x)>>4));
printf("== Header Langth : %1d                                ==\n",
((ihP->x)&0x0f));
printf("== Type of service : %-2X                             ==\n",
ihP->tos);
printf("== Total Length : %-6d                            ==\n",
ntohs(ihP->length));
printf("== Identification : %-6d                          ==\n",
ntohs(ihP->identifier));
printf("== Fragment offset filed : %-4X                     ==\n",
ntohs(ihP->fragment));
printf("== Time to live : %-3d                             ==\n",
ntohs(ihP->ttl));
printf("== Protocol : %-2d                                    ==\n",
ihP->protocol);
printf("== Checksum : %-8d                              ==\n",
ntohs(ihP->cksum));
printf("======================================================\n");

return;
}

// not used
void Layer3_ARP(INPUT void * vP)
// vP : Packet struct Start Address
{
return;
}

// not used
void Layer3_REVARP(INPUT void * vP)
// vP : Packet struct Start Address
{
return;
}

// not used
void Layer3_PUP(INPUT void * vP)
// vP : Packet struct Start Address
{
return;
}

//////////////////////////////////////////////////////////////////////////
// Product Date : 2009/09/18                                            //
// Author : (Last) Lee                                                  //
//          (First) Hyunbin                                             //
// comment : This function is expression to Ethernet Protocol in Layer2.//
//           Layer2인 Ethernet의 정보를 출력시는 함수                   //
// 인지값 - INPUT(포인터의 방향을 표시)                                 //
//    void * vP (현재 패킷을 카리키는 포인터)                     //
// 반환값 - void                                                        //
//////////////////////////////////////////////////////////////////////////
void Layer2_Ether(INPUT void * vP)
{
struct ETHERNET_FRAME* ehP
= (struct ETHERNET_FRAME*)(((Packet*)vP)->NProtocol);
((Packet*)vP)->NProtocol =(const u_char *)(ehP+1); // Next Protocol Address

printf("======================================================\n");
printf("=========== Layer 2 :  Ethernet Information ==========\n");
printf("======================================================\n");
printf("==       Source          ->       Destination       ==\n");
printf("==   %02X:%02X:%02X:%02X:%02X:%02X   "
"->    %02X:%02X:%02X:%02X:%02X:%02X    ==\n",
ehP->Source[0],
ehP->Source[1],
ehP->Source[2],
ehP->Source[3],
ehP->Source[4],
ehP->Source[5],

ehP->Destination[0],
ehP->Destination[1],
ehP->Destination[2],
ehP->Destination[3],
ehP->Destination[4],
ehP->Destination[5]
);

switch(ntohs(ehP->FrameType))
{
case ETHERTYPE_IP:
((Packet*)vP)->Layer3 = Layer3_IP;
break;
case ETHERTYPE_ARP:
((Packet*)vP)->Layer3 = Layer3_ARP;
break;
case ETHERTYPE_REVARP:
((Packet*)vP)->Layer3 = Layer3_REVARP;
break;
case ETHERTYPE_PUP:
((Packet*)vP)->Layer3 = Layer3_PUP;
break;
default:
break;
}
printf("======================================================\n");
return;
}

//////////////////////////////////////////////////////////////////////////
// Product Date : 2009/09/18                                            //
// Author : (Last) Lee                                                  //
//          (First) Hyunbin                                             //
// comment : This function is printed hexa and ascii code               //
//           입력되는 버퍼의 내용을 hexa(16진수)와                      //
//           아스키 코드(ascii code)로 출력 시키는 함수                 //
// 인지값 - INPUT : 포인터의 방향을 표시, 즉 입력이란 의미              //
//    const : 입력된 버퍼의 값은 함수 실행 도중에 변경되지 않음   //
//          u_char *buffer : unsigned char pointer 형 변수 buffer       //
// 반환값 - void                                                        //
//////////////////////////////////////////////////////////////////////////
void PrintHexaNAscii(INPUT const u_char *buffer, int size)
{
int loop_temp = 0;
int counter = 0;

printf("=======================================================================\n");
printf("Address 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D");
printf(" 0E 0F 123456789ABCDEF\n");
printf("=======================================================================\n");

counter = 0;

// 표현되는 크기의 제한
if(1200 < size)
size = 1200;

while(counter < size)
{
printf("0x%04X ",counter);
loop_temp = 0;
while(loop_temp < 16)
{
printf("%02X ", *buffer);
++buffer;
++loop_temp;
}
buffer = buffer -16;
loop_temp = 0;
while(loop_temp < 16)
{
// 아스키 코드로 인식되는 범위 이외의 값은 '.'으로 처리
if(31 > *buffer || 127 <= *buffer)
{
putchar('.');
}
else
{
putchar(*buffer);
}
++buffer;
++loop_temp;
}
counter = counter + loop_temp;
putchar('\n');
}
return;
}
반응형