[yummyKit] 6 day

9 분 소요

※주의사항※
연구 목적으로 작성된 것이며, 허가 받지 않은 공간에서는 테스트를 절대 금지합니다. 악의적인 목적으로 이용할 시 발생할 수 있는 법적 책임은 자신한테 있습니다. 이는 해당 글을 열람할 때 동의하였다는 것을 의미합니다.


흐어 ㅜㅜ 이 글은 분명 3일 전에 쓰고있던건뎀 갑자기 IE 브라우저가 다운되면서 저장도 안된 상태로 날아가부렀서욤 ㅜㅜㅜ 그래서 다시씀니다!! 후욱,, 후욱,,

요즘 너무 나태해지다 보니 정신이 몽롱해지면서 머리가 몽총해진다는 것을 깨달았어욧!! 세상에나 마상에나 코딩이 안되는거 있죵 ㅜㅜ 그래서! 신년 목표 및 계획을 핑계삼아 오늘부터 열씸히 하려함니다!! 석사 가즈아~



냠냠!! 역시 *nix 짱짱맨이져!! 꺄륵~ (모든 윈도우 유저에게 죄송함니다.. 흑 제가 윈도우를 좋아하진 않아서욥.. 호고곡!)

참 요즘 깃헙에 재밌는거 올리고있어욤!! 씨언어로 만드는 객체지향 클래스!! 물론 객체지향이라함은 꽃과 같은 기능이 6개나 존재해서(encapsulation, inheritance, overloading, overriding, virtual/interface/abstract, access modifier) 전부 구현은 어렵지만욤!! 클래스 기능을 최대한 구현해보고, C1X(C11 이라고도 함미당)부터 생긴 _Generic 키워드를 통해 오버로딩도 구현할 슈 있어욤!! 이렇게 언어 만들어 가즈아~!


Live Packet Capture

자! 오늘 하려고 했던 거슨 바로바로 live packet capture 예욤!! 지난 포스팅에서는 pcap_open_offline() 함수를 통해서 패킷이 캡쳐된 파일을 분석하는 것이었다면, 이번엔 실제로 흘러가는 패킷을 분석하는 것이죵!!

호에에 이것을 구현하믄 이제 sniffer 는 금방 구현하지 않을까욥!? 네 않을 수도 있숨미다.. 왜냐하믄 arp 의 개념을 딱! 머릿속에 박은 채로 victim 과 router 사이에 잘 위치해야하거든욤!! 우선 소스코드를 보여드리기 전에, 수행할 결과화면을 보여드릴게욤!!


sample image


먼저 제 NIC 는 저기 보이는 NPF_{F044528C_..._558A} 하나만 있다고 해욤! 히히 가상머신이라 딱히 vmnet 이 없어서 1개밖에 안잡혀욧!

그리고 이 윈도우의 IP는 172.20.10.5 번이었구욤, 라우터의 IP는 172.20.10.1 이에욤! 172.20.10.3 번이 간혹 보이는뎅, 얘는 제 가상머신 중 하나인 우분투 리눅스의 IP구욤!

Source/Destination MAC Address를 보시면 딱 2가지만 번갈아가면서 나와욤! 하나는 윈도우의 MAC, 다른 하나는 라우터의 MAC 주소람니다!! 호엥 왜 외부 패킷으로 나가는데 라우터까지만 MAC 주소가 나오냐구욤!?


network flow

인터넷 통신을 보았을 때, Host PC --> Router --> Router --> ... --> Data Center --> ... --> DNS Server --> .. --> Router --> Web Server 와 같은 순서로 패킷이 흐르는데, Host PC 는 7계층에서 시작하여서 Router 가 존재하는 3계층(뭐 Switch 의 경우 MultiLayer 까지 존재해서 Layer 2 ~ 7 까지 다양하지만, 라우터의 경우 L4 까지 존재하는 것으로 알고있어용!!)을 통해 물리계층을 지나 다시 Web Server 인 7계층까지 도달할것이에욤!!

그럼 우리의 Host PC 는 MAC Address 를 담아서 맞물려있는 라우터 즉, 현재 연결되어 있는 네트워크의 라우터에게 패킷을 전송, 이 라우터는 라우팅 테이블을 통해 다음 라우터로 지나가므로 MAC Address 가 필요하지 않아서 헤더를 떼어내 버려요!! 그렇기 때문에 Host PC 의 MAC Address 와 라우터의 MAC Address 만 나오게 되는 것이죵!!


※ 참고로 위 작업은 개인 휴대폰의 핫스팟을 이용하였으며, 타인에게 피해가 가지 않도록 실습하였음을 말씀드립니다. 다시 한 번 말씀드리지만 모의실습을 진행할 시 자신만의 실습 환경에서만 진행하시길 부탁드리며, 그렇지 않을 시 모든 법적 책임은 자신에게 있다는 것을 명심하길 바랍니다.


