C++ 이용한포트스캔 Winpcap 이용기존수업시간 Client, BasicDump 코드이용 제출일 2016, 06, 01 전공사이버경찰학과 과목네트워크보안프로그래밍학번 10121702 담당교수소길자이름김주명
목차 목차포트스캔코드포트스캔결과포트스캔탐지코드포트스캔탐지결과 참조 02 03 05 06 11 12 2
포트스캔코드 #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") typedef struct OpenPort int port; OpenPort *next; OpenPort; // 링크드구조선언 void error_proc(); // 에러구문 int main(int argc, char* argv[]) WSADATA wsa; SOCKET clntsd; SOCKADDR_IN clntaddr; // 각종소켓관련변수선언 char address[20]; int start_port = 0; int end_port = 65535; // 시작과끝을정해주고, 주소를저장할변수선언 OpenPort *openportlist = (OpenPort *)malloc(sizeof(openport)); OpenPort *openportnodetail = openportlist; // 링크리스트를위한동적메모리할당과앞부분와끝부분을선언 FILE *file = fopen("openedportlist.txt","wt"); // 파일로저장하기위한선언 printf(" 포트스캔할서버주소를입력하세요. : "); scanf("%s",address); printf(" 시작할포트스캔번호를입력하시오. : "); scanf(" %d", &start_port); printf(" 마지막포트스캔번호를입력하시오. : "); scanf(" %d", &end_port); 3
int num=0; for(num=start_port;num<=end_port;num++) // 시작부터끝까지포트스캔 if(wsastartup(makeword(2,2), &wsa)!= 0) error_proc(); clntsd = socket(af_inet, SOCK_STREAM, 0); if(clntsd == INVALID_SOCKET) error_proc(); // 에러판단 ZeroMemory(&clntAddr,sizeof(clntAddr)); clntaddr.sin_family = AF_INET; clntaddr.sin_port = htons(num); clntaddr.sin_addr.s_addr = inet_addr(address); // 입력한주소값으로소켓연결 if (connect(clntsd, (SOCKADDR *)&clntaddr, sizeof(clntaddr)) == SOCKET_ERROR) printf("[ ]%d 포트닫힘 \n", num); else printf("[ ]%d 포트열림 \n", num); fprintf(file,"[ ]%d 포트열림 \n", num); // 열린포트파일로저장 OpenPort *openedportnode = (OpenPort *)malloc(sizeof(openport)); openedportnode->port = num; openedportnode->next = NULL; openportnodetail->next = openedportnode; openportnodetail = openportnodetail->next; // 포트가열려있으면, 끝링크의항목에 Next 추가시키고 // 끝링크는다시해당항목으로이동 closesocket(clntsd); WSACleanup(); fclose(file); void error_proc() fprintf(stderr,"error: %d \n", WSAGetLastError()); exit(1); 4
포트스캔결과 포트스캔구간 : 443 445 열린포트 OpenedPostList.txt 파일로저장 5
포트스캔탐지코드 #include "stdafx.h" #include "pcap.h" #include <WinSock2.h> #include <stdio.h> #include <string.h> typedef struct ip_header u_char ihl:4; // 헤더길이 * 4 u_char ver:4; // IPv4 or IPv6 u_char tos; // 서비스종류 u_short tlength; // 헤더길이 + 데이터길이 u_short id; // 분할조각의 identification 17:UDP) u_short flag_offset; // 분할정보 + 분할순서 u_char ttl; // TTL(Time to live) u_char protocol; // 다음에올프로토콜종류 (1:ICMP 2:IGMP 6:TCP u_short cheksum; // 헤더의오류검증 u_char saddr[4]; // 보내는 IP u_char daddr[4]; // 받는 IP u_int op_pad; // option + padding iph; typedef struct TCPHeader u_short SourcePort; u_short DestPort; u_int SeqNum; u_int AckNum; u_char TCPlength; u_char flags; u_short WinSize; u_short CheckSum; u_short UrgentPointer; TCPHeader; // TCP 헤더선언 typedef struct visitlist u_char SenderIP[4]; int port; visitlist* next; visitlist* past; visitlist; visitlist *headlink=null, *visitlink = NULL, *taillink = NULL; void packet_handler(u_char *param, const struct pcap_pkthdr *h, const u_char 6
*data); int checkscan(visitlist *List); int main() char packet_filter[] = "tcp"; struct bpf_program fcode; pcap_if_t *aldevs; pcap_if_t *item; pcap_t *lancard; int inum; int i=0; char errbuf[pcap_errbuf_size]; /* 패킷캡쳐할때필터링할조건 */ u_int netmask; if(pcap_findalldevs(&aldevs, errbuf) == -1) // 디바이스검색 printf("error in pcap_findalldevs : %s\n", errbuf); up: int count=0; for(item=aldevs;item!=null;item=item->next) printf(" \n"); printf("** <%d 번장치 > **\n", count); printf(" 어댑터정보 : %s \n", item->name); printf(" 어댑터이름 : %s \n", item->description); printf(" \n"); count++; item=aldevs; printf(" 네트워크장치선택 : "); int choice; scanf_s("%d", &choice, 10); system("cls"); if(choice > count-1) printf(" \n" ); printf(" < The Device dose not exist. Please Try Again. > \n"); ); printf(" \n" goto up; 7
for(int count=0;count<choice;count++) item=item->next; printf("user select : %s \n", item->name ); lancard=pcap_open_live(item->name,65536,0,1000,errbuf); /* 패킷을필터링하는정보추가 */ netmask= 0xffffff; if(pcap_compile(lancard, &fcode, packet_filter, 1, netmask) < 0 ) fprintf(stderr, "\nunable to compile the packet filter. Check the syntax.\n"); //Free the device list pcap_freealldevs(aldevs); return -1; // 필터적용 if(pcap_setfilter(lancard, &fcode) < 0 ) fprintf(stderr,"\nerror setting the filter.\n"); //Free the device list pcap_freealldevs(aldevs); return -1; pcap_loop(lancard,0,packet_handler,null); void packet_handler(u_char *param, const struct pcap_pkthdr *h, const u_char *data) // 링크리스트구조를위해앞과뒤부분을미리선언후사용한다. iph *ih; ih = (iph *)(data+14); // IP 헤더선언 if(ih->protocol == 6) TCPHeader *TCP; TCP = (TCPHeader *)(((u_char*)ih)+(ih->ihl*4)); //IP 헤더시작위치 + ip 헤더길이 >saddr[count]; if(headlink == NULL) visitlink = (visitlist *)malloc(sizeof(visitlist)); int count = 0; for (count = 0; count < 4;count++) visitlink->senderip[count] = ih- 8
visitlink->port = ntohs(tcp->destport)-1; visitlink->next = NULL; headlink = visitlink; taillink = visitlink; printf("[%d - X]\n", visitlink->port); 경우 else if (headlink->next!= NULL) // 만일이전에통신한포트와다른포트로통신이될 if (ntohs(tcp->destport)-1!= taillink->port) visitlink = (visitlist *)malloc(sizeof(visitlist)); int count = 0; for (count = 0; count < 4; count++) visitlink->senderip[count] = ih- >saddr[count]; visitlink->port = ntohs(tcp->destport)-1; visitlink->next = NULL; visitlink->past = taillink; taillink->next = visitlink; taillink = visitlink; printf("[%d - %d]\n", visitlink->past->port, visitlink->port); 검사하기시작합니다. // 이때부터 3 회이상통신이므로통신을 checkscan(headlink); else if (ntohs(tcp->destport) - 1!= taillink->port) visitlink = (visitlist *)malloc(sizeof(visitlist)); int count = 0; for (count = 0; count < 4; count++) visitlink->senderip[count] = ih- >saddr[count]; visitlink->port = ntohs(tcp->destport) - 1; visitlink->next = NULL; visitlink->past = taillink; taillink->next = visitlink; taillink = visitlink; printf("[%d - %d]\n", visitlink->past->port, visitlink->port); 9
int checkscan(visitlist *List) List = List->next; int changedcounter = 0; int port1; int port2; 비교하여 알립니다. // 가장최근통신한포트와, 그이전의포트, 그그이전의포트를 //3 번이상다른포트로통신하였을경우, 콘솔창에포트스캔의심을 while (1) port1 = List->port; if (List->next == NULL) break; else List = List->next; port2 = List->port; if (port1!= port2) changedcounter++; 측에서포트스캐닝을하고있습니다!\n", if (List->next == NULL) break; else List = List->next; port1 = List->port; if (port1!= port2) printf("[ ] %d.%d.%d.%d List->SenderIP[0], List- >SenderIP[1], List->SenderIP[2], List->SenderIP[3]); return 0; 10
포트스캔탐지코드 본인은포트스캔을가상으로하지않고 2 개의컴퓨터로실험을하였다. 본인의 PC_IP = 192.168.43.78 공격자의 PC_IP = 192.168.43.7 본인의 PC 에포트스캐닝탐지툴을돌리고, 공격자가포트스캐닝공격을실행한다. 문제점은공격자의포트스캐닝을탐지도하지만포트를통해통신하는수많은패킷들 또한포트스캐닝을한다고탐지가되는점이다. 이런점에서개선이필요하다. 11
참조 수업 네트워크보안프로그래밍 [ 영산대학교소길자교수님 ] 참조자료 김태룡학생 [C++ 을이용한포트스캔및탐지 ] 보고서 수업시간의 PPT 자료 웹페이지 http://prof.ysu.ac.kr/blog/blog_message.asp?b_id=kjso 포트스캐닝정의 [ 위키백과 ] https://ko.wikipedia.org/wiki/%ed%8f%ac%ed%8a%b8_%ec%8a%a4%ec %BA%94 포트스캔 [ 후니네 ] http://sound10000w.tistory.com/30 1 2