Scapy etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Scapy etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

24 Eylül 2015 Perşembe

Python ile Packet Sniffing

Merhaba Arkadaşlar,

Bugün python script dili ile sniffer scripti hazırlamanın aşamalarını anlatacağım. İki farklı yöntemden bahsedeceğim; Birincisi herhangi bir kütüphaneden faydalanmadan bir sniffer nasıl yazılır sorusuna cevap vermeye çalışacağım.İkincisi ise daha önceden bahsetmiş olduğum Scapy kütüphanesini kullanarak bir sniffer hazırlamanın nasıl olduğunu göstereceğim.

Daha önce yayınlamış olduğum Python ile Socket programlama ve Scapy ile Host ve Port Tarama yazılarım konuya aşinalık kazanmak isteyen arkadaşlara faydalı olabilir. Aşağıdaki bağlantılardan bu yazılara ulaşabilirsiniz.

http://msesli.blogspot.com.tr/2015/06/python-ile-socket-programlama.html

http://msesli.blogspot.com.tr/2015/06/scapy-ile-host-ve-port-tarama.html

Teknik detaylara geçmeden önce bir packet sniffer'ın  nasıl çalıştığından bahsedelim. Packet sniffer belirlenen bir veya daha fazla ağ arayüzüne gelen paketleri yakalar. Bir ağ arayüzü sadece kendisini ilgilendiren paketleri dikkate almak için yapılandırılmıştır. Bütün paketlerin yakalanabilmesi için sniffer aracımız, ilgili ağ arayüzünü promiscous mode'a getirir. Promiscous mode, ağ arayüzünün paketleri herhangi bir kritere tabi tutmadan kabul ettiği çalışma modudur. Ağ arayüzünü bu çalışma mode'una almak için  yönetici yetkilerine sahip olunmalıdır.

Bir sniffer aracının çalışma prensibini özetlediğimize göre artık pyhton ile kendi aracımızı yazmaya başlayabiliriz.

import socket
import os
host="192.168.76.132"
if os.name=="nt":
      socket_protocol = socket.IPPROTO_IP
else:
      socket_protocol = socket.IPPROTO_ICMP
sniffer = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol)
sniffer.bind((host,0))
sniffer.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)
if os.name=="nt":
      sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
while True:
      print sniffer.recvfrom(65565)
if os.name=="nt":
      sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)

Satır satır kodumuzu inceleyecek olursak, ilk iki satırda işimize yarayacak modülleri scriptimize dahil ediyoruz. Daha sonra dinleme yapacak sistemin ip adresini "host" değişkenimize atıyoruz. Sonraki aşamada Linux ile Windows sistemlerdeki bir farklılıktan dolayı bir işletim sistemi sorgusu yapıyoruz. Eğer işletim sistemi Windows ise protokolden bağımsız bütün IP paketlerini yakalayabiliyoruz, eğer işletim sistemi Linux ise sadece ICMP paketlerini yakalayabiliyoruz. Sniffer aracımız bir sunucu gibi çalışacağı için önce bir socket oluşturuyoruz ve "host" değişkenimizde tuttuğumuz IP adresimize bu sunucuyu bağlamış oluyoruz. Bir sonraki aşamada yakalayacağımız paketlerin IP başlıklarının paketlere dahil edilmesini aktif ediyoruz. Eğer Windows işletim sisteminde isek ağ arayüzünü promiscous mode'da çalışmasını sağlıyoruz. Yakaladığımız paketleri ekrana yazdırmak için bir sonsuz döngü yarattıktan sonra yine eğer Windows sistemde isek ağ arayüzünü promiscous mode'dan çıkarıyoruz.

Yukarıdaki kodu bir metin editörü ile dosya açıp içine kopyalıyoruz ve "py" formatında kaydediyoruz. Daha sonra bu scripti çalıştırılabilir hale getirip çalıştırıyoruz. Aşağıdaki komutlarla bu işlemleri gerçekleştiriyoruz.

#nano sniffer.py
#chmod +x sniffer.py
#python sniffer.py

Scriptimiz çalıştıktan sonra yakalanacak paketleri bekliyor, farklı bir terminalden www.google.com adresine ping attığımızda bu paketlerin aracımız tarafından yakalandığı görülür. Ekran görüntüsü 1' den de görüceleği gibi bu yakalanan paketlerdeki veriler RAW data denilen ham halde elde edilmektedir. Tcpdump gibi profesyonel bir araçtaki bu paketleri görüntülemek için bu verileri decode işlemine tabi tutmamız gerekir ya da Scapy kütüphanesinin bize sağladığı imkanlardan faydalanmamız gerekir.

