-
Notifications
You must be signed in to change notification settings - Fork 3
/
coldcut.py
152 lines (121 loc) · 4.41 KB
/
coldcut.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/local/bin/python -*- Mode: Python; tab-width: 4 -*-
'''coldcut v 0.2 - a bulk scanner for certain ESMTP Features
coldcut reads hostnames (or better IP addresses) from stdin. It tries
to connect the hosts on port 25, issue an EHLO command and then a
QUIT. Im a certain ESMTP feature is present at the host it outputs its
IP.
By using the excellent medusa framework coldcut is able to scan
several hounderd hosts at once - if your OS can handle this.
For further enlightment on ESMTP see RFC 1869 (SMTP Service Extensions).
python -O coldcut.py < List
[email protected] - http://c0re.23.nu/
'''
version = '$Id: coldcut.py,v 1.4 2001/12/05 22:49:30 drt Exp $'
# TODO:
# sort resp output
# generate statistics
# gnerate address lists
# issue this commands
surveycommands = ['EHLO survey.c0re.23.nu',
'QUIT']
# max time we wait for a sucessfull data gathering process
timeout = 66
# number of concurrent querys this might be limited by your OS
# Win 95: 55, Linux 2.0: 245, Linux 2.2: 1000
# FreeBSD, NT: 1000; can be tweaked for more.
concurrency = 222
import sys
import socket
import time
import select
import asyncore
import asynchat
def monitor():
'''reap stale and open new connenctions until we reach concurrency'''
# from work_in_progress/reaper.py
# 'bring out your dead, <CLANG!>... bring out your dead!'
now = int(time.time())
for x in asyncore.socket_map.keys():
s = asyncore.socket_map[x]
if hasattr(s, 'timestamp'):
if (now - s.timestamp) > timeout:
print >>sys.stdout, 'reaping connection to', s.host
s.close()
# create new connections
while len(asyncore.socket_map) < concurrency:
line = sys.stdin.readline()
if line[-1:] == '\n':
line = line [:-1]
if line != '':
s = smtpscan(line)
else:
break
def loop():
'''loop over our sockets and monitor connections'''
if hasattr (select, 'poll') and hasattr (asyncore, 'poll3'):
poll_fun = asyncore.poll3
else:
poll_fun = asyncore.poll
while asyncore.socket_map:
monitor()
poll_fun(30.0, asyncore.socket_map)
class smtpscan (asynchat.async_chat):
'''class implementing the actual scan'''
def __init__ (self, address):
'''constuctor - opens connection'''
asynchat.async_chat.__init__ (self)
self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
self.set_terminator ('\r\n')
self.buffer = ''
self.host = address
self.timestamp = int(time.time())
self.resp = {}
self.awaiting = 'BANNER'
self.commands = [x for x in surveycommands]
self.done = 0
try:
self.connect((address, 25))
except:
self.handle_error()
self.close()
def handle_connect(self):
'''we have successfull connected'''
# ... and ignore this fact
pass
def handle_error(self):
'''print out error information to stderr'''
print >>sys.stderr, "ERROR:", self.host, sys.exc_info()[1]
def collect_incoming_data (self, data):
'''collect data which was recived on the socket'''
self.buffer = self.buffer + data
def found_terminator (self):
'''we have read a whole line and decide what do do next'''
data = self.buffer
self.buffer = ''
# update timestamp
self.timestamp = int(time.time())
# save response
if __debug__:
print "<<", self.host, data
if not self.resp.has_key(self.awaiting):
self.resp[self.awaiting] = data + '\n'
else:
self.resp[self.awaiting] += data + '\n'
# check if the server awaits a new command
if data[3] == ' ' and len(self.commands) > 0:
cmd = self.commands.pop(0)
self.awaiting = cmd.split(' ')[0]
self.push('%s\r\n' % (cmd))
if __debug__:
print ">>", self.host, cmd
def handle_close (self):
'''when the connection is closed use monitor() to start new connections'''
self.close()
if len(self.resp):
print "(%r, %r)" % (self.host, self.resp)
monitor()
# "main"
# use monitor() to fire up the number of connections we want
monitor()
# handle all the connection stuff
loop()