Minggu, 20 Mei 2012

Pemrograman Jaringan Dengan BSD Socket Linux Pakai Bahasa C

Linux mendukung TCP/IP, disini akan dijelaskan bagaimana membuat suatu program (network) daemon proses, dengan BSD socket interface dengan menggunakan bahasa C/C++. Untuk itu diharapkan anda sudah familiar dengan pemrograman C/C++ di linux dan topik seperti fork, signal dll. Setelaih itu kita akan lihat program sederhana yang sederhana yang mengimplementasikan BSD socket untuk membuat trojan atau backdoor.  Saya bukan "master" jadi jangan mengharap banyak dari tutorial ini, saya cuma mengajak belajar bersama karena semua ini menyenagkan. Untuk lebih jelas mengenai fungsi2 dalam tutorial ini sebaiknya anda melihat rujukan manual dalam section 2 (mudahnya ketikan perntintah "man listen" misalnya, untuk melihat manual dari fungsi listen())

Apa itu socket? (bukan toket lho!)

Di Unix atau Linux 'semua' adalah file. Ketika suatu program melakukan proses I/O maka program tersebut akan membaca atau menulis pada file descriptor. Socket merupakan file descriptor untuk networking. File descriptor hanya sebuah integer yang berasosiasi dengan suatu device dan dapat berupa terminal, suatu koneksi pada network, atau yang lainnya. Misalnya suatu printer port hardware berasosiasi dengan file /dev/lpt1, maka untuk memberikan informasi atau mengambil informasi dari port tersebut yang kita lakukan adalah membuka akses ke file tersebut dan membacanya atau menuliskan informasi. File descriptor ini dapat dipandang sebagai interface antar programer dengan sistem operasi, akan kita lihat dengan konsep ini perkerjaan menjadi lebih mudah mudah.
 

Dengan socket descriptor maka komunikasi dapat dilakukan dengan membuka soket, menulis lalu menutup setelah socket tidak  digunakan.Soket digunakan sebagai mekanisme komunikasi baik dalam satu komputer maupun antar komputer dalam network.  Ketika network dibutuhkan maka terjadi pemanggilan rutin sistem (system calls) atau fungsi socket().
 
-- intermezo: Apalagi itu system calls? System calls adalah fungsi-fungsi yang telah disediakan oleh UNIX sebagai interface ilangsung ke sistem operasi Dengan fungsi2 tersebut kita dapat mengkses dan mengkontrol devices. Dalam UNIX fungsi2 tersebut telah terdapat dalam BSD Socket API. 
 
Konsep tersebut, dimana IP dan port direpresentasikan dalan file merupakan konsep BSD Socket.

Jenis Protokol

Protokol sekarang ini yang banyak digunakan dalam internet adalah Transmission Control Protocol (TCP) dan User Datagram Protocol (UDP). Socket untuk suatu aplikasi tertentu di identifikasi dengan nomor port, .  TCP atau UDP merupakan protokol ditingkat application layer, keduanya menggunakan Internet Protocol (IP) untuk mengenali / mengidentifikasi alamat mesin.  TCP/IP terdiri dari dua bagian yaitu alamat IP yang mengidentifikasi mesin dan port yang mengidentifikasi suatu jenis aplikasi yang berjalan di mesin tersebut.Nomor port adalah bilangan bulat dari 1 keatas. Port antara 1 dan IPPORT_RESERVED (yang di definisikan di /usr/include/netinet/in.h -- biasaya 1024) yang disediakan system untuk digunakan(anda harus root jika ingin membuat server dan bind port).
 
Dua jenis tipe internet socket tersebut biasa disebut juga Stream Sockets (SOCK_STREAM) dan Datagram Sockets (SOCK_DGRAM).  Datagram Sockets, yang menggunakan TCP sebagai protokol, memiliki sifat error free (karena ada mekanisme pengecekan kesalahan), data dikirimkan dibundel dalam satu grup disebut datagram.  Sedangkan Stream Sockets, yang menggunakan UDP sebagai protokol, sangat riskan terhadap error dan sering disebut sebagai connectionless artinya socket ini selalu terbuka dan siap menerima informasi tanpa harus ada mekanisme membuka koneksi dengan sifat ini informasi bisa lebih cepat dibanding datagram socket karena data dikirim perkarakter.
 