Ekran Görüntüsü 1: Yakalanan paketler

from scapy.all import *

def packet_capture(packet):
      print packet.show()
packet=sniff(prn=packet_capture)
wrpcap('sniffedpackets.pcap',packet)

Scapy kütüphanesi bu aşamada işimiz oldukça rahatlatacak. Kodumuzu inceleyecek olursak ilk önce scapy kütüphanesini scriptimize dahil ediyoruz. Daha sonra yakaladığımız paketlere yapacağımız işlemleri tanımlayacağımız methodu oluşturuyoruz. Pakete yapacağımız işlem ise verileri ekrana yazdırmak.Sonraki satırda yakaladığımız paketleri "packet" değişkenimizde tutuyoruz. Ardından bu paketleri "packet_capture" methodumuza yolluyoruz ve ayrıca"sniffedpackets.pcap" dosyasına yazıyoruz. Benzer şekilde bu scripti çalıştırılabilir hale getirip çalıştırıyoruz. www.google.com adresine ping atıp scriptimizin çalıştığı konsola geri döndüğümüzde anlık olarak yakalanan paketleri görebiliriz. Tabiki Wireshark ya da tcpdump gibi profesyonel araçlardaki gibi okunabilirlik söz konusu olmasa da ham veriden daha okunabilir olduğu söylenebilir. "Ctrl+C" kombinasyonuyla scriptin çalışmasını durduğumuzda "sniffedpackets.pcap" dosyası oluşturulur.

Ekran Görüntüsü 2:Yakalanan Paketlerin Konsolda incelenmesi

Yakalanan paketleri hem konsolda hemde "sniffedpacket.pcap" dosyasını Wireshark'ta açarak inceleyebiliriz. Konsoldaki çıktıya baktığımızda daha öncedeki yazılarımda da kullandığım Scapy programının çıktıları ile karşılaşıyoruz. Paketle ilgili parametreleri gayet net bir şekilde görebildiğimizden detaylı incelemeleri gerçekleştirebiliyoruz. Bundan daha iyisi tabiki bu paketleri Wireshark programı ile incelemek. Ekran Görüntüsü 3'te görülebileceği gibi Wireshark ile yakalanmış gibi ayrıntılı paket analizi yapmak mümkün.



Ekran Görüntüsü 3:Yakalanan Paketlerin Wireshark'ta İncelenmesi

Bugün bir sniffer aracı nasıl çalışır ve python ile bir sniffer aracı nasıl yazılır sorularının cevaplarını vermeye çalıştım. Scapy kütüphanesinin python ile program geliştiricilerinin işini ne kolaylaştırdığını bir kez daha görmüş olduk. Her ne kadar programımız Wireshark kadar profesyonel olmasa da, Wiresharkı çalıştırmamızın mümkün olmadığı ya da kaynak sıkıntısı çektiğimiz ortamlarda (Raspberry Pi vs.) işimize yarar bir araç geliştirmiş olduk. Bir sonraki yazıda görüşmek üzere.

Yararlandığım Kaynak:
Justin SERTZ,"BLACK HAT PYTHON"

16 Haziran 2015 Salı

Scapy ile Host ve Port Tarama

Merhaba Arkadaşlar,

Bu yazıda, scapy programı ile host ve port tarama işleminin nasıl gerçekleştirildiğini anlatacağım. "NMAP varken neden Scapy ?" diye sorduğunuzu duyuyorum şimdiden. Python ile kendi tarama araçlarımızı nasıl yazabileceğimizi anlatan birkaç yazı paylaşmayı planlıyorum. Bu araçların nasıl çalıştığını anlatmadan böyle bir işe başlamak istemedim. Nmap, oldukça profesyonel bir araç(araç demek bile hakaret aslında) ancak scapy ile TCP,UDP,IP gibi yeni başlayanlar için soyut kavramların, nasıl detaylı bir şekilde incelenip, bu paketlerin hazırlanabildiğini göstermeye çalışacağım.

Bugün host tarama işlemini ve port tarama işlemini gerçekleştireceğiz. Host tararken katman 2 yada katman 3'te çalışabiliriz. Bunu şu şekilde gerçekleşecek; elimizdeki IP adresinin ağda aktif olup olmadığını ARP paketleri göndererek veya ICMP paketleri göndererek öğrenebiliriz. Port tarama işleminde ise Katman 4'te çalışacağız. TCP ve UDP paketleri hazırlayıp, hedef IP adresinden gelen veya gelmeyen cevap paketlerini yorumlayarak taradığımız portun açık olup olmama durumunu öğreneceğiz.

