Scapy Kurulumu
- $ cd /tmp
- $ wget --trust-server-names scapy.net # veya wget -O scapy.zip scapy.net
- $ unzip scapy-x.x.x.zip
- $ cd scapy
- $ sudo python setup.py install
komutları ile kurulum gerçekleştirilir.
Scapy'i Başlatmak
- Sudo Scapy
komutu ile scapy başlatılır.
Scapy Kullanımı
- from scapy.all import *
Yazının bu aşaması artık tamamen örnekler üzerinden gidecektir.
- ethernet_frame = Ether()
- ethernet_frame.show()
###[ Ethernet ]###
- dst = ff:ff:ff:ff:ff:ff
- src = xx:xx:xx:cb:ed:cd
- type = LOOP
- ethernet_frame = Ether()
- ethernet_frame.src = "aa:bb:cc:dd:ee:ff"
- ethernet_frame.show()
###[ Ethernet ]###
- dst = ff:ff:ff:ff:ff:ff
- src = aa:bb:cc:dd:ee:ff #değişen kısım
- type = LOOP
- ip_packet = IP()
- ip_packet = show()
###[ IP ]###
- version = 4
- ihl = None
- tos = 0x0
- len = None
- id = 1
- flags =
- frag = 0
- ttl = 64
- proto = hopopt
- chksum = None
- src = 127.0.0.1
- dst = 127.0.0.1
- \options \
- ip_packet = IP()
- ip_packet.src = "192.168.1.2"
- ip_packet.dst = "192.168.1.11"
- ip_packet.ttl = 128
- ip_packet.show()
###[ IP ]###
- version = 4
- ihl = None
- tos = 0x0
- len = None
- id = 1
- flags =
- frag = 0
- ttl = 128 #Değiştirdiğimiz kısım
- proto = hopopt
- chksum = None
- src = 192.168.1.2 #Değiştirdiğimiz kısım
- dst = 192.168.1.11 #Değiştirdiğimiz kısım
- \options \
Scapy'de Paket Gönderme ve Veriyi İşleme
Artık bir paketi nasıl manipüle edebileceğimizi biliyoruz, fakat takdir edersiniz ki amacımız sadece bir protokolün içeriğini manipüle etmek değil, aynı zamanda bu manipüle edilmiş paketi göndermektir. Bunun için Scapy bize temel olarak 6 adet fonksiyon kullanma imkanı sağlamıştır. Aşağıda bu fonksiyonları görmekteyiz;
- send()
- sendp()
- sr()
- sr1()
- srp()
- srp1()
send()
Bu fonksiyon sayesinde oluşturduğumuz paketleri cihazımızdaki ethernet kartı veya wireless kartı vasıtası ile iletim ortamına gönderebiliyoruz. Aşağıdaki örneği inceleyelim.
- send(IP(dst="192.168.10.14", src="192.168.10.62")/ICMP()/"Scapy")
- .
- Sent 1 packets.
Tamam buraya kadar her şey güzel fakat, burada syntax açısından biraz farklılıklar var. Kısaca buna değinmekte fayda var. Sadece tek bir protokol yerine birden fazla protokolden oluşan bir network paketini oluşturmak içinTCP/IP protocol yapısını bilmek gerekir. Mesela HTTP isteği sadece HTTP datasından ibaret değildir. Öncelikle bu HTTP datasını kapsülleyen bir TCP datagramı, bu datagramı kapsülleyen IP paketi, IP paketini kapsülleyen bir Ethernet frame’i vardır. Yani yapı şu şekildedir. Ethernet > IP > TCP > HTTP data . Dolayısıyla Scapy’de de paketlerimizi oluştururken bu yapıya dikkat etmemiz gerekmektedir. Örneğimize geri dönecek olursak protokol başlıklarını sırası ile sonuna () koyarak ekledik. Daha sonra / işaretini de kapsülleyici olarak kullandık. Mesela IP() ile ilk olarak IP paketimizin başlığını eklemiş olduk. Daha sonra parametre verme mantığı ile source ve destination adreslerini src ve dst değişkenlerini kullanarak örnekteki gibi değiştirdik. Daha sonra ICMP() ile ICMP başlığını ekledik. Bu ICMP başlığının payload kısmına da verimizi yerleştirdik. Bu kapsülleme işlemlerini de hep / işareti ile yaptık. Tüm bu işlemlerden sonra artık içinde Scapy yazan bir ICMP paketi oluşmuş oldu. Bizim amacımız bu paketi göndermekti. İşte bu paketi de send() fonksiyonumuzun içine yazarak göndermiş olduk. Genel olarak süreç ve yapı bu şekildedir. Gerisi teferruattur. Şimdi aşağıdaki örneğimizi inceleyelim.
- send(IP(dst="192.168.10.14")/ICMP()/"Scapy", loop=1, inter=0.2, verbose=False)
sendp()
Bu fonksiyonumuz ise temel olarak, send() fonksiyonu ile aynı görevi üstlenmektedir. Fakat aralarındaki temel fark şudur; send() fonksiyonu ile Layer 3 düzeyinde işlemler yapabilirsiniz, Layer 2(802.3, 802.11, 802.1q, 802.15..) yani bu örnekteki Ethernet çerçevesinde değişiklik yapamazsınız, bu değerler otomatik olarak Scapy tarafından(dolaylı yoldan işletim sistemi tarafından) doldurulur. Fakat sendp() fonksiyonu ile Layer 2 katmanında da paketlerinizi manipüle edebilirsiniz. Yani Ethernet çerçevesinde istediğiniz değişikliği yapabilirsiniz. Şimdi bu teorik bilgiden sonra aşağıdaki kodumuzu inceleyelim.
Bu fonksiyonumuz ise temel olarak, send() fonksiyonu ile aynı görevi üstlenmektedir. Fakat aralarındaki temel fark şudur; send() fonksiyonu ile Layer 3 düzeyinde işlemler yapabilirsiniz, Layer 2(802.3, 802.11, 802.1q, 802.15..) yani bu örnekteki Ethernet çerçevesinde değişiklik yapamazsınız, bu değerler otomatik olarak Scapy tarafından(dolaylı yoldan işletim sistemi tarafından) doldurulur. Fakat sendp() fonksiyonu ile Layer 2 katmanında da paketlerinizi manipüle edebilirsiniz. Yani Ethernet çerçevesinde istediğiniz değişikliği yapabilirsiniz. Şimdi bu teorik bilgiden sonra aşağıdaki kodumuzu inceleyelim.
- sendp(Ether(src="aa:bb:cc:dd:ee:ff")/IP(dst="192.168.10.14")/ICMP()/"Scapy", count=10, inter=0.2, verbose=False)
sr()
Şimdiye kadar oluşturduğumuz paketlerimizi sadece iletim ortamına göndermekle yetindik. Fakat sadece göndermek bizim için yeterli değil, ağ kartımıza gelen paketleri de değerlendirmek en az göndermek kadar önemlidir. Aslında biz yukarıdaki örneklerde ICMP paketi gönderdirdiğimiz de, cevap olarak bize ICMP Reply paketi gelmektedir, fakat biz o ICMP Reply paketini göremedik ve dolayısıyla o ICMP Reply paketini işleyemedik. İşte bu ICMP Reply paketi gibi bizim ağ kartımızdan gönderdiğimiz pakete cevap olarak gelen paketleri sr() fonksiyonu ile işleme alabiliyoruz. Aynı zamanda sr() fonksiyonu ile paketlerimizi iletim ortamına da gönderedebiliriz. Yani ayrıca send() fonksiyonunu kullanmamıza gerek yoktur.
sr'nin açılımı send and recieve'dir
Aşağıdaki örneği inceleyelim.
- ans, unans = sr(IP(dst="cyberkod.com")/TCP(sport=9898, dport=80, flags= 'S'))
- for send, recieve in ans:
- send.show()
- print("--")
- recieve.show()
###[ IP ]###
###[ IP ]###
- version = 4
- ihl = None
- tos = 0x0
- len = None
- id = 1
- flags =
- frag = 0
- ttl = 64
- proto = tcp
- chksum = None
- src = 192.168.10.63
- dst = 192.30.252.153
- \options \
- ###[ TCP ]###
- sport = 9898
- dport = http
- seq = 0
- ack = 0
- dataofs = None
- reserved = 0
- flags = S
- window = 8192
- chksum = None
- urgptr = 0
- options = {}
###[ IP ]###
- version = 4L
- ihl = 5L
- tos = 0x0
- len = 44
- id = 0
- flags = DF
- frag = 0L
- ttl = 46
- proto = tcp
- chksum = 0xc52c
- src = 192.30.252.153
- dst = 192.168.10.63
- \options \
- ###[ TCP ]###
- sport = http
- dport = 9898
- seq = 3181249471
- ack = 1
- dataofs = 6L
- reserved = 0L
- flags = SA
- window = 28720
- chksum = 0xb805
- urgptr = 0
- options = [('MSS', 1436)]
sr1()
Bu fonksiyonumuz ise paket gönderip sadece dönen cevabı bir değişkene atama işlemini gerçekleştirmektedir. Yani bir ICMP paketi gönderdiniz, eğer başarılı bir şekilde paketiniz gitti ise dönen ICMP reply paketini bir değişkende saklayabilirsiniz. Yok başarılı bir şekilde gitmedi ise bundan haberdar da olamazsınız. Çünkü sr() fonksiyonunda olduğu gibi bir unans değeri döndürmez. Aşağıdaki örneği inceleyelim.
Bu fonksiyonumuz ise paket gönderip sadece dönen cevabı bir değişkene atama işlemini gerçekleştirmektedir. Yani bir ICMP paketi gönderdiniz, eğer başarılı bir şekilde paketiniz gitti ise dönen ICMP reply paketini bir değişkende saklayabilirsiniz. Yok başarılı bir şekilde gitmedi ise bundan haberdar da olamazsınız. Çünkü sr() fonksiyonunda olduğu gibi bir unans değeri döndürmez. Aşağıdaki örneği inceleyelim.
- recieved = sr1(IP(dst="google.com")/ICMP())
- recieved.show()
###[ IP ]###
- version = 4L
- ihl = 5L
- tos = 0x0
- len = 28
- id = 0
- flags =
- frag = 0L
- ttl = 54
- proto = icmp
- chksum = 0xfb52
- src = 172.217.17.206
- dst = 192.168.10.63
- \options \
- ###[ ICMP ]###
- type = echo-reply
- code = 0
- chksum = 0x0
- id = 0x0
- seq = 0x0
sniff()
Yazının sonlarına doğru değinmezsem içimde kalır dediğim bir fonksiyondur sniff() fonksiyonu. Bu fonksiyon sayesinde ağ kartınıza gelen paketleri dinleyip bir değişkene çok kolay bir şekilde atayabilirsiniz. İçerisine gireceğiniz çeşitli filtreler ile spesifik paketleri dinleyebilirsiniz. Örnekleri inceleyelim.
- pkts = sniff(filter="arp", count=5)
- pkts.summary()
- Ether / ARP who has 192.168.10.147 says 192.168.10.1 / Padding
- Ether / ARP who has 192.168.10.148 says 192.168.10.1 / Padding
- Ether / ARP who has 192.168.10.149 says 192.168.10.1 / Padding
- Ether / ARP who has 192.168.10.150 says 192.168.10.1 / Padding
- Ether / ARP who has 192.168.10.151 says 192.168.10.1 / Padding
- pkts = sniff(filter="arp", count=5)
- pkts[0].show()
Basit Scapy Komutları
Using Scapy’s powerful packet crafting facilities we can quick replicate classic TCP Scans. For example, the following string will be sent to simulate an ACK Scan:
- >>> ans, unans = sr(IP(dst="www.slashdot.org")/TCP(dport=[80,666],flags="A"))
- >>> for s,r in ans: ... if s[TCP].dport == r[TCP].sport: ... print str(s[TCP].dport) + " is unfiltered"
- >>> for s in unans: ... print str(s[TCP].dport) + " is filtered"
Xmas Scan can be launched using the following command:
- >>> ans, unans = sr(IP(dst="192.168.1.1")/TCP(dport=666,flags="FPU") )
IP Scan
A lower level IP Scan can be used to enumerate supported protocols:
- >>> ans, unans = sr(IP(dst="192.168.1.1",proto=(0,255))/"SCAPY",retry=2)
The fastest way to discover hosts on a local ethernet network is to use the ARP Ping method:
- >>> ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.1.0/24"),timeout=2)
- >>> ans.summary(lambda (s,r): r.sprintf("%Ether.src% %ARP.psrc%") )
- >>> arping("192.168.1.*")
Classical ICMP Ping can be emulated using the following command:
- >>> ans, unans = sr(IP(dst="192.168.1.1-254")/ICMP())
- >>> ans.summary(lambda (s,r): r.sprintf("%IP.src% is alive") )
In cases where ICMP echo requests are blocked, we can still use various TCP Pings such as TCP SYN Ping below:
- >>> ans, unans = sr( IP(dst="192.168.1.*")/TCP(dport=80,flags="S") )
- >>> ans.summary( lambda(s,r) : r.sprintf("%IP.src% is alive") )
If all else fails there is always UDP Ping which will produce ICMP Port unreachable errors from live hosts. Here you can pick any port which is most likely to be closed, such as port 0:
- >>> ans, unans = sr( IP(dst="192.168.*.1-10")/UDP(dport=0) )
- >>> ans.summary( lambda(s,r) : r.sprintf("%IP.src% is alive") )
Malformed packets:
- >>> send(IP(dst="10.1.1.5", ihl=2, version=3)/ICMP())
- >>> send( fragment(IP(dst="10.0.0.5")/ICMP()/("X"*60000)) )
- >>> send(IP(dst=target, id=42, flags="MF")/UDP()/("X"*10)) >>> send(IP(dst=target, id=42, frag=48)/("X"*116)) >>> send(IP(dst=target, id=42, flags="MF")/UDP()/("X"*224))
- >>> send(IP(src=target,dst=target)/TCP(sport=135,dport=135))
No comments:
Post a Comment