Edisi iseng : mengetahui mac address node (pc) dengan memanfaatkan arp request


Errr, sebenarnya saya bingung mau kasih judul apa (dan juga bingung mau kasih gambar apa) makanya bisa panjang begini. Kali ini intinya saya mau share source code untuk mencari mac address dari pc lain yang terhubung dalam suatu jaringan lokal (baca : LAN).

Source codenya bisa di akses di sini, di akun github saya. Kenapa saya mengarahkan ke github ? karena github keren, ada highlight textnya jadinya lebih elegan...kan. Kalo yang tidak mau repot langsung saja compile dan jalankan, inputnya hanya alamat ipv4 target yang ingin di ketahui mac addressnya.

Bikin program ini motifnya buat pemanasan aja karena sudah lama tidak ngutak-ngatik kode lagi sekalian belajar socket low level (baca : RAW socket) dari situ juga dan wew...ini sangat menyenangkan karena dengan socket ini kita sudah hampir 100% mengendalikan paket-paket data yang kita kirim melalui NIC di pc kita (ya, tidak 100% karena frame-frame seperti presemble, FCS dll untuk kebutuhan ke otentikan paket data tersebut tidak bisa kita kendalikan...memang mau buat apa ?). 

Bagian penting yang memungkinkan kita bisa mengedalikan low level paket data ada di :
int create_socket ()
{
    int fd;

    fd = socket(AF_PACKET, SOCK_RAW, htons(0x0806));
    if (fd == -1)
        printf("socket error\n");

    return fd;
}
 Tapi dengan konsekuensi saat menjalankan program ini kita harus memakai hak akses root kalau tidak socketnya mendapat nilai return -1 AKA socket error. Kalau sudah begini kita bebas mendefiniskan bentuk paket yang akan kita kirimakan, di program ini paket yang akan di kirim semuanya terangkum di 
char *pkt;
Loh, kok sudah sampai membahas pengiriman paket, fokus kita disini kan untuk mencari mac address target ? oh iya saya hampir lupa menjelaskannya, jadi disini sesuai dengan judulnya kita akan mencari tahu mac address target dengan mengirimkan arp request ke jaringan di tempat kita sedang terhubung (baca : LAN) dari dari arp request tadi kita akan mendapat balasan arp reply, dimana di dalam arp reply itu tercantum mac address si target tadi. Dan memang kegunaan dari protokol arp ini adalah untuk "untuk saling komunikasi antar node (baca : pc)" di dalam jaringan  agar satu sama lain saling mengetahui mac addressnya selain IP addressnya (baca : menkonversi ip address ke mac address). Selain menkonversi dari IP ke mac, dalam protokol arp ini bisa juga menkonversi ke arah sebaliknya. namanya reverse arp tapi tidak akan kita bahas kali ini karena di luar topik kita saat ini.

Ok, jadi program ini dimulai dengan membaca input ip address yang ingin di cari mac addressnya, setelah program menerima inputnya tentu saja tidak akan di terima mentah-mentah. Setelah di terima program akan menguji apakah input yang di berikan benar-benar ipv4 address yang valid, syarat-syarat address yang valid tentu saja suatu ipv4 punya 4 segmen angka dari 0 - 255 dan itulah inti dari kode ini :
int examine_addr (char *addr)
{
    char *ex;
    char sec_addr [3];
    char *token;
    unsigned int tes;
    int chk_ip = 0;
   
    ex = strchr(addr, ' ');
    if (ex != NULL) {
        printf("alamat yang di masukkan salah, mohon jangan ada spasi\n");
        return 0;
    }
    token = strtok(addr, ".");
    while (token != NULL) {
        chk_ip++;
        tes = atoi(token);
        if (tes > 255) {
            printf("alamat ip tidak ada yang lebih dari 255\n");
            return 0;
        }
        token = strtok(NULL, ".");
    }
    if (chk_ip != 4) {
        printf("alamat tidak valid\n");
        return 0;
    }

    return 1;
}
 Setelah program yakin kalau input yang di masukkan itu valid, langkah selanjutnya adalah mengirimkan arp request ke jaringan LAN kita saat ini, anatomi arp request adalah seperti berikut beserta dengan ethernet framenya :