해당 패킷 흐름은 Host 인 윈도우 10에서 N사(뇌이뻐!)의 포털사이트에 접속했을 때 잡힌 패킷이에욤! 나중에 패킷들 분석해보시면 중간중간 SSL 적용 안되어있던것도..읍읍

위 네이버로 통하는 IP는 cmd 창이나 terminal 에서 "nslookup www.naver.com" 에서도 볼 수 있는 IP + "traceroute(윈도우의 경우 tracert) www.naver.com" 으로 확인할 수 있으니 "엇!! 이거 해킹아냡!! 막 네이버 아이피 알고 그러면 잡혀가는거 아니얍!!" 하실 필요는 없어용!! 각 포털 사이트 및 중견급 이상 기업의 사이트들은 웹서버에 접근하지 못하도록 중간에 패킷에 정보를 주지 않고 흘리거나, access denied 시켜버려욤!


아닛 어떻게 access denied 를 시킬 수 있는거짓!? 리눅스에서의 traceroute 명령은 초기에 UDP 프로토콜을 통해 next hop 으로 넘어가도록 되어있어욤. 그러다가 ICMP 프로토콜의 TTL 값이 끝(총 라우터 64번 거친 경우; 리눅스는 default TTL maximum 64, 윈도우는 default TTL maximum 128)나거나, time to live exceeded 되거나 등등의 오류/성공 코드를 통해 결과를 받아욤!

윈도우에서의 tracert 명령은 처음부터 ICMP 프로토콜을 이용해서 결과를 받구욤! 둘이 약간 다르죵!? ㅎㅎ


위 ICMP 프로토콜은 패킷 전송이 원활히 흘러가는가 알아보기 위한 ping 명령을 위할 때가 아니면 사용할 일이 적기에, 보통 막아버려욤! 특히 윈도우는 처음부터 막혀있어서 필요시 wf.msc 와 같은 방화벽 정책에서 열어주어야 함니다!


오잉 위 패킷캡쳐 구현을 말씀드리다가 막 네트워크까지 주저리주저리했네욤 :) 히히

이제 소스코드를 보여드릴 때가 된 것 같군뇸!! 아마 이번 포스팅에서는 main 함수까진 못하구 사용되는 라이브러리 및 타 함수만 분석해드리고 빠잇! 할 것 같아욤!! 오늘도 아리따운 마크다운을 이용해서 가져와보기 전에! 다 가져가야만 속이 후련한 해바라기 식당의 아들을 만나보고 갈까욥!?



속이 후련했... 냐!!!! 내가 더 슬프게 해주꿰 ㅜㅜ 병진이형! 형은 나가이써 돼지고기 싫으면!!

정말정말 명작인 영화이자 연기 짱짱의 김래원쨩..

그럼 이제 소스코드를 보러 갑씨다! 뾰로롱


source code

#pragma comment(lib, "ws2_32.lib")
/*
This code is made by yummyHit using Microsoft Visual C++ 2010 Express.
You must have winpcap and add to library, include directory at your VC/bin directory.
+ Additional, install libnet and include it.
+ Additional, include <libnet-macros.h> in libnet-headers.h file.
Must be add linker: ws2_32.lib; wpcap.lib; Packet.lib
*/
#define HAVE_REMOTE
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#include <pcap.h>
#include <libnet.h>
#define PROMISCUOUS 1
#define NONPROMISCUOUS 0

void mac_print(int init, struct libnet_ethernet_hdr *eth) {
    int i = 0;
    if(init == 0) {
        while(i < ETHER_ADDR_LEN) {
            printf("%02x:", eth->ether_shost[i]);    // print Source Mac Address
            if((i+1) == (ETHER_ADDR_LEN-1))        // If next i value is last index, print last address value and quit loop.
                printf("%02x", eth->ether_shost[++i]);
            i++;
        }
        printf("\n");
    }
    else {
        i = 0;
        while(i < ETHER_ADDR_LEN) {
            printf("%02x:", eth->ether_dhost[i]);    // print Destination Mac Address
            if((i+1) == (ETHER_ADDR_LEN-1))        // If next i value is last index, print last address value and quit loop.
                printf("%02x", eth->ether_dhost[++i]);
            i++;
        }
        printf("\n");
    }
}


지난 포스팅과 include 하는 것은 거의 똑같져!? 다른거라면 libnet 라이브러리!

libnet library

지난 코드에선 ethernet frame, arp/ip packet, tcp/udp segment 구조체를 직접 만들어서 패킷 데이터를 할당시켰잖아욤!? 이젠 그럴필요 없슴니다! 묻지도 따지지도 말고 libnet 라이브러리만 추가하시면 되어욤!! 오픈소스로 있으니 직접 사이트에서 다운로드 받으셔두 되구욤!!</span>

