2014-10-21 22 views
7

Scapy'de 3 yollu bir el sıkışması yapmaya çalışıyorum. Aşağıdaki kodu kullanarak, Scapy'de 3 şekilde el sıkışması

#!/usr/local/bin/python 

from scapy.all import * 

sport = random.randint(1024,65535) 

# SYN  
ip=IP(src='172.16.120.5',dst='172.16.100.101') 
SYN=TCP(sport=sport,dport=443,flags='S',seq=1000) 
SYNACK=sr1(ip/SYN) 

# ACK    
my_ack = SYNACK.seq + 1 
ACK=TCP(sport=sport, dport=443, flags='A', seq=1001, ack=my_ack) 
send(ip/ACK) 

Ancak sunucuda ben dönüş SYN-ACK gönderilir ve ACK karşılığında gönderilir rağmen sadece SYN_RECV görüyoruz. İşte sunucusu (172.16.100.101) bir yakalama,

08:10:19.455038 IP 172.16.120.5.58972 > 172.16.100.101.https: S 1000:1000(0) win 8192 
08:10:19.455343 IP 172.16.100.101.https > 172.16.120.5.58972: S 2541678705:2541678705(0) ack 1001 win 18484 <mss 1460> 
08:10:19.545808 IP 172.16.120.5.58972 > 172.16.100.101.https: . ack 1 win 8192 
08:10:24.015204 IP 172.16.100.101.https > 172.16.120.5.58972: S 2541678705:2541678705(0) ack 1001 win 18484 <mss 1460> 

size nihai ACK gibi sunucu doesnt benziyor bu yüzden SYN-ACK iki kez gönderiliyor görebileceğiniz gibi. Herhangi bir fikir ?

DÜZENLEME:

Ive doğrudan piton gelen paketlerin her biri çıkış yazılır. Bunun farklı bir bağlantı için olduğunu unutmayın. DÜZENLEME 2

>>> SYN 
<TCP sport=26193 dport=https seq=1000 flags=S |> 
>>> 
>>> SYNACK 
<IP version=4L ihl=5L tos=0x0 len=44 id=0 flags=DF frag=0L ttl=63 proto=tcp chksum=0x741 src=172.16.100.101 dst=172.16.120.5 options=[] |<TCP sport=https dport=26193 seq=1023579974 ack=1001 dataofs=6L reserved=0L flags=SA window=18484 chksum=0xdb18 urgptr=0 options=[('MSS', 1460)] |<Padding load='\x00\x00' |>>> 
>>> 
>>> ACK 
<TCP sport=26193 dport=https seq=1001 ack=1023579975 flags=A |> 

:

Aşağıda başarılı ve unsucessful bağlantıyı gösterir.

SCAPY

20:58:37.357056 IP 172.16.120.5.35957 > 172.16.100.101.https: S 10:10(0) win 8192 
20:58:37.357369 IP 172.16.100.101.https > 172.16.120.5.35957: S 900629853:900629853(0) ack 11 win 18484 <mss 1460> 
20:58:37.445888 IP 172.16.120.5.35957 > 172.16.100.101.https: . ack 900629854 win 8192 

CURL

20:58:46.165413 IP 172.16.120.5.33241 > 172.16.100.101.https: S 2266708589:2266708589(0) win 5840 <mss 1460,sackOK,timestamp 17370497 0,nop,wscale 6> 
20:58:46.166296 IP 172.16.100.101.https > 172.16.120.5.33241: S 2138155488:2138155488(0) ack 2266708590 win 18460 <mss 1460,sackOK,timestamp 107550664 17370497,nop,wscale 7> 
20:58:46.169026 IP 172.16.120.5.33241 > 172.16.100.101.https: . ack 2138155489 win 92 <nop,nop,timestamp 17370497 107550664> 
+0

'EŞZ-ACK' paket 1 yerine 2541678706 beklenen dizi numarası ile' ack' gösterir gibi görünmektedir 'bildirim 1 kazanmak 8192' olarak kaydedilir: Referans olarak, bu kodudur. 'SYNACK' ve' my_ack' yazdırabilirsiniz (doğru şekilde ayarlanmış gibi görünüyorlar)? – Yoel

