Mengirim Raw Packet: Latihan Ping


Setelah sebelumnya aku belajar membaca raw packet yang diterima network card, kali ini aku ingin mencoba mengirim raw packet secara langsung. Keuntungannya adalah aku bisa bebas menentukan semua parameter packet yang aku kirim. Sebagai latihan, aku akan mencoba membuat program yang mirip seperti program PING yang mengirim dan menerima packet ICMP ECHO.

Format packet ICMP ditentukan oleh RFC 792. Berikut ini adalah contoh packet ECHO REQUEST yang dikirim oleh program PING:

xx xx 08 00 4a 5c 02 00    01 00 61 62 63 64 65 66
67 68 69 6a 6b 6c 6d 6e    6f 70 71 72 73 74 75 76
77 61 62 63 64 65 66 67    68 68

Dan ini adalah contoh ECHO REPLY atas packet di atas:

xx xx 00 00 52 5c 02 00    01 00 61 62 63 64 65 66
67 68 69 6a 6b 6c 6d 6e    6f 70 71 72 73 74 75 76
77 61 62 63 64 65 66 67    68 69

Byte awal 08 menunjukkan kalau packet tersebut adalah ECHO REQUEST, dan byte 00 menunjukkan kalau packet tersebut adalah ECHO REPLY. Byte kedua (CODE) berisi nilai 00. Kemudian diteruskan dengan dua byte checksum. Dua byte berikutnya adalah IDENTIFIER, dilanjutkan dengan dua byte SEQUENCE NUMBER. Sepertinya program PING selalu menggunakan IDENTIFIER dengan nilai 0x0200. Nilai SEQUENCE NUMBER dipergunakan untuk mencocokkan antara request dan reply. Setelah itu PING mengirimkan 32 byte data yang berupa deretan huruf.

Sebelum memulai mengirim packet, aku harus memastikan bawah packet ICMP di-enkapsulasi lagi oleh packet IP, lalu oleh packet Ethernet. Untuk mempermudah pembuatan program, aku membuat sebuah struct sederhana yang merepresentasikan packet ECHO REQUEST seperti berikut ini:

struct ECHO_REQUEST {
  u_char mac_destination[6];
  u_char mac_source[6];
  u_short type;
  u_char ip_version_headerlength;
  u_char ip_services;
  u_short ip_totalLength;
  u_short ip_identification;
  u_char ip_flag;
  u_char ip_fragment_offset;
  u_char ip_ttl;
  u_char ip_protocol;
  u_short ip_checksum;
  u_char ip_source[4];
  u_char ip_destination[4];
  u_char  icmp_type;
  u_char  icmp_code;
  u_short icmp_checksum;
  u_short icmp_identifier;
  u_short icmp_sequence;
  u_char  icmp_data[32];
};

Jika aku ingin men-PING komputer dengan IP 192.168.1.1 dari komputer dengan IP 192.168.1.2, maka aku dapat mengisi setiap field di packet seperti:

void initializeEchoRequestPacket(ECHO_REQUEST *echoRequest) {
  u_char mac_destination[6] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
  valuecpy(echoRequest->mac_destination, mac_destination, 6);
  u_char mac_source[6] = {0x2, 0x2, 0x2, 0x2, 0x2, 0x2 };
  valuecpy(echoRequest->mac_source, mac_source, 6);
  echoRequest->type = 0x0008;

  echoRequest->ip_version_headerlength = 0x45;
  echoRequest->ip_services = 0x00;
  echoRequest->ip_totalLength = 0x3C00;
  echoRequest->ip_identification = 0x0400;
  echoRequest->ip_flag = 00;
  echoRequest->ip_fragment_offset = 0x0000;
  echoRequest->ip_ttl = 0x80;
  echoRequest->ip_protocol = 0x01;
  echoRequest->ip_checksum = 0x0000;
  u_char ip_source[4] = {192,168,1,2};
  valuecpy(echoRequest->ip_source, ip_source, 4);
  u_char ip_dest[4] = {192,168,1,1};
  valuecpy(echoRequest->ip_destination, ip_dest, 4);

  echoRequest->icmp_type = 0x08;
  echoRequest->icmp_code = 0x00;
  echoRequest->icmp_checksum = 0x0000;
  echoRequest->icmp_identifier = 0x0002;
  echoRequest->icmp_sequence = 0x000d;
  for (int i=0; i<32; i++) {     echoRequest->icmp_data[i] = 'B';
  }
}

