티스토리 뷰

security

ARP 스푸핑

jjang36524 2021. 9. 5. 16:15

ARP 스푸핑: 로컬 네트워크(LAN)에서 사용하는 ARP 프로토콜의 허점을 이용하여 공격 대상 호스트에게 MAC(Media Access Control) 주소를 속이는 공격

로컬 네트워크 환경에서는 IP 주소뿐만 아니라 MAC 주소가 통신에 함께 사용
호스트 A가 통신을 위해서 호스트 B의 MAC 주소를 알아내는 과정:
A : 호스트 B의 MAC 주소를 찾는 ARP Request를 전송
B : 자기 자신을 찾는 ARP Request인 경우, 호스트 A에게 ARP Reply를 전송
A : B의 MAC 주소 정보가 포함된 B의 ARP Reply를 수신, ARP 테이블에 IP 주소와 함께 저장

ARP 헤더의 크기는 28바이트
Hardware Type은 Ethernet 환경이면 1, Protocol Type은 IP 조회이면 0x0800
Hardware Address Length의 값:6,Protocol Address Length의 값: 4
OPcode: Request이면 1, Reply면 2
Source Hardware Address(MAC)와 Source Protocol Address(IP)가 설정, MAC 주소를 모르면 하드웨어 주소는 00:00:00:00:00:00으로 설정
A,B,C가 있는 네트워크에서 A가 C에게 전송->
A가 ff:ff:ff:ff:ff:ff 주소로 ARP Request 메시지를 전송->
모든 호스트가 수신, C만 답변->
ARP 테이블 업데이트
ARP Request를 이용하여 공격 가능

#include <stdio.h>
#include <string.h>

#ifndef __linux__
    #include <winsock2.h>
#else
    #include <netinet/in.h>
    #include <arpa/inet.h>
#endif

#include <stdint.h>

#define ETHERTYPE_IP    0x0800      /* IP */
#define ETHERTYPE_ARP   0x0806      /* Address resolution */

#define ARPOP_REQUEST   1           /* ARP request */
#define ARPOP_REPLY     2           /* ARP reply   */

#ifndef __linux__
    #pragma pack(push, 1)
#endif
struct ether_header{
    uint8_t ether_dhost[6];         /* destination eth addr */
    uint8_t ether_shost[6];         /* source ether addr    */
    uint16_t ether_type;            /* packet type ID field */
}
#ifndef __linux__
    ;
    #pragma pack(pop)
#else
__atrribute__ ((__packed__));
#endif

#ifndef __linux__
    #pragma pack(push, 1)
#endif
struct arphdr{
    uint16_t ar_hrd;            /* Format of hardware address */
    uint16_t ar_pro;            /* Format of protocol address */
    uint8_t ar_hln;             /* Length of hardware address */
    uint8_t ar_pln;             /* Length of protocol address */
    uint16_t ar_op;             /* ARP opcode (command).      */
}
#ifndef __linux__
    ;
    #pragma pack(pop)
#else
__attribute__ ((__packed__));
#endif

#ifndef __linux__
    #pragma pack(push, 1)
#endif
struct ether_arp
{
    struct arphdr ea_hdr;       /* fixed-size header */

    uint8_t arp_sha[6];         /* sender hardware address */
    uint8_t arp_spa[4];         /* sender protocol address */
    uint8_t arp_tha[6];         /* target hardware address */
    uint8_t arp_tpa[4];         /* target protocol address */
}
#ifndef __linux__
    ;
    #pragma pack(pop)
#else
__attribute__ ((__packed__));
#endif

#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ar_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
#define arp_pln ea_hdr.ar_pln
#define arp_op  ea_hdr.ar_op

#ifndef __linux__
    #pragma pack(push, 1)
#endif
struct arp_packet{    /* arp 패킷을 전송하기 위한 arp_packet 구조체 정의 */
    struct ehter_header ether_header;
    struct ether_arp ether_arp;
}
#ifndef __linux__
    ;
    #pragma pack(pop)
#else
__atttribute__ ((__packed__));
#endif

void make_ether_header(struct ether_header *ether_header,
                uint8_t *dest, uint8_t *source, uint16_t type);

void make_arp_header(struct ether_arp *ether_arp, uint8_t *sha,
                uint32_t spa, uint8_t *tha, uint32_t tpa, uint32_t op);

void strmac_to_buffer(const char *str, uint8_t *mac);

void make_ether_header(struct ether_header *ether_header,
            uin8_t *dest, uint8_t *source, uint16_t type)
{
    memcpy(ether_header->ether_dhost, dest, 6);
    memcpy(ether_header->ether_shost, source, 6);

    ether_header->ether_type = htons(type);
}

void make_arp_header(struct ehter_arp *ether_arp, uint8_t *sha,uint8_t *tha,
            uint32_t spa, uint8_t *tha, uint32_t tpa, uint32_t op)
{
    ether_arp->arp_hrd = ntohs(1);
    ether_arp->arp_pro = ntohs(ETHERTYPE_IP);
    ether_arp->arp_hln = 6;
    ether_arp->arp_pln = 4;

    ether_arp->arp_op = htons(op);

    memcpy(ether_arp->arp_sha, sha, 6);
    memcpy(ether_arp->arp_spa, &spa, 4);

    (tha)?
        (memcpy(ether_arp->arp_tha, sha, 6)):
        (memset(ether_arp->arp_tha, 0x00, 6));
    
    memcpy(ether_arp->arp_spa, &spa, 4);
}

void strmac_to_buffer(const char *str, uint8_t *mac)
{
    int i;
    unsigned int tmac[6];

    sscanf(str, "&x:&x:&x:&x:&x:&x",
        &tmac[0], &tmac[1], &tmac[2], &tmac[3], &tmac[4], &tmac[5]);

    for(i = 0; i < 6; i +=1){
        mac[i] = (unsigned char)tmac[i];
    }
}

'security' 카테고리의 다른 글

네트워크 요약  (0) 2021.09.08
HTTP와 HTTPS  (0) 2021.09.05
monitor mode 및 패킷 수집 실습  (0) 2021.09.05
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함