Aplikasi sederhana dari networking adalah client-server model. Sebuah proses server menunggu koneksi dari suatu client proses. Ketika koneksi terjadi maka Socket interproses comunication (IPC) 
 
Untuk membuat sebuah aplikasi server dengan menggunakan BSD
interface, maka diperlukan langkah2 berikut:
 
1.    Membuat socket baru dengan fungsi socket() 
2.    mem-bind suatu alamat (alamat Ip dan nomor port) ke socket dengan   fungsi bind()Langkah ini mengidentifikasi server sehingga client tau kemana dia harus pergi.  
3.    Listen (mendengarkan) apakah ada request koneksi baru di socket dengan fungsi listen() 
4.    Menerima koneksi baru dengan fungsi accetpt()
 
Biasanya service/layanan pada server harus disediakan dalam jangka waktu lama, dan harus bisa menerima koneksi atau memberikan beberapa layanan sekaligus. Untuk itu server harus dapat menerima dan memproses koneksi baru ketika dia sedang menjalankan proses dari koneksi yang lain.  Untuk dapat melakukan hal tersebut maka biasanya implementasi server dilakukan dengan fork atau pencabangan, sehingga server melakukan pencabangan yaitu membuat proses (thread) baru yang mendengarkan koneksi baru bersamaan ketika server
meng-accept suatu koneksi. Inilah yang disebut multithreading, sebuah komputer melakukan beberapa proses sekaligus dalam waktu bersamaan, satu thread memproses inforsi yang sudah datang dan thread yang lain tetap sebagai proses menunggu koneksi baru. 

Analogi yang Baik

 
Cara yang sering digunakan untuk menjelaskan proses komunikasi dengan socket adalah dengan analogi komunikasi telepon.  Bayangkan jika seseorang dalam satu kantor, jika ia ingin dapat berkomunikasi dengan telpon tentu saja yang pertama harus ia punyai adalah telpon. Dalam komunikasi socket berarti anda harus punya atau mebuat soket yaitu dengan memanggil fungsi socket(). Setiap telpon memiliki nomor yang unik untuk dapat dikenali dan jika dalam satu ruangan ada beberapa telpon dengan satu alamat kita biasa menggunakan nomor ektensi untuk itu. Ini serupa dengan pengalamatan socket dimana socket diberi nomer/alamt berupa AF_INET yaitu alamat utama yang penting untuk komunikasi antar komputer. Pemberian alamat ini dilakukan dengan pemanggilan fungsi bind().
 
AF_INET adalah nomor IP (IP address) yang terdiri dari 4 byte nomer yang dipisah dengan titik, misalnya 167.205.26.12 (ini berlaku untuk penglamatan menggunakan standar IPv4, standar baru IPNG atau IPv6 agak berbeda dan tidak akan dibahas disini). Pengalamatan jenis lain untuk socket adalah AF_UNIX yang penting untuk komunikasi pada satu komputer, ini seperti nomor ekstensi pada contoh telppon tadi sehingga dalam satu jaringan telpon kantor tadi hanya diperlukan identifikasi nomor ekstensi saja yang mepercepat proses koneksi. 
 
Jika satu nomor ekstensi melayani suatu service yang diberikan orang tertentu misalnya satu nomor ekstensi untuk orang di bagian pemasaran dan yang lain di bagian produksi, maka nomor ekstensi tersebut dapat diidentikkan dengan dengan nomer port.  Agar satu komputer dapat melayani beberapa komunikasi sekaligus dengan fungsi  yang berbeda, maka tiap socket yang ada diidentifikasi dengan nomor  tambahan yang spesifik untuk service tertentu dengan nomor port.  
 
Satu nomor port misalnya melayani tranfer email, sedangkan yang lain memberikan service web. 
 
Identitas lain iyang penting saat pembuatan socket adalah jenis/tipe socket, yaitu stream socket atau datagram socket.  seperti telah dijelaskan diatas. Pilihlah tipe socket yang sesuai kebutuhan. 
 
Setelah telpon terinstal maka yang dilakukannya adalah menunggu sambungan, dalam socket ini dilakukan dengan fungsi listen(). Jika terjadi sambungan dan telpon akan diterima untuk memulai komunikasi maka kita memberikan fungsi accept() pada analogi komunikasi socket.
 