+0

Soruyu güncelledim. Finalin doğru olduğunu düşünüyorsun ACK yanlış ack numarasına sahip. Bununla birlikte, çalışan bir bağlantı kurarsam, yani başarılı bir şekilde kurulmuş olan 443 numaralı bağlantı noktasına bir curl gerçekleştirirseniz, bu da 1 – felix001

+0

ile son ACK'yı gösterir Başarılı bir "curl" bağlantısının eşdeğer bir kaydını da gönderebilir misiniz? Sunucu nasıl uygulanır? Alınan paketleri basan bir "scapy" betiği ile değiştirebilir misiniz? – Yoel

cevap

3

I ACK nihai DİZİ numarası yükseltilmektedir sonunda bu düzeltmek başardı.

from scapy.all import * 

sport = random.randint(1024,65535) 

# SYN 
ip=IP(src='172.16.120.5',dst='172.16.100.101') 
SYN=TCP(sport=sport,dport=443,flags='S',seq=1000) 
SYNACK=sr1(ip/SYN) 

# SYN-ACK 
ACK=TCP(sport=sport, dport=443, flags='A', seq=SYNACK.ack + 1, ack=SYNACK.seq + 1) 
send(ip/ACK) 

İşte bir tcpdump davranışı gösteren

...

20:47:54.226591 IP 172.16.120.5.55348 > 172.16.100.101.443: S 1000:1000(0) win 8192 
20:47:54.227220 IP 172.16.100.101.443 > 172.16.120.5.55348: S 4265040634:4265040634(0) ack 1001 win 18484 <mss 1460> 
20:47:54.317452 IP 172.16.120.5.55348 > 172.16.100.101.443: . ack 4265040635 win 8192 
+0

yaptım ama senin yanlış numaranın yanlış olması gerekiyor, 1002 olmalı. – felix001

+0

Bu garip ... neden bu işe yarıyor? Bu güncellemeden sonra paketlerin izleme günlüğünü kaydeder misiniz? Diziyi daha fazla artırırsanız, o da işe yarıyor mu? – Yoel

+0

Ive bir tcpdump ekledi. Ayrıca daha yüksek bir şey deneyirsem çalışır. ama buna katılıyorum, bu garip. Ayrıca 1002'nin üstündeki sıra sayısını yükseltmeyi denedi ve işe yarıyor. Ayrıca bunu başka bir cihazda denedim (yani QNAP NAS). – felix001

2

This gistscapy.layers.inet örneğin dayalı basit scapy üç yönlü el sıkışma sınıfını uygular.

#!/usr/bin/env python 
# -*- coding: UTF-8 -*- 
# Author : [email protected] <github.com/tintinweb> 
''' 
A simple TCP three-way handshake example 

#> python scapy_tcp_handshake.py 
DEBUG:__main__:init: ('oststrom.com', 80) 
DEBUG:__main__:start 
DEBUG:__main__:SND: SYN 
DEBUG:__main__:RCV: SYN+ACK 
DEBUG:__main__:SND: SYN+ACK -> ACK 
DEBUG:__main__:RCV: None 
DEBUG:__main__:RCV: None 
None 
DEBUG:__main__:SND: FIN 
DEBUG:__main__:RCV: None 

Note: linux might send an RST for forged SYN packets. Disable it by executing: 
#> iptables -A OUTPUT -p tcp --tcp-flags RST RST -s <src_ip> -j DROP 
''' 
from scapy.all import * 
import logging 
logger = logging.getLogger(__name__) 