Agar packet ICMP ECHO REQUEST ini dapat dikirim dan diterima, selain mengisi IP address dengan benar, aku juga harus mengisi nilai MAC Source dan MAC Destination (yang merupakan bagian dari Ethernet Frame) dengan benar. Selain itu, aku juga harus melakukan kalkulasi untuk menghasilkan checksum dengan benar. Proses kalkulasi dan contoh kode program untuk kalkulasi checksum dapat dilihat di RFC 1071. Ini adalah contoh fungsi sederhana untuk menghitung nilai checksum untuk IP Header:

void calculateIPChecksum(ECHO_REQUEST *packet) {
  u_short *shortValue = (u_short*)
    (&packet->ip_version_headerlength);
  long totalValue = 0;

  for (int i=0; i<10; i++) {     
    totalValue += (*shortValue);     
    shortValue++;   
  }   
  while (totalValue>>16) {
    totalValue = (totalValue & 0xffff) + (totalValue>>16);
  }
  packet->ip_checksum = ~totalValue;
}

Fungsi di atas mengandaikan IP Header berukuran fixed 20 bytes atau 10 words. Kalkulasi checksum dilakukan dengan menjumlahkan seluruh word (integer 16-bit) yang membentuk IP Header. Jika hasil jumlah dalam bentuk angka 16-bit ini mengandung carry/overflow , maka carry dari MSB dijumlahkan ke LSB, dan ini dilakukan berulang sampai tidak ada carry lagi. Dan hasilnya, 1’s complement dari nilai tersebut adalah nilai cheksum yang dipakai.

Dan sebagai langkah terakhir untuk mengirim ECHO REQUEST, aku harus melakukan proses pengiriman packet. Cara yang paling gampang adalah dengan menggunakan fungsi pcap_sendpacket(). Sebagai contoh, aku mengirimkan 15 kali ECHO REQUEST dengan menggunaakan kode seperti berikut:

for (int j=0; j<15; j++) {   
  struct ECHO_REQUEST *echoRequest = 
    new struct ECHO_REQUEST();   
  initializeEchoRequestPacket(echoRequest);   
  echoRequest->ip_identification = (u_short) j;
  echoRequest->icmp_identifier = 0x0002;
  echoRequest->icmp_sequence = (u_short) j;
  calculateIPChecksum(echoRequest);
  calculateICMPChecksum(echoRequest);
  if (pcap_sendpacket(handle, (u_char*)((void*)echoRequest), 74)) {
    printf("ERROR: %s\n", pcap_geterr(handle));
    exit(EXIT_FAILURE);
  }
  delete echoRequest;
}

O ya, sebagai data pada ECHO REQUEST, aku mengirimkan 32 byte huruf ‘B’. Sebenarnya, aku punya kebebasan untuk memberikan nilai apa saja disini. Salah satu ide kreatif yang pernah aku temui adalah mengirimkan data melalui ICMP ECHO, seperti isi web page atau text chatting. Administrator cenderung memblokir komunikasi TCP/IP berdasarkan port. Jika ia berbaik hati membolehkan packet ICMP REQUEST keluar masuk dengan leluasa [test dengan mencoba apakah program PING dapat dipakai], maka seseorang bisa saja melakukan tunneling. Misalnya, request HTTP disisipkan sebagai data dalam packet ICMP ECHO REQUEST, kemudian diterima oleh komputer lain yang bebas dari blokiran. Program spesial di komputer lain tersebut membaca data spesial di ICMP ECHO REQUEST tersebut, lalu melakukan koneksi internet, dan mengirimkan hasilnya ke komputer pengguna, juga dalam bentuk ICMP ECHO REQUEST/REPLY. Sang administrator di ruangan khususnya, kini sedang serius membaca log firewall (atau mungkin membaca chat gadis-gadis QA sambil sesekali tertawa, no offense here, just a speculation), hanya akan melihat dua komputer saling nge-ping.

Perihal Solid Snake
I'm nothing...

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: