2014-10-21 18 views
7

Próbuję stworzyć 3-drożny uścisk dłoni w Scapy. Korzystanie poniższy kod,3-drożny uścisk dłoni w Scapy

#!/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) 

Jednak na serwerze widzę tylko SYN_RECV chociaż powrót SYN-ACK jest wysyłany i ACK jest wysyłany w zamian. Oto capture z serwera (172.16.100.101),

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> 

Jak widać SYN-ACK jest wysyłany dwa razy więc wygląda na to doesnt serwerze jak ostatnim ACK. Jakieś pomysły ?

Edycja:

Ive także nadrukowane wyjście każdego z pakietów bezpośrednio pytona. Zauważ, że było to dla innego połączenia.

>>> 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 |> 

EDIT 2:

Poniżej przedstawiono udane i unsucessful połączenia.

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

'pakiet SYN-ACK' jest rejestrowane jako 'ACK 1 wygranej 8192', co wydaje się wskazywać na' ack' z oczekiwanej liczby sekwencji 1 zamiast 2541678706. Czy możesz wydrukować 'SYNACK' i' my_ack' (choć wydają się być ustawione poprawnie)? – Yoel

+0

Ive zaktualizowałem pytanie. Myślisz, że masz rację, że ACK ma nieprawidłowy numer potwierdzenia. Jednak jeśli wezmę działające połączenie, tj. Wykonam zawinięcie do portu 443, który został pomyślnie ustanowiony, to pokazuje również ostateczną wersję ACK z 1 – felix001

+0

. Czy możesz również opublikować równoważny log udanego połączenia 'curl'? W jaki sposób jest wdrażany serwer? Czy można go zastąpić skryptem 'scapy', który drukuje odebrane pakiety? – Yoel

Odpowiedz

3

udało mi się rozwiązać ten problem w końcu przez zwiększający ostatecznej liczby nast ACK.

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) 

Herezje tcpdump pokazuje zachowanie ...

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

Zrobiłem ale twój seq numer był nieprawidłowy, musi być 1002. – felix001

+0

To jest dziwne ... dlaczego to działa? Czy możesz wysłać dziennik śledzenia pakietów po tej aktualizacji? Jeśli inkrementujesz sekwencję o więcej, to też działa? – Yoel

+0

Ive dodał tcpdump. Również jeśli spróbuję czegoś wyższego, to działa. ale muszę przyznać, że to dziwne. Próbowałem również podnieść liczbę seq powyżej 1002 i to działa. Próbowałem też tego na innym urządzeniu (np. QNAP NAS). – felix001

2

This gist implementuje prosty scapy trójdrożny klasę handshake w oparciu o przykład w scapy.layers.inet. Dla porównania, ten kod:

#!/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() 
Powiązane problemy