class TcpHandshake(object): 

    def __init__(self, target): 
     self.seq = 0 
     self.seq_next = 0 
     self.target = target 
     self.dst = iter(Net(target[0])).next() 
     self.dport = target[1] 
     self.sport = random.randrange(0,2**16) 
     self.l4 = IP(dst=target[0])/TCP(sport=self.sport, dport=self.dport, flags=0, 
             seq=random.randrange(0,2**32)) 
     self.src = self.l4.src 
     self.swin = self.l4[TCP].window 
     self.dwin=1 
     logger.debug("init: %s"%repr(target)) 

    def start(self): 
     logger.debug("start") 
     return self.send_syn() 

    def match_packet(self, pkt): 
     if pkt.haslayer(IP) and pkt[IP].dst == self.l4[IP].src \ 
      and pkt.haslayer(TCP) and pkt[TCP].dport == self.sport \ 
      and pkt[TCP].ack == self.seq_next: 
      return True 
     return False 

    def _sr1(self, pkt): 
     send(pkt) 
     ans = sniff(filter="tcp port %s"%self.target[1],lfilter=self.match_packet,count=1,timeout=1) 
     return ans[0] if ans else None 

    def handle_recv(self, pkt): 
     if pkt and pkt.haslayer(IP) and pkt.haslayer(TCP): 
      if pkt[TCP].flags & 0x3f == 0x12: # SYN+ACK 
       logger.debug("RCV: SYN+ACK") 
       return self.send_synack_ack(pkt) 
      elif pkt[TCP].flags & 4 != 0:  # RST 
       logger.debug("RCV: RST") 
       raise Exception("RST") 
      elif pkt[TCP].flags & 0x1 == 1:  # FIN 
       logger.debug("RCV: FIN") 
       return self.send_finack(pkt) 
      elif pkt[TCP].flags & 0x3f == 0x10: # FIN+ACK 
       logger.debug("RCV: FIN+ACK") 
       return self.send_ack(pkt) 

     logger.debug("RCV: %s"%repr(pkt)) 
     return None 

    def send_syn(self): 
     logger.debug("SND: SYN") 
     self.l4[TCP].flags = "S" 
     self.seq_next = self.l4[TCP].seq + 1 
     response = self._sr1(self.l4) 
     self.l4[TCP].seq += 1 
     return self.handle_recv(response) 

    def send_synack_ack(self, pkt): 
     logger.debug("SND: SYN+ACK -> ACK") 
     self.l4[TCP].ack = pkt[TCP].seq+1 
     self.l4[TCP].flags = "A" 
     self.seq_next = self.l4[TCP].seq 
     response = self._sr1(self.l4) 
     return self.handle_recv(response) 

    def send_data(self, d): 
     self.l4[TCP].flags = "PA" 
     response = self._sr1(self.l4/d) 
     self.seq_next = self.l4[TCP].seq + len(d) 
     self.l4[TCP].seq += len(d) 
     return self.handle_recv(response) 

    def send_fin(self): 
     logger.debug("SND: FIN") 
     self.l4[TCP].flags = "F" 
     self.seq_next = self.l4[TCP].seq + 1 
     response = self._sr1(self.l4) 
     self.l4[TCP].seq += 1 
     return self.handle_recv(response) 

    def send_finack(self, pkt): 
     logger.debug("SND: FIN+ACK") 
     self.l4[TCP].flags = "FA" 
     self.l4[TCP].ack = pkt[TCP].seq+1 
     self.seq_next = self.l4[TCP].seq + 1 
     response = send(self.l4) 
     self.l4[TCP].seq += 1 
     raise Exception("FIN+ACK") 

    def send_ack(self, pkt): 
     logger.debug("SND: ACK") 
     self.l4[TCP].flags = "A" 
     self.l4[TCP].ack = pkt[TCP].seq+1 
     self.seq_next = self.l4[TCP].seq + 1 
     response = self._sr1(self.l4) 
     self.l4[TCP].seq += 1 

if __name__=='__main__': 
    logging.basicConfig(level=logging.DEBUG) 
    logger.setLevel(logging.DEBUG) 
    conf.verb = 0 
    tcp_hs = TcpHandshake(("oststrom.com",80)) 
    tcp_hs.start() 
    print repr(tcp_hs.send_data("INTENTIONAL BAD REQUEST\r\n\r\n\r\n")) 
    tcp_hs.send_fin()