Struktur itu sama untuk arp request maupun arp reply. Yang membedakan mereka berdua hanya di bagian OP (operation code), untuk arp request bitnya dalam bentuk hex adalah 0x0001 dan untuk reply 0x0002. Berdasarkan struktur ini lah, paket data yang akan kita kirimakn di bentuk terlebih dahulu dengan kode berikut ini :
char* create_pkt (char *ip)
{
    char *ptr;
    char *adr;
    char *token;
    int fd;
    int arp_proto = htons(ARP_PROTO);
    int hw_tp = htons(HARDWARE_TYPE);
    int pro_type = htons(PROTOCOL_TYPE);
    int hw_size = HARDWARE_SIZE;
    int pr_size = PROTOCOL_SIZE;
    int opcode = htons(OPCODE);
    int i;
    unsigned char seq;
    struct ifreq buffer;
    struct sockaddr_in *ipadd;

    ptr = malloc(sizeof(char [ARP_TOTAL_LEN]));
    memset(ptr, 0x00, sizeof (char [ARP_TOTAL_LEN]));
    fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
    memset(&buffer, 0, sizeof(buffer));
    strcpy(buffer.ifr_name, "wlan0");
    ioctl(fd, SIOCGIFHWADDR, &buffer);
    close(fd);
    memcpy(ptr, BRODCAST_PKT, MAC_LEN);
    memcpy(ptr + MAC_LEN, buffer.ifr_addr.sa_data, MAC_LEN);
    memcpy(ptr + (2 * MAC_LEN), &arp_proto, 2);
    memcpy(ptr + ETHER_FRAME_LEN, &hw_tp, 2);
    memcpy(ptr + ETHER_FRAME_LEN + 2, &pro_type, 2);
    memcpy(ptr + ETHER_FRAME_LEN + 4, &hw_size, 1);
    memcpy(ptr + ETHER_FRAME_LEN + 5, &pr_size, 1);
    memcpy(ptr + ETHER_FRAME_LEN + 6, &opcode, 2);
    memcpy(ptr + ETHER_FRAME_LEN + 8, buffer.ifr_addr.sa_data, MAC_LEN);
    memset(&buffer, 0, sizeof buffer);
    strcpy(buffer.ifr_name, "wlan0");
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (ioctl(fd, SIOCGIFADDR, &buffer) == -1)
        printf("ioctl ip checking error\n");
    close(fd);
    ipadd = (struct sockaddr_in *) &(buffer.ifr_addr);
    adr = inet_ntoa(ipadd->sin_addr);
    printf("alamat ipmu adalah : %s\n", adr);
    token = strtok(adr, ".");
    while (token != NULL) {
        seq = atoi(token);
        memcpy(ptr + ETHER_FRAME_LEN + 8 + MAC_LEN + i, &seq, 1);
        token = strtok(NULL, ".");
        i++;
    }
    i = 0;
    token = strtok(ip, ".");
    while (token != NULL) {
        seq = atoi(token);
        memcpy(ptr + ETHER_FRAME_LEN + 8 + (2 * MAC_LEN) + IP_LEN + i, &seq, 1);
        token = strtok(NULL, ".");
        i++;
    }

    return ptr;
}
setelah di bentuk, kemudian paket siap di kirimkan. Dari arp request tadi, node (baca : pc) yang merasa memiliki IP address yang kita input tadi akan melakukan arp reply, kalau di ibaratkan si node yang punya alamat IP tadi seolah berkata "itu nama julukan saya, nama asli saya adalah [insert mac address here]".

Karena banyaknya paket data yang berkeliaran di jaringan, program akan menfilter paket data yang mana yang merupakan "balasan" (baca : arp reply) dari "pertanyaan" (baca : arp request) program kita tadi. Untuk itulah paket data yang tertangkap akan di saring dengan serangkaian kode ini : 
        while (1) {
            if (recvfrom(sock, pkt, 1024, 0, (struct sockaddr *) &ll, (socklen_t *) &size) == -1)
                printf("error at receiving packet\n");
            memcpy(&arp, pkt + ETHER_FRAME_LEN - 2, 2);
            if (strncmp(arp, ARP_PACKET, 2) == 0) {
                memcpy(&arp, pkt + ETHER_FRAME_LEN + 6, 2);
                if (strncmp(arp, ARP_REPLY, 2)  == 0) {
                    memcpy(second_fill, fountain_fill, sizeof (char [15]));
                    token = strtok(second_fill, ".");
                    for (i = 0; i < 4; i++) {
                        memset(&seq, 0, 1);
                        seq = atoi(token);
                        ip_target [i] = seq;
                        token = strtok(NULL, ".");
                    }
                    if (strncmp(ip_target, pkt + ETHER_FRAME_LEN + 14, 4) == 0) {
                        memcpy(mac_target, pkt + ETHER_FRAME_LEN + 8, 6);
                        printf("mac addresnya adalah :");
                        for (i = 0; i < MAC_LEN; i++) {
                            printf(" %02x", *(mac_target + i));
                        }
                        printf("\n");
                        break;
                    }
                }
            }
        }
Di akhir kode di atas, setelah kita menyeleksi paket data yang merupakan "balasan" dari "pertanyaan" program kita, pada akhirnya program menekstrak ke buffer yang sudah di sediakan, mac address dari arp reply yang di kirimkan oleh node yang "mengaku" memiliki alamat IP itu. Setelah di ekstrak ke buffer kemudian langkah terakhir menprint ke terminal mac address tersebut dan selesai.

yup cukup sekian, untuk versi windowsnya bisa menggunakan libcap (silahkan pelajari sendiri) dan juga jika kita punya database hardware berdasarkan 3 seqment bit pertama di mac address, kita bisa menyajikan mac addressnya dengan lebih elegan seperti yang ada di wireshark. Untuk selanjutnya saya belum tahu mau buat apa lagi, bukan karena kurang bahan yang bisa di teliti tapi justru karena terlalu banyak yang ingin saya pelajari dan teliti, saking banyaknya saya tidak bisa memutuskan (membuktikan masih betapa ceteknya ilmu saya D: ). Baru-baru ini bidang-bidang yang ingin saya lebih pelajari lagi bertambah, yaitu open BTS. Mungkin pembahasan selanjutnya akan saya bahas...kalau saya punya cukup waktu luang.

Komentar