Network Major

네트워크 패킷 분석 및 파일 추출 프로그램 제작

분류

Best of the Best 9기 팀 프로젝트 (Team. 서예진, 이수진, 김경환)

역할 및 상세 활동

FTP 프로토콜 분석 및 파일 추출 알고리즘 개발

사용한 기술

C++

진행 기간

2020.07 ~ 2020.09

관련 링크

Github

2020_BoB_NetworkMajor

프로젝트 개요

본 프로젝트는 네트워크의 패킷을 분석하는 프로그램을 만들어서, 네트워크 Raw 패킷을 통해서 세부적인 정보를 효율적으로 파악하는 것을 목적으로 한다. 오픈 소스 네트워크 패킷 분석 수집 프로그램인 ‘WireShark’에서는 분석 및 수집을 원하는 네트워크 영역을 선택하고, 이를 통해서 실시간으로 Host에서 일어나고 있는 네트워크 통신을 볼 수 있도록 하며, 캡쳐한 해당 패킷들을 ‘.pcap’ 파일로 저장할 수 있다. 여기서 추출해낸 ‘.pcap’ 파일을 저장하고, ‘NetworkMiner’라는 프로그램에서 불러와서 패킷을 추가적으로 분석할 수 있다.

본 프로젝트의 궁극적인 목표는 ‘NetworkMiner’에서 제공하는 패킷 분석 기능을 구현하는 것이다. 시간적 여유가 된다면, 추가적으로 ‘Wireshark’의 기능인 실시간 패킷 캡쳐 및 분석기능을 결합하고자 한다. 가상 환경에서 실시간으로 네트워크 패킷을 캡쳐하고, 해당 패킷에 내재되어 있는 정보들을 추출하여 프로그램의 사용자에게 가시적으로 보여준다.

프로토콜 분석

HTTP

HTTP 분석

  • 인터넷 통신 프로토콜 (HyperText Transfer Protocol)
  • 클라이언트는 서버에 Request <-> 서버는 클라이언트에 Response
  • Ehternet Header + IPv4 Header + TCP Header + HTTP Data
  • HTTP Data는 html 뿐만 아니라 이미지, 영상, 음성 데이터의 전송도 가능
  • 연결은 3 way-handshake (SYN / SYN + ACK / ACK)
  • 종료는 4 way-handshake (FIN / ACK / FIN / ACK)
  • 클라이언트가 서버에 요청을 보내고, 응답을 받으면 통신이 종료
  • 서버와 통신할 때 80번 포트 사용

SMTP

SMTP 분석

  • 메일 전송 프로토콜 (Simple Mail Transfer Protocol)
  • TCP / IP 네트워크 상에서 메일을 송수신하기 위해 제작
  • 모든 메세지가 7bit ASCII로 규정되어 있어 8bit 이상의 코드를 사용할 때는 MIME 방식으로 변환되어 전달
  • Ethernet Header + IPv4 Header + TCP Header + SMTP Data

FTP

FTP 분석

  • 파일 전송 프로토콜 (File Transfer Protocol)
  • TCP / IP 네트워크 상에서 컴퓨터들이 파일을 주고받기 위해 제작
  • Ethernet Header + IPv4 Header + TCP Header + FTP Data

구현

전체 코드는 여기에서 확인하실 수 있습니다.


HTTP 핵심 코드