Pembuatan Socket

 
Pembuatan socket dilakukan dengan menggunakan system call socket() System call ini didefinisikan di header file socket.h, dan kebanyakan fungsi2 atau system call pada pemrograman socket didefinisikan pada file header tersebut. Untuk itu jangan lupa untuk mendeklarasikannya 
 
#include 
#include 
 
Sytem call socket memiliki prototipe sebagai berikut:
int socket(int domain, int type, int protocol);
nilai balik (return value) dari system call ini adalah -1 jika terjadi error saat pembuatan socket dan domain adalah address dari domain 
 
create INTERNET,TCP socket
        
        int sock;
        sock = socket(AF_INET,         /* 
                     SOCK_STREAM,     /* tipe koneksi */
                     0);              /*
 
handle error
 
        if ( sock < 0 ) { /* ERROR */ }
 

Pengalamatan (binding)

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
int getsockname(int  s , struct sockaddr * name , socklen_t * namelen )
 
pendefinisian tipe soket
 
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
 
atau
 
server. sin_ addr = htonl( INADDR_ ANY );
 
pendefinisian nomor port spesifik yang digunakan
        
constant int TCPPORT=89;
server.sin_port = htons(TCPPORT);
 
binding protocol to socket
 
if (bind(sock, &server, sizeof(server))) { /* ERROR */ }
 

Siap menerima koneksi

int listen( int sockfd, int backlog);

Penerimaan Koneksi

int accept(int s, struct sockaddr *addr, int *addrlen);
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