Scapy programını Kali'de konsola scapy yazarak başlatıyoruz.

Ekran Görüntüsü 1: Scapy programının başlatılması

Scapy programı başlattığımızda bizi programın shell'i karşılıyor. ARP protokolüyle host tarama işlemine geçmeden önce bir ARP paketinin hangi parametrelere sahip olduğunu inceleyelim. Bunun için Scapy programının shell'inde şu komutu giriyoruz.

>>ARP().display()

Ekran Görüntüsü 2: ARP Paketi Parametreleri

Paketi incelediğimizde, "hwsrc" bizim MAC adresimizi, "psrc" ise bizim IP adresimizi temsil ediyor. Benzer şekilde "hwdst" hedef MAC adresini, "pdst" ise hedef IP adresini temsil ediyor. Kısaca ARP protokolünden bahsedecek olursak bir bilgisayar ağda başka bir bilgisayarla haberleşebilmek için IP adresinin yanında MAC adresini de bilmesi gerekir. MAC adresini öğrenebilmek için bütün ağa haberleşmek istediği bilgisayarın IP adresinin hangi MAC adresli cihaza ait olduğunu soran ARP Request paketleri yayınlar. Bu paketi alan hedef IP adresine sahip cihaz kendi MAC adresini bildiren paketi, isteği yapan bilgisayara gönderir. Böylece bilgisayarların haberleşmesi için gerekenler sağlanmış olur. Host tararken bu protokolü şu şekilde kullanacağız. Ağda aktif olup olmadığını öğrenmek istediğimiz IP adresini "pdst" parametresine gireceğiz, "hwdst" yani hedef MAC adresini boş bırakarak bu paketi bütün ağa yayınlayacağız. Eğer bize bir cevap paketi gelirse yani taradığımız bilgisayar kendi MAC adresini bize gönderirse, burdan anlayacağız ki bu IP adresine ait bilgisayar ağda aktif. Şimdi uygulamaya geçelim.

>> arp_request=ARP()
>> arp_request.pdst="192.168.2.5"
>> arp_request.display()

Yukarıdaki komutlar şu anlama geliyor. İlk komutla bir ARP paketi oluşturuyoruz ve arp_request adıyla bu paket üzerinde işlem yapabiliyoruz. İkinci komut, ARP paketinin hedef IP adresi parametresine, taramak istediğimiz IP adresini atıyoruz. Son olarak yayınlamaya hazır paketi gözlemlemek için display methodunu kullanıyoruz.


Ekran Görüntüsü 3: ARP paketinin hazırlanması

>> response=sr1(arp_request)
sr1 methodu paketi gönderip, cevabı almamızı sağlıyor. Bu methodun döndürdüğü değeri response isimli değişkende tutuyoruz.
>> response.display()

Dönen cevap paketini incelediğimizde, taradığımız IP adresini ve sahip olduğu MAC adresini görebiliyoruz. Aslında bu paketin varlığı bile hostun aktif olduğu anlamına geliyor.

Ekran Görüntüsü 4: ARP cevap paketi

Bu işlemi  gerçekleştirirken, bir IP paketi oluşturacağız ve bu paketin içine bir ICMP paketi yerleştireceğiz. Taramak istediğimiz IP adresine bu paketi gönderip bir cevap bekleyeceğiz. Bu cevap paketi, bu IP adresinin ağda aktif olduğunu kanıtlamış olacak.

>> ip = IP()
>> ip.dst="192.168.2.12"
>> ping= ICMP()
>> ping_request = (ip/ping)
>> ping_request.display()

IP ve ICMP paketlerini oluşturup, ICMP paketini IP paketinin içine atıyoruz ve paketi göndermeden önce display methoduyla paketi görüntülüyoruz. Taramak istediğimiz IP adresini IP paketinin "dst" parametresine atadık.

Ekran Görüntüsü 5: ICMP paketinin hazırlanışı

>> ping_reply=sr1(ping_request)
>> ping_reply.display()

Komutları ile paketi gönderiyoruz ve dönen cevabı görüntülüyoruz. Taramak istediğimiz IP adresinden gelen bu cevap paketi hostun aktif olduğunu gösteriyor.

Ekran Görüntüsü 6: ICMP cevap paketinin gözlenmesi