// HTTP 패킷
if (http_get_data_port.size() >= 1 && src_port == 80) {
    int flag1 = 0;
    int port_num = -1;
    for (int i = 0; i < http_get_data_port.size(); i++) {
        if (dst_port == http_get_data_port[i].first) {
            flag1 = 1;  // 데이터가 들어오기 시작한 포트번호인 경우
            port_num = i;
            break;
        }
    }
    if (flag1) { // 해당 포트번호로 들어오는 패킷 합치기
        if (http_sequence_num[port_num] == 0) {
            http_sequence_num[port_num] = ntohl(tcpLayer->getTcpHeader()->sequenceNumber);
        } else if (http_sequence_num[port_num] < ntohl(tcpLayer->getTcpHeader()->sequenceNumber)) {
            const u_char* packet;
            packet = (u_char*) rawPacket.getRawData();
            uint16_t start = 14 + 20 + my_ntohs(packet[46]) * 4;
            int payload_start = total_length - payload_length;
            uint16_t TOTAL_LENGTH = ntohs(ipLayer->getIPv4Header()->totalLength) + 14;
            if (!(packet[payload_start] == 0x48 && packet[payload_start + 1] == 0x54 &&
            packet[payload_start + 2] == 0x54 && packet[payload_start + 3] == 0x50)) {
                for (int i = payload_start; i < total_length; i++) {
                    http_data[port_num][http_data_idx[port_num]++] = packet[i];
                }
            }
        }
    }
    /* 중략 */
}

SMTP 핵심 코드

// SMTP 패킷
if ((src_port == 25 || src_port == 465 || src_port == 587 ) || (dst_port == 25 || dst_port == 465 || dst_port == 587)) {
    printf("\n[ SMTP Packet ]\n");

    const u_char* packet;
    packet = (u_char*) rawPacket.getRawData();
    string smtp_response_code = "";

    // SMTP response code 가져오기
    for (int i = payload_start; i < payload_start + 3; i++) {
        smtp_response_code += packet[i];
    }

    if (smtp_response_code == "220") {  // 220이면 TCP 연결 시작, 서버 준비완료, SMTP 통신 시작
        server_port = src_port ;
        client_port = dst_port ;
    } else {
        if (src_port == server_port) { // server -> client
            printf("(server) -> (client)  \n");
            for(int i= payload_start; i < total_length; i++) {
                printf("%c", packet[i]);
            }
        }
    }
    /* 중략 */
}

FTP 핵심 코드

// FTP 패킷
if (src_port == 21) { // FTP Response 패킷이라면...
    printf("\n[ FTP Response Packet ]\n");
    const uint8_t* packet = rawPacket.getRawData();

    uint16_t start = 14 + 20 + my_ntohs(packet[46]) * 4;
    uint16_t TOTAL_LENGTH = ntohs(ipLayer->getIPv4Header()->totalLength) + 14;

    printf("TCP header len is %d\n", my_ntohs(packet[46]) * 4);
    printf("start index is %d\n", start);
    printf("total length is %d\n", total_length);
    printf("\nResponse: ");

    for (int i = payload_start; i<total_length; i++) {
        printf("%c", packet[i]);
    }

    std::string ftp_command = "";

    // FTP response code 가져오기
    printf("\nResponse Code : ");
    for (int i = start; i < start + 3; i++) {
        ftp_command += (u_char) packet[i];
    }
    ftp_response_code = atoi(ftp_command.c_str());
    printf("%d", ftp_response_code);
    /* 중략 */
}

프로그램 실행 결과

공통

공통 헤더

프로그램 실행 시 출력되는 헤더 정보

공통 헤더

프로그램 실행 시 생성되는 로그 파일

HTTP

공통 헤더

터미널 화면에 출력되는 HTTP 관련 정보

공통 헤더

HTTP 프로토콜에서 추출한 파일들

공통 헤더

WireShark에서 본 HTTP 프로토콜의 Object List

공통 헤더

프로그램 실행 시 생성된 index.action

SMTP

공통 헤더

터미널 화면에 출력되는 SMTP 관련 정보

공통 헤더

SMTP 프로토콜에서 추출한 파일들

공통 헤더

프로그램 실행 시 생성된 winmail.dat

FTP

공통 헤더

터미널 화면에 출력되는 FTP 관련 정보

공통 헤더

FTP 프로토콜에서 추출한 파일들

공통 헤더

프로그램 실행 시 생성된 BoB9_network.docx

공통 헤더

프로그램 실행 시 생성된 bob-logo1.png

추후 보완 사항

  • SMTP 내에서의 멀티미디어 컨텐츠 인코딩
  • 라이브 패킷 분석 기능 추가
  • FTP Active Mode 지원