如何在scapy中伪装TCP握手?

2 投票
1 回答
5915 浏览
提问于 2025-04-18 10:36

最近我在尝试写一个Scapy脚本,目的是完成一个完整的TCP握手。我的想法是通过使用-net socket的用户空间接口连接两个Qemu虚拟机(这个接口似乎能很好地处理原始的IP和以太网),然后让我机器B阻止来自A的所有输入(这样可以防止A发送重置信号)。接着,我用telnet从机器A连接到B,并在机器B上运行了以下脚本:

#!/usr/bin/python

import scapy.all as scapy

filter = "port 31337"
iface = "eth0"

def prepare_response(t):
    print("Received: %s" % repr(t))
    t.src, t.dst = t.dst, t.src  # swap ethernet addresses
    ip = t.getlayer("IP")
    ip.src, ip.dst = ip.dst, ip.src
    t.dport, t.sport = t.sport, t.dport
    t.ack = t.seq
    t.ack += 1

syn = scapy.sniff(filter=filter, count=1, iface=iface)[0]
print(syn.sprintf('%TCP.flags%'))

syn_ack = syn
prepare_response(syn_ack)
syn_ack.getlayer("TCP").flags |= 0x10  # set the ACK flag
print(syn_ack.sprintf('%TCP.flags%'))

print("Sending: %s" % repr(syn_ack))
scapy.sendp(syn_ack, iface=iface, verbose=False)

ack = scapy.sniff(filter=filter, count=1, iface=iface)[0]
assert(ack.flags & 0x10)

问题是,我并没有收到来自A的确认信号(ACK),反而收到了一个重复的同步信号(SYN),就好像SYN+ACK没有被正确处理一样:

https://imgur.com/kv7A3Hr

在机器A上,tcp确认SYN+ACK已经到达机器:

05:47:03.925100 IP 10.0.0.1.39634 > debian.31337: Flags [S], seq 2426802888, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 4], length 0
05:47:03.927515 IP debian.31337 > 10.0.0.1.39634: Flags [S.], seq 2426802888, ack 2426802889, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 4], length 0

这是从机器B的角度看得到的PCAP文件,已经转成Base64格式:

1MOyoQIABAAAAAAAAAAAAP//AAABAAAAYlilUwieDgARAQAAEQEAAAEAXgAA+1JUABI0VggARQABA2UUQAD/ESrYCgAAAuAAAPsU6RTpAO/r/QAAAAAAAwAAAAUAAAE2ATUBNAEzATIBMQFlAWYBZgFmATABMAE0ATUBMAE1ATABMAEwATABMAEwATABMAEwATABMAEwATABOAFlAWYDaXA2BGFycGEAAP8AAQtkZWJpYW4tMTA5MwVsb2NhbAAA/wABATIBMAEwAjEwB2luLWFkZHLAUAD/AAHAWgANAAEAAAB4AAsESTY4NgVMSU5VWMBaAAEAAQAAAHgABAoAAALAcQAMAAEAAAB4AALAWsBaABwAAQAAAHgAEP6AAAAAAAAAUFQA//4SNFbADAAMAAEAAAB4AALAWmJYpVMJoA4AnAAAAJwAAAABAF4AAPtSVAASNFYIAEUAAI4GlEAA/xGJzgoAAAHgAAD7FOkU6QB6hFgAAIQAAAAAAQAAAAABNgE1ATQBMwEyATEBZQFmAWYBZgEwATABNAE1ATABNQEwATABMAEwATABMAEwATABMAEwATABMAEwATgBZQFmA2lwNgRhcnBhAAAMgAEAAAB4ABIKZGViaWFuLTQwNwVsb2NhbABnWKVTvIYIAEIAAABCAAAAUlQAEjRWUlQAEjRWCABFAAA0HdtAAEAGCOcKAAABCgAAAprbemmul/p8AAAAAIACOQhjsAAAAgQFtAEBBAIBAwMEZ1ilU5COCABCAAAAQgAAAFJUABI0VlJUABI0VggARQAANB3bQABABgjnCgAAAgoAAAF6aZrbrpf6fK6X+n2AEjkIY7AAAAIEBbQBAQQCAQMDBGhYpVPTfggAQgAAAEIAAABSVAASNFZSVAASNFYIAEUAADQd3EAAQAYI5goAAAEKAAACmtt6aa6X+nwAAAAAgAI5CGOwAAACBAW0AQEEAgEDAwRqWKVTrI4IAEIAAABCAAAAUlQAEjRWUlQAEjRWCABFAAA0Hd1AAEAGCOUKAAABCgAAAprbemmul/p8AAAAAIACOQhjsAAAAgQFtAEBBAIBAwME

这是从A到B的视角:

1MOyoQIABAAAAAAAAAAAAP//AAABAAAAVVilU9NXCABCAAAAQgAAAFJUABI0VlJUABI0VggARQAANB3bQABABgjnCgAAAQoAAAKa23pprpf6fAAAAACAAjkIFCkAAAIEBbQBAQQCAQMDBFVYpVPIYAgAQgAAAEIAAABSVAASNFZSVAASNFYIAEUAADQd20AAQAYI5woAAAIKAAABemma266X+nyul/p9gBI5CGOwAAACBAW0AQEEAgEDAwRWWKVT008IAEIAAABCAAAAUlQAEjRWUlQAEjRWCABFAAA0HdxAAEAGCOYKAAABCgAAAprbemmul/p8AAAAAIACOQgUKQAAAgQFtAEBBAIBAwMEWFilU4FfCABCAAAAQgAAAFJUABI0VlJUABI0VggARQAANB3dQABABgjlCgAAAQoAAAKa23pprpf6fAAAAACAAjkIFCkAAAIEBbQBAQQCAQMDBA==

起初我以为这可能和Linux的TCP/IP有些奇怪的地方有关,所以我尝试关闭TCP时间戳和SYN cookies。我还试着增加IP ID,但也没有帮助。这两台机器都在运行Debian 7.5,使用的是linux-image-3.2.0-4-686-pae,运行在qemu 1.6.2下。我到底漏掉了什么呢?

1 个回答

3

这是一个校验和的问题。

在IP层面上,交换源地址和目的地址是没问题的,但在TCP层面上,当你改变标志位的值时,原来的校验和就会出错。

最好的办法是让Scapy为你计算正确的校验和值,你可以在prepare_response()里加上del(t[TCP].chksum)

撰写回答