(libnet web site: http://packetfactory.openwall.net/projects/libnet)

혹은 리눅스라면 역시 패키지 다운로드를 통하면 됨니다!!

데비안의 경우 libnet1-* / 레드햇의 경우 libnet* 을 통해서 설치하시면 되어욤!


#include <libnet.h>

여기서 libnet-headers.h 가 필요한 것인데, 말 그대로 패킷 전송에 필요한 헤더를 모아둔 곳이에욤! 해당 파일에서 필요한 구조체는


/*
 *  Ethernet II header
 *  Static header size: 14 bytes
 */
struct libnet_ethernet_hdr
{
    uint8_t  ether_dhost[ETHER_ADDR_LEN];/* destination ethernet address */
    uint8_t  ether_shost[ETHER_ADDR_LEN];/* source ethernet address */
    uint16_t ether_type;                 /* protocol */
};

/*
 *  ARP header
 *  Address Resolution Protocol
 *  Base header size: 8 bytes
 */
struct libnet_arp_hdr
{
    uint16_t ar_hrd;         /* format of hardware address */
#define ARPHRD_NETROM   0   /* from KA9Q: NET/ROM pseudo */
#define ARPHRD_ETHER    1   /* Ethernet 10Mbps */
#define ARPHRD_EETHER   2   /* Experimental Ethernet */
#define ARPHRD_AX25     3   /* AX.25 Level 2 */
#define ARPHRD_PRONET   4   /* PROnet token ring */
#define ARPHRD_CHAOS    5   /* Chaosnet */
#define ARPHRD_IEEE802  6   /* IEEE 802.2 Ethernet/TR/TB */
#define ARPHRD_ARCNET   7   /* ARCnet */
#define ARPHRD_APPLETLK 8   /* APPLEtalk */
#define ARPHRD_LANSTAR  9   /* Lanstar */
#define ARPHRD_DLCI     15  /* Frame Relay DLCI */
#define ARPHRD_ATM      19  /* ATM */
#define ARPHRD_METRICOM 23  /* Metricom STRIP (new IANA id) */
#define ARPHRD_IPSEC    31  /* IPsec tunnel */
    uint16_t ar_pro;         /* format of protocol address */
    uint8_t  ar_hln;         /* length of hardware address */
    uint8_t  ar_pln;         /* length of protocol addres */
    uint16_t ar_op;          /* operation type */
#define ARPOP_REQUEST    1  /* req to resolve address */
#define ARPOP_REPLY      2  /* resp to previous request */
#define ARPOP_REVREQUEST 3  /* req protocol address given hardware */
#define ARPOP_REVREPLY   4  /* resp giving protocol address */
#define ARPOP_INVREQUEST 8  /* req to identify peer */
#define ARPOP_INVREPLY   9  /* resp identifying peer */
    u_char ar_sha[6];       // Sender hardware address
    u_char ar_spa[4];       // Sender IP address
    u_char ar_dha[6];       // Target hardware address
    u_char ar_dpa[4];       // Target IP address
};

/*
 *  IPv4 header
 *  Internet Protocol, version 4
 *  Static header size: 20 bytes
 */
struct libnet_ipv4_hdr
{
#if (LIBNET_LIL_ENDIAN)
    uint8_t ip_hl:4,      /* header length */
           ip_v:4;         /* version */
#endif
#if (LIBNET_BIG_ENDIAN)
    uint8_t ip_v:4,       /* version */
           ip_hl:4;        /* header length */
#endif
    uint8_t ip_tos;       /* type of service */
#ifndef IPTOS_LOWDELAY
#define IPTOS_LOWDELAY      0x10
#endif
#ifndef IPTOS_THROUGHPUT
#define IPTOS_THROUGHPUT    0x08
#endif
#ifndef IPTOS_RELIABILITY
#define IPTOS_RELIABILITY   0x04
#endif
#ifndef IPTOS_LOWCOST
#define IPTOS_LOWCOST       0x02
#endif
    uint16_t ip_len;         /* total length */
    uint16_t ip_id;          /* identification */
    uint16_t ip_off;
#ifndef IP_RF
#define IP_RF 0x8000        /* reserved fragment flag */
#endif
#ifndef IP_DF
#define IP_DF 0x4000        /* dont fragment flag */
#endif
#ifndef IP_MF
#define IP_MF 0x2000        /* more fragments flag */
#endif
#ifndef IP_OFFMASK
#define IP_OFFMASK 0x1fff   /* mask for fragmenting bits */
#endif
    uint8_t ip_ttl;          /* time to live */
    uint8_t ip_p;            /* protocol */
    uint16_t ip_sum;         /* checksum */
    struct in_addr ip_src, ip_dst; /* source and dest address */
};

/*
 *  TCP header
 *  Transmission Control Protocol
 *  Static header size: 20 bytes
 */
struct libnet_tcp_hdr
{
    uint16_t th_sport;       /* source port */
    uint16_t th_dport;       /* destination port */
    uint32_t th_seq;          /* sequence number */
    uint32_t th_ack;          /* acknowledgement number */
#if (LIBNET_LIL_ENDIAN)
    uint8_t  th_x2:4,         /* (unused) */
             th_off:4;        /* data offset */
#endif
#if (LIBNET_BIG_ENDIAN)
    uint8_t  th_off:4,        /* data offset */
             th_x2:4;         /* (unused) */
#endif
    uint8_t  th_flags;       /* control flags */
#ifndef TH_FIN
#define TH_FIN    0x01      /* finished send data */
#endif
#ifndef TH_SYN
#define TH_SYN    0x02      /* synchronize sequence numbers */
#endif
#ifndef TH_RST
#define TH_RST    0x04      /* reset the connection */
#endif
#ifndef TH_PUSH
#define TH_PUSH   0x08      /* push data to the app layer */
#endif
#ifndef TH_ACK
#define TH_ACK    0x10      /* acknowledge */
#endif
#ifndef TH_URG
#define TH_URG    0x20      /* urgent! */
#endif
#ifndef TH_ECE
#define TH_ECE    0x40
#endif
#ifndef TH_CWR
#define TH_CWR    0x80
#endif
    uint16_t th_win;         /* window */
    uint16_t th_sum;         /* checksum */
    uint16_t th_urp;         /* urgent pointer */
};

/*
 *  UDP header
 *  User Data Protocol
 *  Static header size: 8 bytes
 */
struct libnet_udp_hdr
{
    uint16_t uh_sport;       /* source port */
    uint16_t uh_dport;       /* destination port */
    uint16_t uh_ulen;        /* length */
    uint16_t uh_sum;         /* checksum */
};



짜란! 요것들 임니다! 우리가 yummyKit 과 같은 프로그램을 만들기 위해 계속 사용할 Ethernet ! ARP ! IPv4 ! TCP ! UDP ! 대표적인 프로토콜들이죵!! 이 외에도 총 68개의 구조체가 있으니 68개의 프로토콜에 대한 헤더가 구조체로 만들어져 있는 파일임니다!!

아아 역시 사람은 지식이 많아야함미다 ㅜㅜ 무지하니 이런것들이 있는 줄도 모르고 한땀한땀 만들면 물논 실력은 좋아질 수 있으나.. 시간을 생각했을 때 이런 정도는 시간허비가 커진다고 느껴져용 ㅜㅜ 라이브러리를 알았으면 기냥 패키지 뙇!! 다운로드 받아서 바로 include 뙇!!


헤더 외에도 우리에게 필요했던 ETHER_ADDR_LEN, ARPOP_REQUEST, ARPOP_REPLY 와 같은 전처리가 되어있으니 이것도 사용하면 될 것 같네욤!! 코드 가독성아 좋아져라 얍!

라이브러리만 설명하는데 포스팅 스크롤이 압박되어버렸네욥... 빠르게 다음 함수를 설명드리고 마칠게용!! 제성함미다... (((꾸벅


void mac_print(int init, struct libnet_ethernet_hdr *eth);


마크다운을 사용하시면 예쁘게 나옴니다 얏호!! (+____+) 그치만,, 이렇게라도 하지 않으면 회원쨩,, 개발 재미없다고 떠날것 같은걸!


온전히 함수명 그대~로 MAC Address 출력을 위함이에욤!! MAC Address 의 경우 unsigned char 형식으로 1바이트씩 6개가 이루어져 있어서 %02x 또는 %02X 로 출력해주어야 하거든요!! 또한 예쁘게 보기 위하여 MAC Address를 표기하는 AA:BB:CC:DD:EE:FF 방식을 위해 마지막 바이트에선 뒤에 ":" 세미콜론을 붙이지 않고 출력하는 것!!!

그리고 위 함수를 처음 들어갔을 때 init 이라는 정수형 변수를 통해 if 조건 분기를 타게되는데, 이것은 Source MAC Address 인지 Destination MAC Address 인지 구별을 위함이에욤!! libnet_ethernet_hdr 구조체를 이용했기 때문에 출발지와 목적지의 변수가 달라서 따로 써야하거든뇸!!


오늘 왠지 스크롤 압박이 되었네욥.. 히히 다음번엔 온전히 main 함수를 분석하여 실제로 첫 번째 사진과 같이 live packet capture 프로그램을 만들어보아욤!! 오늘은 월요일 아침 6시이니 월요일 좋다는 짤과 함께 다음 포스팅에서 뵈어욥 뿅!!




Check out the yummyhit’s website for more info on who am i. If you have questions, you can ask them on E-mail.

카테고리:

업데이트:

댓글남기기