Scapy ile UDP port tarama işlemini gerçekleştirirken, IP paketinin içine UDP paketini yerleştirip, taramak istediğimiz IP adresinin aktif olup olmadığını öğrenmek istediğimiz portuna gönderiyoruz. Eğer ICMP port-unreacheable cevap paketi gelirse bu port kapalıdır, eğer bir cevap gelmezse port açıktır. Bu yaklaşım çok sağlıklı bir yaklaşım olmasa da, bu yöntemi kullanan araçların nasıl çalıştığını görmek açısından faydalı olduğunu düşünüyorum.

Uygulamayı Vmware ortamında Kali ve Metasploitable2 işletim sistemlerini kullanarak gerçekleştireceğim.

Kalide konsola scapy komutunu girerek programı başlatıyoruz ve aşağıdaki komutları giriyoruz.

>> i= IP()
>> i.dst="192.168.200.130"
>> u=UDP()
>> u.dport=123
>> request=(i/u)
>> request.display()

IP paketimizi hazırladık ve hedef IP adresimizi girdikten sonra UDP paketimizi oluşturup hedef portu 123 (NTP) olarak belirledik. "request" değişkeni, IP paketinin içine UDP paketimizi yerleştirilmiş halini temsil ediyor. Display methoduyla paketimizi inceleyebiliriz.

Ekran Görüntüsü 7: UDP paketinin hazırlanması

>> response = sr1(request)
>> response.display()

Komutları ile paketi gönderip, cevap paketini incelediğimizde IP paketinin içinde bir ICMP paketinin geldiğini görüyoruz. Bu paketin "port unreachable" mesajı bize taradığımız portun kapalı olduğunu gösteriyor. Eğer bir cevap almasaydık portun açık olduğunu varsayabilirdik.

Ekran Görüntüsü 8: ICMP port unreachable paketi

TCP port tarama işleminde de, yine bir IP paketi oluşturacağız ve bu TCP() paketini içine yerleştireceğiz. Bu paketi hedef IP adresimize göndermeden önce TCP paketinde "flags" parametresini hangi taramayı yapmak istiyorsak ona göre ayarlayacağız ve cevap paketindeki "flags" parametresini yorumlayarak taradığımız portun açık olup olmadığını anlayacağız.

>> i=IP()
>> i.dst="192.168.200.130"
>> t=TCP()
>> request= (i/t)
>> request.display()

Daha öncekilere benzer şekilde paketimizi hazırladık. Varsayılan olarak TCP paketinin "flags" parametresi "S", "dport" parametresi de http(80) olarak ayarlanmıştır. 

Ekran Görüntüsü 9: TCP paketinin hazırlanması

>> response =sr1(request)
>> response.display()

Komutları ile paketi gönderip, gelen cevap paketini incelediğimizde, TCP cevap paketindeki "flags" parametresinin "SA" olarak ayarlanmış olduğunu görüyoruz. Bu bize taradığımız portun (80) açık olduğunu gösteriyor.

Ekran Görüntüsü 10: TCP cevap paketi

Bu şekilde TCP paketinin "flags" parametresini "F" olarak ayarlayarak FIN taramasıda yapabiliriz. FIN tarama ters mantıkla çalıştığı için kapalı porttan cevap bekleriz. Gelen paketin "flags" parametresi "RA" olarak ayarlanmışsa port kapalı olduğunu anlarız.

Ekran Görüntüsü 11: FIN tarama
Yukarıdaki ekran görüntüsünü incelediğimizde, hedefin 511 nolu portuna FIN taraması gerçekleştirdiğimizde, cevap paketinin "flags" parametresi "RA" olarak ayarlanmış yani port kapalı. Açık bir porta bu taramayı yaptığımızda bir cevap paketi almayız.

Toparlayacak olursak, host ve port tarama işlemlerinin gerçekleştirilmesinde ilk tercih olarak genelde nmap programı kullanılıyor olsa da scapy programı bu işlemlerin ağ trafiğinde nasıl gerçekleştiğini anlamamıza yardımcı oluyor. Wireshark programı ile tarama sırasında ağ trafiğini inceleyerek de bu işlemler takip edilebilir. Bundan sonraki yazılarımda, python'da kullanacağım scapy kütüphanesinin methodlarını ve parametrelerini de tanımış olduk. Umarım faydalı bir yazı olmuştur. Bir sonraki yazıda görüşmek üzere.



Yararlandığım Kaynak:

Justin Hutchens,"Kali Linux Network Scanning Cookbook"