Ack номер за потвърждаване на данните в scapy

Играя си със scapy, опитвайки се да направя подобен на nmap, успях да направя трипосочно ръкостискане и автоматично получавам данни, ако се свържа към smtp сървър, но не мога да го потвърдя.

Свързах се с него чрез netcat, за да видя защо не работи и nc всъщност изпрати ACK пакет с полето TCP ack, зададено на дължината на получения сегмент от данни + 1. Така че се опитвам да направя същото със scapy, но Не знам къде да намеря дължината на TCP сегмент. Опитах lsc(TCP), но не мога да видя полето.

Ето wireshark заснемане на netcat връзката:

въведете описание на изображението тук

И подробности за пакета:

въведете описание на изображението тук

Както можете да видите, полето за потвърждение на пакета точно под данните е 37 + 1 = 38.

Някой знае ли къде и как може да се намери?

РЕДАКТИРАНЕ:

Всъщност няма поле, което да дава дължината на сегмента, но може да се изчисли с два метода:

    tcp_seg_len = len(rp.getlayer(Raw).load)
    # or
    ip_total_len = rp.getlayer(IP).len
    ip_header_len = rp.getlayer(IP).ihl * 32 / 8
    tcp_header_len = rp.getlayer(TCP).dataofs * 32 / 8
    tcp_seg_len = ip_total_len - ip_header_len - tcp_header_len

    ans_ack,unans_ack = sr(IP(dst=ip)/TCP(sport=pkt[1].dport, \
                                          dport=pkt[1].sport, \
                                          seq=rp[1].ack, \
                                          ack=tcp_seg_len + 1, \
                                          flags="A"), \
                           verbose=0, timeout=1)

Въпреки това, когато отпечатам стойностите, получавам добрия ack номер, но когато гледам улавянето на wireshark, имам огромен ack номер и пакетът е маркиран като „ACKed unseen segment“. Когато гледам байтовете в хекса, все пак получих правилната стойност. Някой знае ли защо се случва това и как да го реша?


person Jeff Bencteux    schedule 02.11.2015    source източник


Отговори (2)


Wireshark използва относителни числа в своя дисплей, така че правилният scapy ред е:

    ans_ack,unans_ack = sr(IP(dst=ip)/TCP(sport=pkt[1].dport, \
                                      dport=pkt[1].sport, \
                                      seq=rp[1].ack, \
                                      ack=rp[1].seq + tcp_seg_len, \
                                      flags="A"), \
                       verbose=0, timeout=1)

И следният код (вижте РЕДАКТИРАНЕ във въпроса) работи:

ip_total_len = rp.getlayer(IP).len
ip_header_len = rp.getlayer(IP).ihl * 32 / 8
tcp_header_len = rp.getlayer(TCP).dataofs * 32 / 8
tcp_seg_len = ip_total_len - ip_header_len - tcp_header_len
ans_ack,unans_ack = sr(IP(dst=ip)/TCP(sport=pkt[1].dport, \
                                      dport=pkt[1].sport, \
                                      seq=rp[1].ack, \
                                      ack=rp[1].seq + tcp_seg_len, \
                                      flags="A"), \
                           verbose=0, timeout=1)
person Jeff Bencteux    schedule 02.11.2015
comment
Когато изпробвах кодовия ви фрагмент, открих, че е необходим int() за tcp_seg_len, което иначе беше float за мен, което неочаквано се срина scapy... - person mozzbozz; 10.02.2019
comment
Защо са ви необходими всички тези изчисления за дължината на tcp сегмента? Това, което направихте във въпроса tcp_seg_len = len(rp.getlayer(Raw).load), работи перфектно за мен - person Tomerikoo; 09.05.2021

За да получите дължината на TCP сегмента (това е проверено за IPv6 трафик):

tcp_header_len = rp.getlayer(TCP).dataofs * 32 / 8
tcp_seg_len = rp.plen - tcp_header_len
person Smrithi Komalan    schedule 18.08.2016