-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path0trace.py
136 lines (111 loc) · 3.83 KB
/
0trace.py
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
#!/usr/bin/env python
# 0trace.py
# Jon Oberheide <[email protected]>
# http://jon.oberheide.org/0trace/
import dnet, dpkt, pcap
import sys, sets, time, struct, select, threading
MAX_HOPS = 30
SEQ_DELTA = 3
class AckProbe(threading.Thread):
def __init__ (self, ip, tcp):
self.ip = ip
self.tcp = tcp
self.tcp.flags = dpkt.tcp.TH_ACK
self.tcp.data = struct.pack('H', 0)
self.sock = dnet.ip()
threading.Thread.__init__(self)
def run(self):
for i in xrange(1, SEQ_DELTA+1):
self.tcp.seq += i
for j in xrange(MAX_HOPS):
self.ip.id = j
self.ip.ttl = j
buf = dnet.ip_checksum(str(self.ip))
self.sock.send(buf)
time.sleep(0.001)
class Monitor(threading.Thread):
def __init__ (self, filter):
self.hops = []
self.filter = filter
self.reached = False
threading.Thread.__init__(self)
def run(self):
pc = pcap.pcap()
pc.setnonblock(True)
pc.setfilter(self.filter)
while True:
rfd, wfd, efd = select.select([pc.fileno()], [], [], 3)
if not rfd:
break
ts, pkt = pc.next()
eth = dpkt.ethernet.Ethernet(pkt)
ip = eth.data
if ip.p == dpkt.ip.IP_PROTO_TCP:
self.reached = True
elif ip.p == dpkt.ip.IP_PROTO_ICMP:
icmp = ip.data
if icmp.type == dpkt.icmp.ICMP_TIMEXCEED and \
icmp.code == dpkt.icmp.ICMP_TIMEXCEED_INTRANS and \
icmp.data.ip.id < MAX_HOPS and \
icmp.data.ip.id > 0 and \
icmp.data.ip.ttl > 0:
self.hops.append((icmp.data.ip.id, ip.src))
class ZeroTrace:
def main(self):
if len(sys.argv) < 4:
print 'Usage: %s interface target_ip target_port' % sys.argv[0]
sys.exit(1)
print '0trace.py by Jon Oberheide <[email protected]>'
interface = sys.argv[1]
target_ip = dnet.addr(sys.argv[2])
target_port = sys.argv[3]
filter = 'src host %s and src port %s and (tcp[13] & 0x17 == 0x10)' % \
(target_ip, target_port)
pc = pcap.pcap(interface)
pc.setfilter(filter)
pc.setnonblock(True)
print '[+] Waiting for traffic from target on %s...' % interface
while True:
rfd, wfd, efd = select.select([pc.fileno()], [], [])
if rfd:
ts, pkt = pc.next()
break
print '[+] Traffic acquired, waiting for a gap...'
while True:
rfd, wfd, efd = select.select([pc.fileno()], [], [], 3)
if not rfd:
break
ts, pkt = pc.next()
eth = dpkt.ethernet.Ethernet(pkt)
ip = eth.data
tcp = ip.data
ip.src, ip.dst = ip.dst, ip.src
tcp.seq, tcp.ack = tcp.ack, tcp.seq
tcp.sport, tcp.dport = tcp.dport, tcp.sport
print '[+] Target acquired: %s:%s -> %s:%s (%s/%s)' % \
(dnet.ip_ntoa(ip.src), tcp.sport,
dnet.ip_ntoa(ip.dst), tcp.dport,
tcp.seq, tcp.ack)
print '[+] Setting up a sniffer...'
m = Monitor('icmp or (%s)' % filter)
m.start()
time.sleep(1)
print '[+] Sending probes...'
p = AckProbe(ip, tcp)
p.start()
p.join()
m.join(5)
print
print 'TRACE RESULTS'
print '-------------'
m.hops = list(sets.Set(m.hops))
m.hops.sort()
for id, hop in m.hops:
print '%d %s' % (id, dnet.ip_ntoa(hop))
if m.reached:
print 'Target reached.'
else:
print 'Probe rejected by target.'
print
if __name__ == '__main__':
z = ZeroTrace().main()