pcap용 헤더파일과 라이브러리 경로를 추가후 win32 콘솔에서 작성
///////////////////////// IP_Data.h /////////////////////////
#define ETH_ALEN 6 // 출발및 도착지 주소의 크기 정의
struct MEC_Ether_header
{
u_int8_t ether_dhost[ETH_ALEN]; // 도착지 이더넷 주소
u_int8_t ether_shost[ETH_ALEN]; // 출발지 이더넷 주소
u_int16_t ether_type; // 패킷 타입 ID 필드
};
#pragma pack(push,1)
struct MEC_Ip_header{
unsigned char ip_hl:4; // 헤더 길이
unsigned char ip_v:4; // 버전
unsigned char ip_tos:8; // 서비스 타입
u_short ip_len; // 전체길이
u_short ip_id; // 식별자
u_short ip_off; // 플래그, 오프셋 필드
u_int8_t ip_ttl; // TTL
u_int8_t ip_p; // 프로토콜
u_short ip_sum; // 체크섬
struct in_addr ip_src; // 출발지 IP주소
struct in_addr ip_dst; // 도착지 IP주소
};
#pragma pack(pop)
///////////////////////// main.c /////////////////////////
#include "pcap.h"
#include "remote-ext.h"
#include "IP_Data.h"
#pragma comment(lib,"Ws2_32.lib") // 라이브러리파일 수동 추가
#pragma comment(lib,"wpcap.lib") // 라이브러리파일 수동 추가
#define MY_PACKETTIME 1000 // 패킷 Timeout ms단위
//(0이면 패킷이들어올때까지 기다림)
void HexPrint( void * , u_int ); // 사용자정의 함수
int iCnt; // For문 계산용
int main()
{
pcap_if_t * alldevs; // 네트워크관련 모든 장치
pcap_if_t * devsTemp; // 장치출력을 위한 TEMP포인터
pcap_t * adhandle; // 사용할장치 핸들러
int inum; // 장치번호 선택 입력용
int i=0; // 장치번호 선택 출력용
int res;
char errbuf[PCAP_ERRBUF_SIZE]; // 에러를 위한 char *
char timestr[16]; // 시간출력을 위한 char *
const u_char * pkt_data; // 실제 모든 패킷
time_t local_tv_sec; // 시간 ms
struct tm * ltime; // 현재시간단위 구조체
struct pcap_pkthdr *header; // 시간, 길이를 가지고있는 구조체
struct MEC_Ether_header * pEth; // 이더넷 헤더 *
struct MEC_Ip_header * pIph; // IP헤더 *
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
// 전체 장치의 이름과 경로 획득
for(devsTemp=alldevs; NULL != devsTemp; devsTemp=devsTemp->next)
{
printf("%d. name [%s]\n", ++i, devsTemp->name);
if (devsTemp->description)
printf(" 랜카드 [%s]\n\n", devsTemp->description);
else
printf(" (No description available)\n");
}
if(i==0) // 연결된 장치가 없을때 종료
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return -1;
}
// 전체 장치의 이름과 경로 획득
printf("Enter the interface number (1-%d):",i);
scanf_s("%d", &inum); // 몇번 장치로부터 읽을껀지 입력받는다
if(inum < 1 || inum > i) // 장치번호 입력이 잘못되었을때 종료
{
printf("\nInterface number out of range.\n");
pcap_freealldevs(alldevs);
return -1;
}
// 장치선택
for(devsTemp=alldevs, i=0; i< inum-1 ;devsTemp=devsTemp->next, i++);
// 선택된 장치 열기
adhandle= pcap_open(devsTemp->name, // name of the device
1500, // 읽어들일때 최대 크기 (1500 == Ether)
PCAP_OPENFLAG_PROMISCUOUS, // (난잡한)모드 - 내컴퓨터 and 다른사람 컴퓨터
MY_PACKETTIME, // 패킷 TimeOut 설정
NULL, // authentication on the remote machine
errbuf // 열때 잘못되면 에러를 여기에 넣어준다
);
if ( adhandle == NULL) // 장치를 열지 못하면 종료
{
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", devsTemp->name);
pcap_freealldevs(alldevs);
return -1;
}
printf("\n[%s] 로부터 읽는중...\n", devsTemp->description); // "읽는중...." 출력
pcap_freealldevs(alldevs); // 장치 연후 필요가 없으므로 해제
/* 실제 패킷 캡처 */
// (연 장치핸들러, 시간및 길이 구조체, 실제 패킷)
res = pcap_next_ex(adhandle, &header, &pkt_data);
if(res <= 0) // 캡쳐한 패킷이 없으면 종료
{
printf("패킷을 얻지 못했습니다.\n");
printf("Error reading the packets: %s\n", pcap_geterr(adhandle));
return -1;
}
local_tv_sec = header->ts.tv_sec; // 캡쳐했을때의 시스템 시간
ltime=localtime(&local_tv_sec); // 현재의 시간으로 바꾼다
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); // 시, 분, 초로 바꾼다
// Micro Sec , len:( 건져올린 Data의 길이 ) 시간 출력
printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
// 이더넷 헤더를 구조체 포인터에 대입 (Eth 헤더 구조체)
pEth = (struct MEC_Ether_header *)pkt_data;
// 이더넷 헤더를 읽고난뒤의 주소 (Ip 헤더 구조체)
pIph = (struct MEC_Ip_header*)(pkt_data + sizeof(*pEth));
/* Eth 헤더 출력부 시작 */
printf("============================ETH HEADER==========================\n");
fprintf(stdout, "DESTINATION Physical Address - ["); // 도착지 Eth주소 출력
for(iCnt = 0 ; iCnt < 6 ; ++iCnt)
{
fprintf(stdout, "%02X:", pEth->ether_dhost[iCnt]);
}
fprintf(stdout, "\b]\t\t\n");
fprintf(stdout, "SOURCE Physical Address - ["); // 출발지 Eth주소 출력
for(iCnt = 0 ; iCnt < 6 ; ++iCnt)
{
fprintf(stdout, "%02X:", pEth->ether_shost[iCnt]);
}
fprintf(stdout, "\b]\n");
// 프로토콜 16진수
fprintf(stdout, "next protocal - [0x%04x] (", ntohs(pEth->ether_type));
// 프로토콜 형식 출력
switch(ntohs(pEth->ether_type))
{
case 0x0800:
fprintf(stdout, "IP) 입니다.\n");
break;
case 0x0200:
fprintf(stdout, "PUP) 입니다.\n");
fprintf(stdout, "해석하지못하여 프로그램을 종료합니다. -_-;\n");
return -100;
case 0x0860:
fprintf(stdout, "ARP) 입니다.\n");
fprintf(stdout, "해석하지못하여 프로그램을 종료합니다. -_-;\n");
return -100;
case 0x8035:
fprintf(stdout, "RARP) 입니다.\n");
fprintf(stdout, "해석하지못하여 프로그램을 종료합니다. -_-;\n");
return -100;
default:
fprintf(stdout,"...) 알수없는 형식입니다.\n");
fprintf(stdout, "해석하지못하여 프로그램을 종료합니다. -_-;\n");
return -100;
}
printf("================================================================\n\n");
/* Eth 헤더 출력부 끝 */
/* Ip 헤더 출력부 시작*/
printf("=============================IP HEADER===========================\n");
/* 버전표시 시작*/
fprintf(stdout, "VERS - [%d] ", pIph->ip_v);
switch(pIph->ip_v)
{
case 4:
fprintf(stdout, "(IPv4)");
break;
case 6:
fprintf(stdout, "(IPv6)");
break;
default:
fprintf(stdout, "(알수없는 버전)");
break;
}
printf("\n");
/* 버전표시 끝*/
if(20 <= ((pIph->ip_hl)*4) ) // 헤더의 길이 (5x4)Byte 20보다 클경우 출력
{
fprintf(stdout, "H.LEN - [%d Byte]\n", (pIph->ip_hl)*4);
}
else // 20보다 작을경우 종료
{
fprintf(stdout, "패킷이 잘못된거 같아서 프로그램을 종료합니다.\n");
return -100;
}
/*서비스 타입 체크 시작*/
fprintf(stdout, "SERVICE TYPE - [0x%X] (",pIph->ip_tos);
switch(pIph->ip_tos)
{
case 0x1E:
fprintf(stdout, "IPTOS_TOS_MASK");
case 0x10:
fprintf(stdout, "IPTOS_LOWDELAY");
break;
case 0x08:
fprintf(stdout, "IPTOS_THROUGHPUT");
break;
case 0x04:
fprintf(stdout, "IPTOS_RELIABILITY");
break;
case 0x02:
fprintf(stdout, "IPTOS_MINCOST");
break;
default:
fprintf(stdout, "BASE");
break;
}
fprintf(stdout,")\n");
/*서비스 타입 체크 끝*/
// 헤더 + Data의 전체길이
fprintf(stdout, "TOTAL LENGTH - [%d Byte]\n", pIph->ip_len);
// 식별 ID
fprintf(stdout, "IDENTIFICATION - [0x%X]\n", pIph->ip_id);
// Do Not Fragment
fprintf(stdout, "(Flag)Do not Fragment - ");
if( 0x4000 == ((ntohs(pIph->ip_off)) & 0x4000) )
{
fprintf(stdout, "[1] (해당 패킷을 폐기)");
}
else
{
fprintf(stdout, "[0] (정상 단편화된 패킷)");
}
printf("\n");
// More Fragment
fprintf(stdout, "(Flag)More Fragment - ");
if( 0x2000 == ((ntohs(pIph->ip_off)) & 0x2000) )
{
fprintf(stdout, "[1] (단편화된 패킷 더 있습니다.)");
}
else
{
fprintf(stdout, "[0] (마지막 패킷 입니다.)");
}
printf("\n");
// 단편화된 Data의 길이
fprintf(stdout, "FRAGMENT OFFSET - [%x Byte]\n", htons(0x1FFF & ntohs(pIph->ip_off)));
// Time To Live
fprintf(stdout, "TIME TO LIVE - [%d]\n", pIph->ip_ttl); // 오프셋
// 프로토콜
fprintf(stdout, "TYPE - ['");
switch(pIph->ip_p)
{
case 1:
fprintf(stdout, "ICMP");
break;
case 2:
fprintf(stdout, "IGMP");
break;
case 6:
fprintf(stdout, "TCP");
break;
case 17:
fprintf(stdout, "UDP");
break;
default:
fprintf(stdout, "아직 못배운");
break;
}
fprintf(stdout, "' 형식입니다.]\n");
// 체크섬 헤더값을 16비트 1's Complement 합 계산 후 결과값을 1's Complement로 저장
fprintf(stdout, "HEADER CHECKSUM - [%d]\n", pIph->ip_sum );
// 출발지 IP
fprintf(stdout, "SOURCE ADDRESS - [%s]\n", inet_ntoa(pIph->ip_src));
// 도착지 IP
fprintf(stdout, "DESTINATION ADDRESS - [%s]\n", inet_ntoa(pIph->ip_dst));
printf("=================================================================\n\n");
/* Ip 헤더 출력부 끝*/
// Hex값 출력을 위한 사용자 정의 함수
HexPrint( (void *)pkt_data , header->len);
if(0 == header->len)
{
printf("\n(error) 읽은 데이터가 없습니다...\n\n");
return -1;
}
return 0;
}
void HexPrint( void *Data, u_int len)
{
int iLin;
fprintf(stdout, "\n=================================================================================\n");
fprintf(stdout, "[ Addr ] 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | \n");
fprintf(stdout, "---------------------------------------------------------------------------------\n");
for(iLin = 0 ; iLin < len ; iLin+=16)
{
fprintf(stdout, "[%08x] ", iLin);
for(iCnt = 0 ; iCnt < 16 ; ++iCnt)
{
if(iCnt == 8)
{
fprintf(stdout, " ");
}
if((iCnt + iLin) < len)
{
fprintf(stdout, " %02X", * ( (u_char*)Data+iCnt + iLin) );
}
else
{
fprintf(stdout, " ");
}
}
printf(" | ");
for(iCnt = 0 ; iCnt < 16 ; ++iCnt)
{
if(iCnt == 8)
{
fprintf(stdout, " ");
}
if((iCnt + iLin) < len)
{
if( ((*((u_char*)Data+iCnt + iLin)) >= 33) && ((*((u_char*)Data+iCnt + iLin)) <= 126) )
{
fprintf(stdout, "%c", * ( (u_char*)Data+iCnt + iLin) );
}
else
{
printf(".");
}
}
else
{
printf(" ");
}
}
printf("\n");
}
fprintf(stdout, "=================================================================================\n\n");
}
SOURCE MADE BY SIGI
|