· 9 years ago · Jan 30, 2017, 08:36 PM
1'''
2http://pastebin.com/QUpNR1hb
338a11b99402ab435eb0bc53419bf278e582cb3c3361da5be1b8f69d3bf422470
4
5Welcome back to the resistance. We have another tool for you today.
6
7While we're all busy collecting hosts we thought it might be useful to increase
8the level of automation required for us to keep in touch. Following these keys
9is a pain, no?
10
11This script is called watchtower.py and it will enable us all to keep an eye on
12any pastes that we find interesting.
13
14Don't worry, we'll get back to walrus.db after enough information has been
15collected, but for now we encourage you to try out your new tool. Save this
16paste as watchtower.py and execute the following command:
17
18>>> python watchtower.py help
19
20This will output some basic usage details as follows:
21
22
23python watchtower.py CMD ARGS...
24
25Commands:
26 run -- Begin monitoring
27 help -- Show this
28 list -- List watched phrases
29 add "PHRASE" -- Add a new phrase to be watched
30 remove "PHRASE" -- Remove an existing phrase from being watched
31
32
33For instance, to begin waiting for the next step, use the following commands:
34
35>>> python watchtower.py add 8b09358a233181b4191bc9051323accc99a6d40bc9dcf2d9ac38ee688a26b21d
36>>> python watchtower.py run
37
38
39But feel free to use your new tool for other purposes as well. For instance,
40I'll personally be listening for this short key: 2ae819d1ba5ba04a
41
42You can contact me by including that in your paste (note that Untitled pastes
43are ignored so be sure to give your paste a title). If you'd like a response be
44sure to leave me a key that you're listening on.
45
46In the meantime, keep on collecting, there is work to do.
47'''
48
49try:
50 from bs4 import BeautifulSoup as Soup
51except:
52 print('bs4 (BeautifulSoup) module required:\npip install bs4')
53 exit()
54
55try:
56 from requests import get
57except:
58 print('requests module required:\npip install requests')
59 exit()
60
61from sys import argv
62from time import sleep
63from os import path, makedirs
64
65COMMANDS = {}
66DIRECTORY = './pastes'
67USER_AGENT = 'There must be some kind of way out of here'
68
69def main():
70 args = argv
71 script, args = args[0], args[1:]
72 if not len(args):
73 help()
74 cmd, args = args[0], args[1:]
75 cmd = cmd.replace('-', '').lower()
76 if cmd not in COMMANDS:
77 print('\nUnknown command: ' + cmd)
78 help()
79 COMMANDS[cmd](*args)
80
81def database():
82 '''
83 Return the sqlite db object.
84 '''
85 from sqlite3 import connect
86 db = connect('watchtower.db')
87 cursor = db.cursor()
88 cursor.execute('create table if not exists Phrases (phrase text)')
89 cursor.execute('''
90 create unique index if not exists idx_phrase on Phrases (phrase)
91 ''')
92 return db
93
94def command(name):
95 '''
96 Decorator for defining commands.
97 '''
98 def wrapper(fn):
99 COMMANDS[name] = fn
100 return fn
101 return wrapper
102
103@command('run')
104def run():
105 '''
106 Let's get this party started!
107 '''
108 if not path.exists(DIRECTORY):
109 makedirs(DIRECTORY)
110 last_key = None
111 try:
112 while True:
113 try:
114 last_key = update(last_key)
115 except KeyboardInterrupt as e:
116 raise e
117 except:
118 # Something weird happened... Wait a bit longer.
119 sleep(4)
120 sleep(1)
121 except KeyboardInterrupt:
122 pass
123
124def update(last_key):
125 '''
126 The main update function. Grabs pastes and looks for phrases.
127 '''
128 phrases = list_phrases(silent=True)
129 if len(phrases) == 0:
130 return last_key
131 next_key = None
132 headers = {'User-Agent': USER_AGENT}
133 pastes = recent_pastes()
134 for paste in pastes:
135 key = paste['key']
136 if next_key is None:
137 next_key = key
138 if last_key == key:
139 break
140 if paste['title'] == 'Untitled':
141 # Ignore Untitled pastes
142 continue
143 req = get('http://pastebin.com/raw/' + key, headers=headers)
144 text = req.text
145 # Phrase could be in title too, just combine these
146 title_text = paste['title'] + text
147 if any(phrase in title_text for phrase in phrases):
148 paste['text'] = text
149 keep(paste)
150 if next_key is None:
151 next_key = last_key
152 return next_key
153
154def keep(paste):
155 '''
156 Keep a paste.
157 '''
158 print(paste['key'])
159 filename = '{}_{}'.format(paste['key'], paste['title'])
160 fp = open(path.join(DIRECTORY, filename), 'wb')
161 fp.write(paste['text'].encode('utf8'))
162 fp.close()
163
164def recent_pastes():
165 '''
166 Grab list of recent pastes.
167 '''
168 headers = {'User-Agent': USER_AGENT}
169 req = get('http://pastebin.com', headers=headers)
170 soup = Soup(req.text, 'html.parser')
171 table = soup.find('div', {'id': 'menu_2'})
172 rows = table.findAll('li')
173 out = []
174 for row in rows:
175 a = row.find('a')
176 title = a.string
177 key = a['href'][1:]
178 out.append({'title': title, 'key': key})
179 return out
180
181@command('help')
182def help():
183 print('''
184python watchtower.py CMD ARGS...
185
186Commands:
187 run -- Begin monitoring
188 help -- Show this
189 list -- List watched phrases
190 add "PHRASE" -- Add a new phrase to be watched
191 remove "PHRASE" -- Remove an existing phrase from being watched
192''')
193 exit()
194
195@command('list')
196def list_phrases(silent=False):
197 db = database()
198 cursor = db.cursor()
199 cursor.execute('select phrase from Phrases')
200 out = []
201 for row in cursor:
202 if not silent:
203 print(row[0])
204 out.append(row[0])
205 return out
206
207@command('add')
208def add_phrase(*phrases):
209 db = database()
210 cursor = db.cursor()
211 for phrase in phrases:
212 cursor.execute('''
213 insert or ignore into Phrases (phrase) values (?)
214 ''', (phrase,))
215 db.commit()
216 list_phrases()
217
218@command('remove')
219def remove_phrase(*phrases):
220 db = database()
221 cursor = db.cursor()
222 for phrase in phrases:
223 cursor.execute('delete from Phrases where phrase = ?', (phrase,))
224 db.commit()
225 list_phrases()
226
227if __name__ == '__main__':
228 main()