Socket Programming dengan Bahasa C (Linux) -------------------- author: mywisdom thanks to: flyf666,gunslinger,petimati,peneter,ketek,chaer,wenkhairu,wahyu,n0te,blackn0te,kumbang,ade yonatan,v3n0m and all devilzc0de crew and members --------------------- pembahasan : pembuatan klien dan server tcp dan udp(c), penggunaan SOCK_RAW untuk spoofing source address (c), Kali ini kita akan membahas tentang socket programming dengan bahasa c . * alat-alat yang diperlukan - gcc ==========SOCKET PROGRAMMING DENGAN BAHASA C===================== socket programming merupakan pemrograman yg bertujuan agar program yang satu bisa berkomunikasi dg program lainya dalam suatu jaringan komputer / internet bisa juga disebut sebagai pemrograman jaringan. * TCP Socket Programming A. TCP Client Kita akan mulai dengan membuat suatu program klien dg bahasa C yang bertujuan untuk melakukan koneksi TCP port 80 ke devilzc0de.org dan melakukan http request. ok mari kita liat dulu kira 2 seperti apa kira2 bentuk dari suatu http request, krn sy gak apal -------------------- tes nc listen port 3339 lalu akses dengan web browser via alamat : http://localhost:3339 # nc -l -p 3339 -vvv listening on [any] 3339 ... connect to [127.0.0.1] from myw1sd0m.org [127.0.0.1] 46545 GET / HTTP/1.1 Host: localhost:3339 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.15) Gecko/2009102814 Ubuntu/8.10 (intrepid) Firefox/3.0.15 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.8,zh-cn;q=0.7,zh;q=0.5,zh-tw;q=0.3,zh-hk;q=0.2 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive sent 0, rcvd 478 ----------------- ok kurang lebih bentuknya seperti di atas berikut ini adalah kode c untuk tcp client kita yang akan melakukan simulasi http request: --------------------------- /**sample tcp client by mywisdom currently devilzc0de coder **/ #include #include #include #include #include #include #include #include #include #include #include #define RCVBUFSIZE 9999 /**kurang lebih di bawah ini adalah bentuk dari suatu http request dengan browser mozilla**/ #define EXPLOIT "GET / HTTP/1.0\nHost: devilzc0de.org:80\nUser-Agent: Mozilla/5.0\nAccept: text/html\nKeep-Alive: 300\n\n" int main() { //echo buffer merupakan karakter dengan panjang 9999 char echobuf[RCVBUFSIZE]; int soket,bytesrcv, totalbytes; //struktur hostent bisa dilihat di /usr/include/netdb.h , berguna untuk mengirimkan dns query //cara kerja dns bisa anda baca di http://myw1sd0m.blogspot.com/2011/04/added-dns-amplification-attack-module.html struct hostent *target; struct sockaddr_in server; if((target=gethostbyname("devilzc0de.org")) == NULL) { printf("\n[-]fungsi gethostbyname gagal ! keluar dari program ! \n"); exit(1); } else { //di sini kita telah berhasil mendapatkan ip address dari devilzc0de.org (ip resolved) printf ("\n[+]fungsi gethostbyname berhasil, ip devilzc0de.org adalah: %u.%u.%u.%u\n",(unsigned char)target->h_addr[0],(unsigned char)target->h_addr[1],(unsigned char)target->h_addr[2],(unsigned char)target->h_addr[3]); } //selanjutnya kita akan menciptakan socket if((soket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } else { printf ("\n[+]di sini file deskriptor telah siap !! selanjutnya kita akan melakukan fungsi connect\n"); } //kita isi struktur sockaddr_in, berupa sin_family=AF_INET untuk koneksi TCP/IP. sin_addr data alamat ip,sin_port berisi nomor port server.sin_family=AF_INET; server.sin_addr.s_addr=*(long *)(target->h_addr); server.sin_port=htons(80); //setelah itu kita akan mencoba memanggil fungsi connect() untuk terhubung ke server if(connect(soket, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) { printf("\n[-]koneksi ke devilzc0de.org via port 80 gagal\n"); exit(1); } else { printf("\n[+]fungsi connect() ke devilzc0de.org via port 80 berhasil !!! selanjutnya kita akan bermain di send dan recv\n"); } //di sini kita kirimkan variabel konstan EXPLOIT yang udah didefinisiin di atas yg isinya meniru2 http request normal if(send(soket, EXPLOIT,9999,0)==-1) { printf("\n[-]gagal send!!! program keluar !!!\n"); exit(1); } else { totalbytes=0; while (totalbytes < RCVBUFSIZE) { //kita terima response dari server dengan fungsi recv if ((bytesrcv = recv(soket, echobuf, RCVBUFSIZE - 1, 0)) <= 0) { printf("\n[-]menunggu sampai data response dari server kita terima\n"); } else { totalbytes += bytesrcv; echobuf[bytesrcv] = '\0'; } totalbytes++; } } if(echobuf) { printf("\n[+]di bawah ini adalah kiriman data dari server : \n"); printf(echobuf); } printf("\n[+]selanjutnya akan kita akhiri dengan fungsi close dan program berakhir !!!\n"); close(soket); } -------------------------------- selanjutnya kita simpan misal dg nama browse.c lalu compile dan jalankan: ------------------------------------------ # gcc -o browse browse.c browse.c: In function 'main': browse.c:87: warning: format not a string literal and no format arguments # ./browse [+]fungsi gethostbyname berhasil, ip devilzc0de.org adalah: 119.235.27.196 [+]di sini file descriptor telah siap !! selanjutnya kita akan melakukan fungsi connect [+]fungsi connect() ke devilzc0de.org via port 80 berhasil !!! selanjutnya kita akan bermain di send dan recv [-]menunggu sampai data response dari server kita terima [-]menunggu sampai data response dari server kita terima .....cutted............ [+]di bawah ini adalah kiriman data dari server : HTTP/1.1 301 Moved Permanently Date: Mon, 18 Apr 2011 22:03:02 GMT Server: Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8q DAV/2 mod_fcgid/2.3.6 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 X-Powered-By: PHP/5.2.15 Location: http://www.devilzc0de.org Content-Length: 0 Connection: close Content-Type: text/html [+]selanjutnya akan kita akhiri dengan fungsi close dan program berakhir !!! ---------------------------------------------- ok mari kita bahas tentang arti kode2 c di atas, pada dasarnya program di atas menggunakan fungsi2 berikut ini secara berurutan: -gethostbyname() -> fungsi ini akan mengisi struktur hostent coba anda lihat file netdb.h di /usr/include/netdb.h , di situ ada keterangan jelas tentang struktur hostent, yg merupakan struktur yang menyimpan data hostname, alias, dll. -------------------------------------------- /* Description of data base entry for a single host. */ struct hostent { char *h_name; /* Official name of host. */ char **h_aliases; /* Alias list. */ int h_addrtype; /* Host address type. */ int h_length; /* Length of address. */ char **h_addr_list; /* List of addresses from name server. */ #if defined __USE_MISC || defined __USE_GNU # define h_addr h_addr_list[0] /* Address, for backward compatibility.*/ #endif }; -------------------------------------------- - socket() -> menciptakan socket (titik akhir komunikasi) dan menentukan protokol yg akan kita pakai selanjutnya mengembalikan FD (file descriptor) untuk fungsi2 socket selanjutnya, diperlukan header : #include dan #include contoh dari penggunaan fungsi socket ini bisa kita lihat di atas: -------------------------------------------------- socket=socket(AF_INET, SOCK_STREAM, 0) ------------------------------------------------- untuk parameter pertama biasa disebut domain / protocol family. yang akan kita pakai. support untuk tiap sistem berbeda-beda, misal di salah satu mesin bisa kita lihat di /usr/include/bits/socket.h : -------------------- sh-3.2# uname -a Linux xxxxxxxxxxxxxxxxxxxxxx 2.6.18-194.32.1.el5 #1 SMP Wed Jan 5 17:52:25 EST 2011 x86_64 x86_64 x86_64 GNU/Linux sh-3.2# cat /usr/include/bits/socket.h -------cutted---- /* Protocol families. */ #define PF_UNSPEC 0 /* Unspecified. */ #define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ #define PF_UNIX PF_LOCAL /* Old BSD name for PF_LOCAL. */ #define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ #define PF_INET 2 /* IP protocol family. */ #define PF_AX25 3 /* Amateur Radio AX.25. */ #define PF_IPX 4 /* Novell Internet Protocol. */ #define PF_APPLETALK 5 /* Appletalk DDP. */ #define PF_NETROM 6 /* Amateur radio NetROM. */ #define PF_BRIDGE 7 /* Multiprotocol bridge. */ #define PF_ATMPVC 8 /* ATM PVCs. */ #define PF_X25 9 /* Reserved for X.25 project. */ #define PF_INET6 10 /* IP version 6. */ #define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ #define PF_DECnet 12 /* Reserved for DECnet project. */ #define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ #define PF_SECURITY 14 /* Security callback pseudo AF. */ #define PF_KEY 15 /* PF_KEY key management API. */ #define PF_NETLINK 16 #define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ #define PF_PACKET 17 /* Packet family. */ #define PF_ASH 18 /* Ash. */ #define PF_ECONET 19 /* Acorn Econet. */ #define PF_ATMSVC 20 /* ATM SVCs. */ #define PF_SNA 22 /* Linux SNA Project */ #define PF_IRDA 23 /* IRDA sockets. */ #define PF_PPPOX 24 /* PPPoX sockets. */ #define PF_WANPIPE 25 /* Wanpipe API sockets. */ #define PF_BLUETOOTH 31 /* Bluetooth sockets. */ #define PF_MAX 32 /* For now.. */ ---------------------cutted------------------------ nama protokol family yg disupport sistem ini bisa kita lihat di kolom ke dua, sedangkan di satu mesin lagi yg 32 bit: root@bt:~# uname -a Linux myw1sd0m.org 2.6.30.9 #1 SMP Tue Dec 1 21:51:08 EST 2009 i686 GNU/Linux root@bt:~# cat /usr/include/bits/socket.h -------------cutted------------- /* Protocol families. */ #define PF_UNSPEC 0 /* Unspecified. */ #define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ #define PF_UNIX PF_LOCAL /* POSIX name for PF_LOCAL. */ #define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ #define PF_INET 2 /* IP protocol family. */ #define PF_AX25 3 /* Amateur Radio AX.25. */ #define PF_IPX 4 /* Novell Internet Protocol. */ #define PF_APPLETALK 5 /* Appletalk DDP. */ #define PF_NETROM 6 /* Amateur radio NetROM. */ #define PF_BRIDGE 7 /* Multiprotocol bridge. */ #define PF_ATMPVC 8 /* ATM PVCs. */ #define PF_X25 9 /* Reserved for X.25 project. */ #define PF_INET6 10 /* IP version 6. */ #define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ #define PF_DECnet 12 /* Reserved for DECnet project. */ #define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ #define PF_SECURITY 14 /* Security callback pseudo AF. */ #define PF_KEY 15 /* PF_KEY key management API. */ #define PF_NETLINK 16 #define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ #define PF_PACKET 17 /* Packet family. */ #define PF_ASH 18 /* Ash. */ #define PF_ECONET 19 /* Acorn Econet. */ #define PF_ATMSVC 20 /* ATM SVCs. */ #define PF_SNA 22 /* Linux SNA Project */ #define PF_IRDA 23 /* IRDA sockets. */ #define PF_PPPOX 24 /* PPPoX sockets. */ #define PF_WANPIPE 25 /* Wanpipe API sockets. */ #define PF_BLUETOOTH 31 /* Bluetooth sockets. */ #define PF_IUCV 32 /* IUCV sockets. */ #define PF_RXRPC 33 /* RxRPC sockets. */ #define PF_MAX 34 /* For now.. */ ------cutted---- jadi bisa kita lihat protokol2 family (domain) yang terinstall di tiap sistem berbeda beda. parameter kedua merupakan jenis socket yg akan dipakai, jenis socket yang dipakai: - SOCK_STREAM -> untuk tipe tcp - SOCK_DGRAM -> untuk tipe udp - SOCK_RAW -> raw protocol biasa dipakai untuk spoofing - SOCK_SEQPACKET -> sequence packet - SOCK_PACKET - SOCK_RDM untuk contoh di atas yg socket(AF_INET, SOCK_STREAM, 0), kita menggunakan AF_INET karena kita akan menggunakan TCP/IP socket, argumen selanjutnya kita isi dengan jenis SOCK_STREAM yang berarti kita akan menggunakan TCP (Connection Stream), dengan argumen protokol 0 atau bisa juga diisi dengan argumen IPPROTO_TCP untuk koneksi TCP. jika socket <0 berarti terjadi kegagalan. - bind() -> bind digunakan untuk mempersiapkan suatu nomor port di lokal secara acak untuk keperluan koneksi kita. - connect() -> digunakan untuk konek ke server, sebelumnya kita harus mengisi dulu struktur dari sockaddr_in server.sin_family=AF_INET; server.sin_addr.s_addr=*(long *)(target->h_addr); server.sin_port=htons(80); kita lihat di file /usr/include/netinet/in.h berikut ini struktur sockaddr_in yang akan kita pakai: untuk kernel2 lama strukturnya langsung keliatan: #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ struct sockaddr_in { short int sin_family; /* Address family */ unsigned short int sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ /* Pad to size of `struct sockaddr'. */ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)]; }; untuk header file di mesin sy saat ini strukturnya sockaddr_in di file /usr/include/netinet/in.h: ------------------- struct sockaddr_in { __SOCKADDR_COMMON (sin_); in_port_t sin_port; /* Port number. */ struct in_addr sin_addr; /* Internet address. */ /* Pad to size of `struct sockaddr'. */ unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)]; }; ---------------------- dari header ini kita tidak melihat adanya sin_family,jika kita lihat lebih jauh ke file /usr/include/bits/sockaddr.h kita bisa melihat makro sbb: -------------------- #define __SOCKADDR_COMMON(sa_prefix) \ sa_family_t sa_prefix##family ---------------------- di mana makro tersebut akan mengambil parameter dari sa_prefix dan menggabungkanya sehingga akan tercipta variabel baru sin_family untuk struktur sockaddr_in ------------- sa_prefix##family-> sin_family -------------- - send() -> fungsi ini berguna mengirimkan data ke server misal: send(soket_klien, "Selamat datang !", 17, 0) soket_klien adl file deskriptor, pesanya:selamat datang, dengan panjang 17 - recv() -> fungsi ini berguna untuk menerima response dari server - close() -> setelah transaksi socket selesai kita tutup file deskriptor dengan fungsi close() untuk lebih jelas tentang fungsi 2 di atas dari shell Anda ketikkan : man socket B. Making TCP Server Setelah memahami cara kerja suatu program klien tcp kita akan mencoba membuat satu tcp server yang akan berjalan di background (daemon) dengan bahasa C yang akan listen di port 80 -------------------------------------------- /***sample server by mywisdom**/ #include #include #include #include #include int main() { int soket,soket_klien,hasil_bind,sin_size,fd; struct sockaddr_in me; struct sockaddr_in klien; //gunakan fungsi fork untuk daemonize di sini (istilah bg process) if((soket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } else { printf("\n[+]socket berhasil dicreate sekarang mari kita lakukan bind port\n"); } //persiapan struktur sebelum bind() me.sin_family = AF_INET; me.sin_addr.s_addr = INADDR_ANY; me.sin_port = htons(80); if(hasil_bind = bind(soket, (struct sockaddr *) &me, sizeof(me))==-1) { printf("\n[-]gagal melakukan bind!!! coba cek apakah port sudah dipakai !!!\n"); exit(1); } else { printf("\n[+]bind berhasil dilakukan!!! selanjutnya kita lakukan listen()\n"); } if(hasil_bind = listen(soket, 5)==-1) { printf("\ngagal listen !!! \n"); exit(1); } else { printf("\n[+]berhasil melakukan listen selanjutnya tinggal looping untuk accept\n"); } char s[16]; while(1) { sin_size = sizeof (klien); soket_klien = accept(soket, (struct sockaddr *)&klien, &sin_size); if (soket_klien == -1) { continue; } else { printf("[+]1 klien terkoneksi !!!\n", s); if (!fork()) { close(soket); } if (send(soket_klien, "Selamat datang !", 17, 0) == -1) { printf("\n[+]jika -1 berarti send gagal !!! \n"); close(soket_klien); exit(1); } close(soket_klien); } } close(soket); } ----------------------- - keterangan urutan - urutan fungsi dasar dari program server di atas adalah : 1. socket if((soket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } kita akan membuat socket,jika socket gagal maka variabel integer soket bernilai -1 jika berhasil =0 selanjutnya kita siapkan struktur untuk bind port 80: //persiapan struktur sebelum bind() me.sin_family = AF_INET; me.sin_addr.s_addr = INADDR_ANY; me.sin_port = htons(80); 2. bind if(hasil_bind = bind(soket, (struct sockaddr *) &me, sizeof(me))==-1) { printf("\n[-]gagal melakukan bind!!! coba cek apakah port sudah dipakai !!!\n"); exit(1); } selanjutnya kita perlu melakukan bind port 80 untuk mempersipkan listen 3. listen if(hasil_bind = listen(soket, 5)==-1) { untuk listen di port 80 sebelum kita menerima accept dari klien 4. accept soket_klien = accept(soket, (struct sockaddr *)&klien, &sin_size); fungsi ini akan mengembalikan nilai 0 jika terjadi klien yg melakukan connect() ke server 5. send() penjelasan fungsi send sudah ada di atas. Ok selanjutnya agar program di atas bisa berjalan di background (daemonize) kita tambahkan fork() kode ini digunakan untuk daemonize if (fork() != 0) { exit(1); } misal bisa kita taruh kode untuk daemonize di atas fungsi socket di program di atas: if (fork() != 0) { exit(1); } if((soket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } kompile dan tes: ------------- root@bt:~/socket# gcc -o daemonize daemonize.c root@bt:~/socket# ./daemonize root@bt:~/socket# [+]socket berhasil dicreate sekarang mari kita lakukan bind port [+]bind berhasil dilakukan!!! selanjutnya kita lakukan listen() [+]berhasil melakukan listen selanjutnya tinggal looping untuk accept root@bt:~/socket# ./klien [+]fungsi gethostbyname berhasil, ip localhost adalah: 127.0.0.1 [+]di sini file descriptor telah siap !! selanjutnya kita akan melakukan fungsi connect [+]fungsi connect() ke localhost via port 80 berhasil !!! selanjutnya kita akan bermain di send dan recv [-]menunggu sampai data response dari server kita terima [-]menunggu sampai data response dari server kita terima --------------cutted here------------------ [+]di bawah ini adalah kiriman data dari server : Selamat datang ! [+]selanjutnya akan kita akhiri dengan fungsi close dan program berakhir !!! root@bt:~/socket# ------------- dari kode di atas kita lihat ada forking untuk menciptakan child process saat ada klien terkoneksi: -------------------------------------- printf("[+]1 klien terkoneksi !!!\n", s); if (!fork()) { close(soket); } --------------------------------------- tujuanya agar server bisa menghandle multiple connection dengan menciptakan child process (forking), Cara ini kurang bagus, untuk lebih bagusnya bisa menggunakan multithreading dengan pthread (/usr/include/pthread.h) * UDP Socket Programming merupakan connectionless socket, implementasi socket udp berbeda dari socket tcp karena di udp tidak ada yg namanya establish !!! (http://www.skullbox.net/tcpudp.php) kali ini kita akan mencoba membuat dulu satu udp server ---------------------- /**udp_server.c dengan port 3333 sample modified from tcp server above**/ #include #include #include #include #include int main() { int soket,soket_klien,hasil_bind,addr_len,udp_con; struct sockaddr_in me; struct sockaddr_in klien; //gunakan fungsi fork untuk daemonize di sini (istilah bg process) //di sini kita menggunakan SOCK_DGRAM untuk tcp tadi kita menggunakan SOCK_STREAM if((soket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } else { printf("\n[+]socket berhasil dicreate sekarang mari kita lakukan bind port\n"); } //persiapan struktur sebelum bind() me.sin_family = AF_INET; me.sin_addr.s_addr = INADDR_ANY; me.sin_port = htons(3333); if(hasil_bind = bind(soket, (struct sockaddr *) &me, sizeof(me))==-1) { printf("\n[-]gagal melakukan bind!!! coba cek apakah port sudah dipakai !!!\n"); exit(1); } else { printf("\n[+]bind berhasil dilakukan!!! selanjutnya kita lakukan looping dan menanti data dengan recvfrom() tanpa listen dan established karena udp adl connectionless protocol !!!\n"); } char s[9999]; addr_len = sizeof(struct sockaddr); while(1) { if((udp_con = recvfrom(soket, s, 9999-1, 0, (struct sockaddr *)&klien, &addr_len)) == -1) { printf("\n[-]recvfrom error !!! keluar dari program\n"); exit(1); } else { printf("[+]fungsi recvfrom bisa dilakukan !!! \n"); } printf("\n[+]Ada paket yang diterima dari recvfrom !!!!\n"); s[udp_con] = '\0'; printf("\n[+] Server menerima string : %s dari klien\n", s); } close(soket); } --------------------------------- misal kita save dengan nama udp_server.c lalu kompile dan jalankan: ======================================= root@bt:~/socket# gcc -o udp_server udp_server.c root@bt:~/socket# ./udp_server [+]socket berhasil dicreate sekarang mari kita lakukan bind port [+]bind berhasil dilakukan!!! selanjutnya kita lakukan looping dan menanti data dengan recvfrom() tanpa listen dan established karena udp adl connectionless protocol !!! ========================================= untuk menguji coba server udp bisa pakai netcat mode udp ke port 3333 ( me.sin_port = htons(3333);): dari klien: ------------------ root@myw1sd0m:~/socket# nc localhost 3333 -u you got pawned ----------------- maka server akan menampilkan pesan dari recvfrom : ---------------- root@bt:~/socket# ./udp_server [+]socket berhasil dicreate sekarang mari kita lakukan bind port [+]bind berhasil dilakukan!!! selanjutnya kita lakukan looping dan menanti data dengan recvfrom() tanpa listen dan established karena udp adl connectionless protocol !!! [+]fungsi recvfrom bisa dilakukan !!! [+]Ada paket yang diterima dari recvfrom !!!! [+] Server menerima string : you got pawned dari klien ----------------- * keterangan udp server Pada udp server di atas kita lihat menjalankan urutan-urutan fungsi kurang lebih sama dg tcp server tapi yg membedakan adl di udp server ini tidak menggunakan listen dan accept, sebagai gantinya , udp server menggunakan recvfrom untuk menerima data klien tanpa melakukan established connection. Urutan2 fungsi yang dijalankan udp server di atas: 1. socket() ---------------- socket(int familt,int type,int proto) ------------- if((soket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } di sini kita membuat menggunakan SOCK_DGRAM (udp) , sedangkan untuk suatu tcp server kita pakai SOCK_STREAM. Sebelumnya variabel socket telah didefinisikan dg tipe integer, int soket, jika return value dari fungsi socket = -1 berarti gagal membuat socket selanjutnya kita siapkan strukturnya untuk bind: //persiapan struktur sebelum bind() me.sin_family = AF_INET; me.sin_addr.s_addr = INADDR_ANY; me.sin_port = htons(3333); di sini kita akan menggunakan port 3333 untuk udp server 2. bind() selanjutnya kita eksekusi bind port 3333 dengan file deskriptor dari soket if(hasil_bind = bind(soket, (struct sockaddr *) &me, sizeof(me))==-1) { printf("\n[-]gagal melakukan bind!!! coba cek apakah port sudah dipakai !!!\n"); exit(1); } jika return <0 berarti gagal melakukan bind, kemungkinan karena port sudah pernah dibind dan file deskriptor untuk port tersebut belum di close 3. recvfrom if((udp_con = recvfrom(soket, s, 9999-1, 0, (struct sockaddr *)&klien, &addr_len)) == -1) { printf("\n[-]recvfrom error !!! keluar dari program\n"); exit(1); } setelah melakukan bind kita lakukan recvfrom untuk menerima data dari klien, untuk keterangan parameter silahkan dilihat di /usr/include/sys/socket.h: --------------------- root@myw1sd0m:~# cat /usr/include/sys/socket.h | grep recvfrom extern ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n, root@myw1sd0m:~# ---------------------- ~MAKING UDP CLIENT~ Ok selanjutnya kita akan mencoba membuat program udp klien yang akan mengirimkan pesan ke port 3333 berikut ini source udp_client.c : -------------------------------- /**sample tcp client by mywisdom currently devilzc0de coder **/ #include #include #include #include #include #include #include #include #include #include #include /**kurang lebih di bawah ini adalah bentuk dari suatu http request dengan browser mozilla**/ #define EXPLOIT "pesan udp\n" int main() { int soket,bytesrcv; //struktur hostent bisa dilihat di /usr/include/netdb.h , berguna untuk mengirimkan dns query //cara kerja dns bisa anda baca di http://myw1sd0m.blogspot.com/2011/04/added-dns-amplification-attack-module.html struct hostent *target; struct sockaddr_in server; if((target=gethostbyname("localhost")) == NULL) { printf("\n[-]fungsi gethostbyname gagal ! keluar dari program ! \n"); exit(1); } else { //di sini kita telah berhasil mendapatkan ip address dari devilzc0de.org (ip resolved) printf ("\n[+]fungsi gethostbyname berhasil, ip localhost adalah: %u.%u.%u.%u\n",(unsigned char)target->h_addr[0],(unsigned char)target->h_addr[1],(unsigned char)target->h_addr[2],(unsigned char)target->h_addr[3]); } //selanjutnya kita akan menciptakan socket if((soket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } else { printf ("\n[+]di sini file deskriptor telah siap !! selanjutnya kita akan melakukan fungsi connect\n"); } //kita isi struktur sockaddr_in, berupa sin_family=AF_INET untuk koneksi TCP/IP. sin_addr data alamat ip,sin_port berisi nomor port server.sin_family=AF_INET; server.sin_addr.s_addr=*(long *)(target->h_addr); server.sin_port=htons(3333); //setelah itu kita akan mencoba memanggil fungsi sendto() untuk mengirimkan sampah kita ke server via port 3333 if((bytesrcv = sendto(soket, EXPLOIT, strlen(EXPLOIT), 0, (struct sockaddr *)&server, sizeof(struct sockaddr))) == -1) { printf("\n[-]gagal mengirimkan sampah ke localhost via port udp : 3333\n"); exit(1); } else { printf("\n[+]ahoy sampah berhasil kita kirim ke localhost via udp port 3333\n"); } printf("\n[+]selanjutnya akan kita akhiri dengan fungsi close dan program berakhir !!!\n"); close(soket); } ------------------------------------------------- untuk mencoba pengiriman string:"pesan udp" via udp port 3333, jalankan udp server: ------------------------------------------------------- root@bt:~/socket# ./udp_server [+]socket berhasil dicreate sekarang mari kita lakukan bind port [+]bind berhasil dilakukan!!! selanjutnya kita lakukan looping dan menanti data dengan recvfrom() tanpa listen dan established karena udp adl connectionless protocol !!! --------------------------------------------------- selanjutnya kita tes pengiriman pesan via port 3333 udp: ------------------ root@myw1sd0m:~/socket# ./udp_client [+]fungsi gethostbyname berhasil, ip localhost adalah: 127.0.0.1 [+]di sini file deskriptor telah siap !! selanjutnya kita akan melakukan fungsi connect [+]ahoy sampah berhasil kita kirim ke localhost via udp port 3333 [+]selanjutnya akan kita akhiri dengan fungsi close dan program berakhir !!! root@myw1sd0m:~/socket# ----------------------------- dari sisi server akan menerima pesan udp jika berhasil: ---------------------- root@bt:~/socket# ./udp_server [+]socket berhasil dicreate sekarang mari kita lakukan bind port [+]bind berhasil dilakukan!!! selanjutnya kita lakukan looping dan menanti data dengan recvfrom() tanpa listen dan established karena udp adl connectionless protocol !!! [+]fungsi recvfrom bisa dilakukan !!! [+]Ada paket yang diterima dari recvfrom !!!! [+] Server menerima string : pesan udp dari klien [+]fungsi recvfrom bisa dilakukan !!! [+]Ada paket yang diterima dari recvfrom !!!! [+] Server menerima string : pesan udp dari klien ---------------------- keterangan: berikut ini adalah fungsi 2 yang dijalankan oleh udp klien di atas untuk mengirimkan string ke udp server: 1. gethotbyname if((target=gethostbyname("localhost")) == NULL) { printf("\n[-]fungsi gethostbyname gagal ! keluar dari program ! \n"); exit(1); } di sini kita akan mencoba melakukan resolve ip localhost dengan fungsi gethostbyname setelah itu kita tampilkan : //di sini kita telah berhasil mendapatkan ip address dari localhost (ip resolved) printf ("\n[+]fungsi gethostbyname berhasil, ip localhost adalah: %u.%u.%u.%u\n",(unsigned char)target->h_addr[0],(unsigned char)target->h_addr[1],(unsigned char)target->h_addr[2],(unsigned char)target->h_addr[3]); cara kerja untuk meresolve, pertama tama akan melihat di /etc/hosts: ----------------------------- root@bt:~/socket# cat /etc/hosts 127.0.0.1 myw1sd0m.org 212.212.212.212 domdomdomdom.org 127.0.0.1 localhost --------------------------- jika entry tidak ditemukan maka query untuk resolve ip dg gethostbyname dilakukan ke luar (/etc/resolv.conf) 2. socket() if((soket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } untuk membuat socket mode udp jika return value = -1 berarti gagal dan program akan keluar (exit(1)) 3. setelah itu kita isi data untuk struktur sockaddr_in server.sin_family=AF_INET; --------------------------------------------> protokol family server.sin_addr.s_addr=*(long *)(target->h_addr); -------------> data ip address server.sin_port=htons(3333); ---------------------------------> nomor port //setelah itu kita akan mencoba memanggil fungsi sendto() untuk mengirimkan sampah kita ke server via port 3333 4. sendto if((bytesrcv = sendto(soket, EXPLOIT, strlen(EXPLOIT), 0, (struct sockaddr *)&server, sizeof(struct sockaddr))) == -1) { printf("\n[-]gagal mengirimkan sampah ke localhost via port udp : 3333\n"); exit(1); } fungsi sendto digunakan untuk mengirimkan string data, di atas terlihat kita mengirimkan isian konstan EXPLOIT ke server. * RAW_SOCK di linux, untuk menggunakan raw_sock diperlukan privilege root, dengan raw socket kita bisa memodifikasi header2 misal yang merupakan favorit dimodifikasi adalah src_port. contoh kode untuk menciptakan raw sock: int rawsock; if((rawsock = socket(PF_PACKET, SOCK_RAW, htons(protocol_to_sniff)))== -1) { perror("Error creating raw socket: "); exit(-1); } *************CATATAN********************** * ctrl+c dan ctrl+z misal di sini kita punya daemon tcp yg run di port 89 -------------------- root@myw1sd0m:~/socket# cat fs.c | grep htons me.sin_port = htons(89); root@myw1sd0m:~/socket# gcc -o fs fs.c root@myw1sd0m:~/socket# ./fs root@myw1sd0m:~/socket# ./fs [+]socket berhasil dicreate sekarang mari kita lakukan bind port [+]bind berhasil dilakukan!!! selanjutnya kita lakukan listen() [+]berhasil melakukan listen selanjutnya tinggal looping untuk accept ^C root@myw1sd0m:~/socket# ./fs [+]socket berhasil dicreate sekarang mari kita lakukan bind port [+]bind berhasil dilakukan!!! selanjutnya kita lakukan listen() [+]berhasil melakukan listen selanjutnya tinggal looping untuk accept ^Z [4]+ Stopped ./fs root@myw1sd0m:~/socket# ./fs [+]socket berhasil dicreate sekarang mari kita lakukan bind port [-]gagal melakukan bind!!! coba cek apakah port sudah dipakai !!! root@myw1sd0m:~/socket# -------------------- untuk eksperimen ini jangan menggunakan ctrl+z untuk menyetop program krn process masih statusnya T distop tanpa menutup file deskriptor, berarti file deskriptor untuk socket masih belum diclose ------------- root@myw1sd0m:~/socket# ps aux | grep fs root 430 0.0 0.0 0 0 ? S< Apr19 0:00 [nfsiod] root 5539 0.0 0.1 4624 2276 ? S Apr19 0:00 /usr/lib/gvfs/gvfsd root 5548 0.0 0.1 4644 2640 ? S Apr19 0:00 /usr/lib/gvfs/gvfs-hal-volume-monitor root 5550 0.0 0.1 4468 2108 ? S Apr19 0:00 /usr/lib/gvfs/gvfs-gphoto2-volume-monitor root 5560 0.0 0.1 4360 2132 ? S Apr19 0:00 /usr/lib/gvfs/gvfsd-burn --spawner :1.20 /org/gtk/gvfs/exec_spaw/0 root 5562 0.0 0.1 20972 2644 ? S Apr19 0:01 /usr/lib/gvfs/gvfsd-trash --spawner :1.20 /org/gtk/gvfs/exec_spaw/1 root 30751 0.0 0.0 1624 320 pts/0 T 02:53 0:00 ./fs root 31405 0.0 0.0 1624 320 pts/0 T 03:03 0:00 ./fs root 31448 0.0 0.0 2016 604 pts/0 R+ 03:03 0:00 grep fs root@myw1sd0m:~/socket# ----------------------- useful links * bgp table lookup https://www.dan.me.uk/bgplookup?asn=17048 * robtex for network mapping http://www.robtex.com referensi http://www.linuxselfhelp.com/gnu/glibc/html_chapter/libc_18.html