-
Notifications
You must be signed in to change notification settings - Fork 238
Expand file tree
/
Copy pathfake_tcp.py
More file actions
177 lines (158 loc) · 8.21 KB
/
Copy pathfake_tcp.py
File metadata and controls
177 lines (158 loc) · 8.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import asyncio
import socket
import sys
import threading
import time
from pydivert import Packet
from monitor_connection import MonitorConnection
from injecter import TcpInjector
class FakeInjectiveConnection(MonitorConnection):
def __init__(self, sock: socket.socket, src_ip, dst_ip,
src_port, dst_port, fake_data: bytes, bypass_method: str, peer_sock: socket.socket):
super().__init__(sock, src_ip, dst_ip, src_port, dst_port)
self.fake_data = fake_data
self.sch_fake_sent = False
self.fake_sent = False
self.t2a_event = asyncio.Event()
self.t2a_msg = ""
self.bypass_method = bypass_method
self.peer_sock = peer_sock
self.running_loop = asyncio.get_running_loop()
class FakeTcpInjector(TcpInjector):
def __init__(self, w_filter: str, connections: dict[tuple, FakeInjectiveConnection]):
super().__init__(w_filter)
self.connections = connections
def fake_send_thread(self, packet: Packet, connection: FakeInjectiveConnection):
time.sleep(0.001)
with connection.thread_lock:
if not connection.monitor:
return
packet.tcp.psh = True
packet.ip.packet_len = packet.ip.packet_len + len(connection.fake_data)
packet.tcp.payload = connection.fake_data
if packet.ipv4:
packet.ipv4.ident = (packet.ipv4.ident + 1) & 0xffff
# if connection.bypass_method == "wrong_checksum":
# ...
if connection.bypass_method == "wrong_seq":
packet.tcp.seq_num = (connection.syn_seq + 1 - len(packet.tcp.payload)) & 0xffffffff
connection.fake_sent = True
self.w.send(packet, True)
else:
sys.exit("not implemented method!")
def on_unexpected_packet(self, packet: Packet, connection: FakeInjectiveConnection, info_m: str):
print(info_m, packet)
connection.sock.close()
connection.peer_sock.close()
connection.monitor = False
connection.t2a_msg = "unexpected_close"
connection.running_loop.call_soon_threadsafe(connection.t2a_event.set, )
self.w.send(packet, False)
def on_inbound_packet(self, packet: Packet, connection: FakeInjectiveConnection):
if connection.syn_seq == -1:
self.on_unexpected_packet(packet, connection, "unexpected inbound packet, no syn sent!")
return
if packet.tcp.ack and packet.tcp.syn and (not packet.tcp.rst) and (not packet.tcp.fin) and (
len(packet.tcp.payload) == 0):
seq_num = packet.tcp.seq_num
ack_num = packet.tcp.ack_num
if connection.syn_ack_seq != -1 and connection.syn_ack_seq != seq_num:
self.on_unexpected_packet(packet, connection,
"unexpected inbound syn-ack packet, seq change! " + str(seq_num) + " " + str(
connection.syn_ack_seq))
return
if ack_num != ((connection.syn_seq + 1) & 0xffffffff):
self.on_unexpected_packet(packet, connection,
"unexpected inbound syn-ack packet, ack not matched! " + str(
ack_num) + " " + str(connection.syn_seq))
return
connection.syn_ack_seq = seq_num
self.w.send(packet, False)
return
if packet.tcp.ack and (not packet.tcp.syn) and (not packet.tcp.rst) and (
not packet.tcp.fin) and (len(packet.tcp.payload) == 0) and connection.fake_sent:
seq_num = packet.tcp.seq_num
ack_num = packet.tcp.ack_num
if connection.syn_ack_seq == -1 or ((connection.syn_ack_seq + 1) & 0xffffffff) != seq_num:
self.on_unexpected_packet(packet, connection,
"unexpected inbound ack packet, seq not matched! " + str(seq_num) + " " + str(
connection.syn_ack_seq))
return
if ack_num != ((connection.syn_seq + 1) & 0xffffffff):
self.on_unexpected_packet(packet, connection,
"unexpected inbound ack packet, ack not matched! " + str(ack_num) + " " + str(
connection.syn_seq))
return
connection.monitor = False
connection.t2a_msg = "fake_data_ack_recv"
connection.running_loop.call_soon_threadsafe(connection.t2a_event.set, )
return
self.on_unexpected_packet(packet, connection, "unexpected inbound packet")
return
def on_outbound_packet(self, packet: Packet, connection: FakeInjectiveConnection):
if connection.sch_fake_sent:
self.on_unexpected_packet(packet, connection, "unexpected outbound packet, recv packet after fake sent!")
return
if packet.tcp.syn and (not packet.tcp.ack) and (not packet.tcp.rst) and (not packet.tcp.fin) and (
len(packet.tcp.payload) == 0):
seq_num = packet.tcp.seq_num
ack_num = packet.tcp.ack_num
if ack_num != 0:
self.on_unexpected_packet(packet, connection, "unexpected outbound syn packet, ack_num is not zero!")
return
if connection.syn_seq != -1 and connection.syn_seq != seq_num:
self.on_unexpected_packet(packet, connection, "unexpected outbound syn packet, seq not matched! " + str(
seq_num) + " " + str(connection.syn_seq))
return
connection.syn_seq = seq_num
self.w.send(packet, False)
return
if packet.tcp.ack and (not packet.tcp.syn) and (not packet.tcp.rst) and (not packet.tcp.fin) and (
len(packet.tcp.payload) == 0):
seq_num = packet.tcp.seq_num
ack_num = packet.tcp.ack_num
if connection.syn_seq == -1 or ((connection.syn_seq + 1) & 0xffffffff) != seq_num:
self.on_unexpected_packet(packet, connection,
"unexpected outbound ack packet, seq not matched! " + str(
seq_num) + " " + str(
connection.syn_seq))
return
if connection.syn_ack_seq == -1 or ack_num != ((connection.syn_ack_seq + 1) & 0xffffffff):
self.on_unexpected_packet(packet, connection,
"unexpected outbound ack packet, ack not matched! " + str(
ack_num) + " " + str(
connection.syn_ack_seq))
return
self.w.send(packet, False)
connection.sch_fake_sent = True
threading.Thread(target=self.fake_send_thread, args=(packet, connection), daemon=True).start()
return
self.on_unexpected_packet(packet, connection, "unexpected outbound packet")
return
def inject(self, packet: Packet):
if packet.is_inbound:
c_id = (packet.ip.dst_addr, packet.tcp.dst_port, packet.ip.src_addr, packet.tcp.src_port)
try:
connection = self.connections[c_id]
except KeyError:
self.w.send(packet, False)
else:
with connection.thread_lock:
if not connection.monitor:
self.w.send(packet, False)
return
self.on_inbound_packet(packet, connection)
elif packet.is_outbound:
c_id = (packet.ip.src_addr, packet.tcp.src_port, packet.ip.dst_addr, packet.tcp.dst_port)
try:
connection = self.connections[c_id]
except KeyError:
self.w.send(packet, False)
else:
with connection.thread_lock:
if not connection.monitor:
self.w.send(packet, False)
return
self.on_outbound_packet(packet, connection)
else:
sys.exit("impossible direction!")