Implementasi (let's code dude..!!)

(akan ditulis nanti..)
Ini sebuah contoh program server yang akan jalan untuk menunggu koneksi:
 
/*
 * @file: tcpserver.c
 *
 */
 
#include 
#include 
#include 
#include 
#include 
 
#define TRUE 1
#define FALSE 0
 
#define TCPPORT 10000          /* server port value */
#define BUFSIZE 1024           /* size of i/o buffer */
#define NOREADS 10             /* number of buffers transferred */
 
main(int argc,char **argv)
{
        int sock;
        int size;
        char buf[BUFSIZE];
        int msgsock;
        struct sockaddr_in gotcha;
        int rc;
        int i;
 
        sock = initSocket();
 
        /** tcp starts listening for connections */
        rc = listen(sock,5);
        if ( rc < 0) {
        perror("listen"); exit(1);
   }
 
        /** accept one connection, will block here. */
        size = sizeof (struct sockaddr_in);
 
        msgsock = accept(sock, &gotcha, &size);       
        if (msgsock < 0 ) { perror("accept"); exit(1); }
 
        /* read and echo so many packets      */
        for ( i = 0; i < NOREADS; i++) {
               doRead(msgsock, buf, BUFSIZE);
               rc = write(msgsock, buf, BUFSIZE); 
               if ( rc < 0 ) {
                       perror("write");
                       exit(1);
               }
        }
 
        /* close sockets
        */
        close(msgsock);
        close(sock);
 
        return(0);
}
 
initSocket()
{
        struct sockaddr_in server;
        int sock;
 
        /** create INTERNET,TCP socket */
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if ( sock < 0 ) {
        perror("socket"); exit(1);
   }
 
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = htons(TCPPORT);      /* specific port */
 
        /** bind protocol to socket    */
        if (bind(sock, &server, sizeof(server))) {
        perror("bind"); exit(1);
   }
        return(sock);
}
 
doRead(int sock,char *buf,int amountNeeded)
{
        register int i;
        int rc;
        char *bpt;
        int count = amountNeeded;
        int amtread;
 
        bpt = buf;
        amtread = 0;
 
again:
        if ( (rc = read(sock,bpt,count)) < 0 ) {
               perror("doRead: reading socket stream");
               exit(1);
        }
        amtread += rc;
 
        if ( amtread < amountNeeded ) {
               count = count - rc;    
               bpt = bpt + rc;
               goto again;
        }
}
 
/* end of file : tcpserver.c */
 
Dan ini contoh file client yang akan menghubungi server diatas:
 

Sedikit Tentang Trojan dan atau Backdoor

 
Trojan dan backdoor adalah dua istilah yang berbeda yang sangat familiar dalam dunia hacking tepatnya cracking. Tapi keduanya memiliki kesamaan, Trojan lebih sering digunakan untuk menyebut program yang digunakan sebagai "remote control" komputer korban, sedangkan backdoor untuk menyebut program yang digunakan untuk mebuka koneksi lewat jalan yang tidak diketahui terutama untuk tetap menyimpan jalan lain jika akses2 lewat jalan yang normal ditutup. Untuk definisi yang lebih pasti lihat JARGON dictionary file.
 
Pembuatan backdoor yang mudah adalah dengan menggunakan stream socket. (Yang lebih mudah lagi adalah dengan memanfaatkan program inetd daemon yang sudah ada, dengan program ini anda tidak memerlukan kemampuan pemrograman untuk membuat backdoor.  Dengan daemon tersebut kita dapat mebuka socket dengan port tertentu hanya dengan option tertentu atau menambahkan pada file konfigurasinya.  Hal ini sama saja jika kita menggunakan program yang "serupa" seperti tcpserver.  Tapi backdoor tersebut tentu saja akan mudah diketahui oleh admin yang berpengalaman). 
 
Kita tidak akan membahas pembuatan (kata pembuatan sepertinya tidak tepat untuk backdoor/trojan berbasis program lain seperti inetd atau tcpserver) backdoor seperti itu. Kita akan membuat dengan kemampuan pemrograman socket dari tutorial tadi sebuah program/daemon proses  baru yang sederhana/kecil. Dengan program baru ini kita berlatih untuk mengimplementasikan kemampuan pemrograman kita. Membuat backdoor berarti kita akan membuat sebuah program pada server dan pada client. Program server biasanya dimpan pada komputer korban, dan program client dipakai di komputer kita sebagai remote controller.
 
Baiklah kita akan memulai, dengan program server.  Aspek2 yang penting dalam membuat backdoor pada server diantaranya, 
 
1.    Pemilihan nama program yang tidak mencurigakan,atau lebih baik    jika program dapat dilihat dengan nama proses yang berbeda dari sebenarnya.  Cara lain untuk menyembunyikan proses adalah dengan menggunakan rootkit, yaitu, biasanya mengganti program standar untuk melihat proses (perintah ps) dengan program yang serupa tapi tak sama =) sehingga proses yang ingin kita hidden menjadi tidak telihat. Hal ini penting karena program kita akan berjalan terus sebagai daemon.
2.    Pemilihan port yang 'aneh'. Hmmm.. aneh disini tidak perlu memilih port bilangan yang tidak biasa misalnya 6732 tapi bisa dengan "justru" memilih port yang sangat umum yang tidak digunakan. Misalnya server itu tidak menggunakan port 110 untuk POP3 service maka port kita dapat mengambil port tersebut danmudah2an adminya lupa sehingga dia merasa dia sendiri yang membuka port tersebut untuk keperluan POP3. Dengan begini program backdoor kita dapat kita berinama juga yang sesuai misalnya qpopper..
3.    Program utama untuk mengakses shell atau untuk membuat shell baru Backdoor dapat sangat simpel yaitu dengan memberikan program utama kita hanya suatu akses pada perintah tertentu misalnya pembuatan user shell baru yang kemudian akan diakses dengan cara biasa (misalnya telnet) atau berisi program ekseskusi eksploit sehingga membuka jalan lain ke akses shell. Sedangkan trojan akan lebih kompleks   sebab dibutuhkan akses ke beberpa perintah standar UNIX yang penting atau akses langsung ke shell.
4.    Pembatasan akses pada backdoor kita. Artinya perlu ada mekanisme kontrol sehingga backdoor kita tidak digunakan politikus2 tak bermoral, pemeras yang hanya memikirkan diri sendiri dan mengabaikan hak-hak orang lain. Tetapi justru backdoor kita gunakan untuk mengontrol mereka, untuk itu kita perlu lebih pintar dari mereka. Perlu adanya proteksi atau authentifikasi misalnya password protection pada backdoor kita. Perlu diingat jangan berpikir terlalu muluk, justru kadang dengan hal-hal kecil yang sangat simpel kita dapat lebih "cerdik" dari orang lain.
 
Jadi ngelantur banyak nih, ok ini cuma sekedar tips "hacking," tips lainnya dapat anda tanyakan pada insting sendiri.

Populer Post